LCOV - code coverage report
Current view: top level - fs/nfs - delegation.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 710 0.0 %
Date: 2022-04-01 14:58:12 Functions: 0 53 0.0 %
Branches: 0 354 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * linux/fs/nfs/delegation.c
       4                 :            :  *
       5                 :            :  * Copyright (C) 2004 Trond Myklebust
       6                 :            :  *
       7                 :            :  * NFS file delegation management
       8                 :            :  *
       9                 :            :  */
      10                 :            : #include <linux/completion.h>
      11                 :            : #include <linux/kthread.h>
      12                 :            : #include <linux/module.h>
      13                 :            : #include <linux/sched.h>
      14                 :            : #include <linux/slab.h>
      15                 :            : #include <linux/spinlock.h>
      16                 :            : #include <linux/iversion.h>
      17                 :            : 
      18                 :            : #include <linux/nfs4.h>
      19                 :            : #include <linux/nfs_fs.h>
      20                 :            : #include <linux/nfs_xdr.h>
      21                 :            : 
      22                 :            : #include "nfs4_fs.h"
      23                 :            : #include "nfs4session.h"
      24                 :            : #include "delegation.h"
      25                 :            : #include "internal.h"
      26                 :            : #include "nfs4trace.h"
      27                 :            : 
      28                 :            : #define NFS_DEFAULT_DELEGATION_WATERMARK (5000U)
      29                 :            : 
      30                 :            : static atomic_long_t nfs_active_delegations;
      31                 :            : static unsigned nfs_delegation_watermark = NFS_DEFAULT_DELEGATION_WATERMARK;
      32                 :            : 
      33                 :          0 : static void __nfs_free_delegation(struct nfs_delegation *delegation)
      34                 :            : {
      35                 :          0 :         put_cred(delegation->cred);
      36                 :          0 :         delegation->cred = NULL;
      37         [ #  # ]:          0 :         kfree_rcu(delegation, rcu);
      38                 :          0 : }
      39                 :            : 
      40                 :          0 : static void nfs_mark_delegation_revoked(struct nfs_delegation *delegation)
      41                 :            : {
      42         [ #  # ]:          0 :         if (!test_and_set_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
      43                 :          0 :                 delegation->stateid.type = NFS4_INVALID_STATEID_TYPE;
      44                 :          0 :                 atomic_long_dec(&nfs_active_delegations);
      45         [ #  # ]:          0 :                 if (!test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
      46                 :          0 :                         nfs_clear_verifier_delegated(delegation->inode);
      47                 :            :         }
      48                 :          0 : }
      49                 :            : 
      50                 :          0 : static struct nfs_delegation *nfs_get_delegation(struct nfs_delegation *delegation)
      51                 :            : {
      52                 :          0 :         refcount_inc(&delegation->refcount);
      53                 :          0 :         return delegation;
      54                 :            : }
      55                 :            : 
      56                 :          0 : static void nfs_put_delegation(struct nfs_delegation *delegation)
      57                 :            : {
      58         [ #  # ]:          0 :         if (refcount_dec_and_test(&delegation->refcount))
      59                 :          0 :                 __nfs_free_delegation(delegation);
      60                 :          0 : }
      61                 :            : 
      62                 :          0 : static void nfs_free_delegation(struct nfs_delegation *delegation)
      63                 :            : {
      64                 :          0 :         nfs_mark_delegation_revoked(delegation);
      65                 :          0 :         nfs_put_delegation(delegation);
      66                 :          0 : }
      67                 :            : 
      68                 :            : /**
      69                 :            :  * nfs_mark_delegation_referenced - set delegation's REFERENCED flag
      70                 :            :  * @delegation: delegation to process
      71                 :            :  *
      72                 :            :  */
      73                 :          0 : void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
      74                 :            : {
      75                 :          0 :         set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
      76                 :          0 : }
      77                 :            : 
      78                 :            : static bool
      79                 :          0 : nfs4_is_valid_delegation(const struct nfs_delegation *delegation,
      80                 :            :                 fmode_t flags)
      81                 :            : {
      82   [ #  #  #  #  :          0 :         if (delegation != NULL && (delegation->type & flags) == flags &&
                   #  # ]
      83         [ #  # ]:          0 :             !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) &&
      84                 :            :             !test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
      85                 :          0 :                 return true;
      86                 :            :         return false;
      87                 :            : }
      88                 :            : 
      89                 :          0 : struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode)
      90                 :            : {
      91                 :          0 :         struct nfs_delegation *delegation;
      92                 :            : 
      93                 :          0 :         delegation = rcu_dereference(NFS_I(inode)->delegation);
      94   [ #  #  #  #  :          0 :         if (nfs4_is_valid_delegation(delegation, 0))
             #  #  #  # ]
      95                 :          0 :                 return delegation;
      96                 :            :         return NULL;
      97                 :            : }
      98                 :            : 
      99                 :            : static int
     100                 :          0 : nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark)
     101                 :            : {
     102                 :          0 :         struct nfs_delegation *delegation;
     103                 :          0 :         int ret = 0;
     104                 :            : 
     105                 :          0 :         flags &= FMODE_READ|FMODE_WRITE;
     106                 :          0 :         rcu_read_lock();
     107                 :          0 :         delegation = rcu_dereference(NFS_I(inode)->delegation);
     108         [ #  # ]:          0 :         if (nfs4_is_valid_delegation(delegation, flags)) {
     109         [ #  # ]:          0 :                 if (mark)
     110                 :          0 :                         nfs_mark_delegation_referenced(delegation);
     111                 :            :                 ret = 1;
     112                 :            :         }
     113                 :          0 :         rcu_read_unlock();
     114                 :          0 :         return ret;
     115                 :            : }
     116                 :            : /**
     117                 :            :  * nfs_have_delegation - check if inode has a delegation, mark it
     118                 :            :  * NFS_DELEGATION_REFERENCED if there is one.
     119                 :            :  * @inode: inode to check
     120                 :            :  * @flags: delegation types to check for
     121                 :            :  *
     122                 :            :  * Returns one if inode has the indicated delegation, otherwise zero.
     123                 :            :  */
     124                 :          0 : int nfs4_have_delegation(struct inode *inode, fmode_t flags)
     125                 :            : {
     126                 :          0 :         return nfs4_do_check_delegation(inode, flags, true);
     127                 :            : }
     128                 :            : 
     129                 :            : /*
     130                 :            :  * nfs4_check_delegation - check if inode has a delegation, do not mark
     131                 :            :  * NFS_DELEGATION_REFERENCED if it has one.
     132                 :            :  */
     133                 :          0 : int nfs4_check_delegation(struct inode *inode, fmode_t flags)
     134                 :            : {
     135                 :          0 :         return nfs4_do_check_delegation(inode, flags, false);
     136                 :            : }
     137                 :            : 
     138                 :          0 : static int nfs_delegation_claim_locks(struct nfs4_state *state, const nfs4_stateid *stateid)
     139                 :            : {
     140                 :          0 :         struct inode *inode = state->inode;
     141                 :          0 :         struct file_lock *fl;
     142                 :          0 :         struct file_lock_context *flctx = inode->i_flctx;
     143                 :          0 :         struct list_head *list;
     144                 :          0 :         int status = 0;
     145                 :            : 
     146         [ #  # ]:          0 :         if (flctx == NULL)
     147                 :          0 :                 goto out;
     148                 :            : 
     149                 :          0 :         list = &flctx->flc_posix;
     150                 :          0 :         spin_lock(&flctx->flc_lock);
     151                 :          0 : restart:
     152         [ #  # ]:          0 :         list_for_each_entry(fl, list, fl_list) {
     153         [ #  # ]:          0 :                 if (nfs_file_open_context(fl->fl_file)->state != state)
     154                 :          0 :                         continue;
     155                 :          0 :                 spin_unlock(&flctx->flc_lock);
     156                 :          0 :                 status = nfs4_lock_delegation_recall(fl, state, stateid);
     157         [ #  # ]:          0 :                 if (status < 0)
     158                 :          0 :                         goto out;
     159                 :          0 :                 spin_lock(&flctx->flc_lock);
     160                 :            :         }
     161         [ #  # ]:          0 :         if (list == &flctx->flc_posix) {
     162                 :          0 :                 list = &flctx->flc_flock;
     163                 :          0 :                 goto restart;
     164                 :            :         }
     165                 :          0 :         spin_unlock(&flctx->flc_lock);
     166                 :          0 : out:
     167                 :          0 :         return status;
     168                 :            : }
     169                 :            : 
     170                 :            : static int nfs_delegation_claim_opens(struct inode *inode,
     171                 :            :                 const nfs4_stateid *stateid, fmode_t type)
     172                 :            : {
     173                 :            :         struct nfs_inode *nfsi = NFS_I(inode);
     174                 :            :         struct nfs_open_context *ctx;
     175                 :            :         struct nfs4_state_owner *sp;
     176                 :            :         struct nfs4_state *state;
     177                 :            :         unsigned int seq;
     178                 :            :         int err;
     179                 :            : 
     180                 :            : again:
     181                 :            :         rcu_read_lock();
     182                 :            :         list_for_each_entry_rcu(ctx, &nfsi->open_files, list) {
     183                 :            :                 state = ctx->state;
     184                 :            :                 if (state == NULL)
     185                 :            :                         continue;
     186                 :            :                 if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
     187                 :            :                         continue;
     188                 :            :                 if (!nfs4_valid_open_stateid(state))
     189                 :            :                         continue;
     190                 :            :                 if (!nfs4_stateid_match(&state->stateid, stateid))
     191                 :            :                         continue;
     192                 :            :                 if (!get_nfs_open_context(ctx))
     193                 :            :                         continue;
     194                 :            :                 rcu_read_unlock();
     195                 :            :                 sp = state->owner;
     196                 :            :                 /* Block nfs4_proc_unlck */
     197                 :            :                 mutex_lock(&sp->so_delegreturn_mutex);
     198                 :            :                 seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
     199                 :            :                 err = nfs4_open_delegation_recall(ctx, state, stateid);
     200                 :            :                 if (!err)
     201                 :            :                         err = nfs_delegation_claim_locks(state, stateid);
     202                 :            :                 if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
     203                 :            :                         err = -EAGAIN;
     204                 :            :                 mutex_unlock(&sp->so_delegreturn_mutex);
     205                 :            :                 put_nfs_open_context(ctx);
     206                 :            :                 if (err != 0)
     207                 :            :                         return err;
     208                 :            :                 goto again;
     209                 :            :         }
     210                 :            :         rcu_read_unlock();
     211                 :            :         return 0;
     212                 :            : }
     213                 :            : 
     214                 :            : /**
     215                 :            :  * nfs_inode_reclaim_delegation - process a delegation reclaim request
     216                 :            :  * @inode: inode to process
     217                 :            :  * @cred: credential to use for request
     218                 :            :  * @type: delegation type
     219                 :            :  * @stateid: delegation stateid
     220                 :            :  * @pagemod_limit: write delegation "space_limit"
     221                 :            :  *
     222                 :            :  */
     223                 :          0 : void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
     224                 :            :                                   fmode_t type,
     225                 :            :                                   const nfs4_stateid *stateid,
     226                 :            :                                   unsigned long pagemod_limit)
     227                 :            : {
     228                 :          0 :         struct nfs_delegation *delegation;
     229                 :          0 :         const struct cred *oldcred = NULL;
     230                 :            : 
     231                 :          0 :         rcu_read_lock();
     232         [ #  # ]:          0 :         delegation = rcu_dereference(NFS_I(inode)->delegation);
     233         [ #  # ]:          0 :         if (delegation != NULL) {
     234                 :          0 :                 spin_lock(&delegation->lock);
     235         [ #  # ]:          0 :                 if (nfs4_is_valid_delegation(delegation, 0)) {
     236         [ #  # ]:          0 :                         nfs4_stateid_copy(&delegation->stateid, stateid);
     237                 :          0 :                         delegation->type = type;
     238                 :          0 :                         delegation->pagemod_limit = pagemod_limit;
     239                 :          0 :                         oldcred = delegation->cred;
     240         [ #  # ]:          0 :                         delegation->cred = get_cred(cred);
     241                 :          0 :                         clear_bit(NFS_DELEGATION_NEED_RECLAIM,
     242                 :          0 :                                   &delegation->flags);
     243                 :          0 :                         spin_unlock(&delegation->lock);
     244                 :          0 :                         rcu_read_unlock();
     245                 :          0 :                         put_cred(oldcred);
     246                 :          0 :                         trace_nfs4_reclaim_delegation(inode, type);
     247                 :          0 :                         return;
     248                 :            :                 }
     249                 :            :                 /* We appear to have raced with a delegation return. */
     250                 :          0 :                 spin_unlock(&delegation->lock);
     251                 :            :         }
     252                 :          0 :         rcu_read_unlock();
     253                 :          0 :         nfs_inode_set_delegation(inode, cred, type, stateid, pagemod_limit);
     254                 :            : }
     255                 :            : 
     256                 :          0 : static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
     257                 :            : {
     258                 :          0 :         const struct cred *cred;
     259                 :          0 :         int res = 0;
     260                 :            : 
     261         [ #  # ]:          0 :         if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
     262                 :          0 :                 spin_lock(&delegation->lock);
     263         [ #  # ]:          0 :                 cred = get_cred(delegation->cred);
     264                 :          0 :                 spin_unlock(&delegation->lock);
     265                 :          0 :                 res = nfs4_proc_delegreturn(inode, cred,
     266                 :          0 :                                 &delegation->stateid,
     267                 :            :                                 issync);
     268                 :          0 :                 put_cred(cred);
     269                 :            :         }
     270                 :          0 :         return res;
     271                 :            : }
     272                 :            : 
     273                 :          0 : static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation)
     274                 :            : {
     275                 :          0 :         struct inode *inode = NULL;
     276                 :            : 
     277                 :          0 :         spin_lock(&delegation->lock);
     278         [ #  # ]:          0 :         if (delegation->inode != NULL)
     279                 :          0 :                 inode = igrab(delegation->inode);
     280         [ #  # ]:          0 :         if (!inode)
     281                 :          0 :                 set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags);
     282                 :          0 :         spin_unlock(&delegation->lock);
     283                 :          0 :         return inode;
     284                 :            : }
     285                 :            : 
     286                 :            : static struct nfs_delegation *
     287                 :          0 : nfs_start_delegation_return_locked(struct nfs_inode *nfsi)
     288                 :            : {
     289                 :          0 :         struct nfs_delegation *ret = NULL;
     290         [ #  # ]:          0 :         struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
     291                 :            : 
     292         [ #  # ]:          0 :         if (delegation == NULL)
     293                 :          0 :                 goto out;
     294                 :          0 :         spin_lock(&delegation->lock);
     295         [ #  # ]:          0 :         if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
     296                 :            :                 /* Refcount matched in nfs_end_delegation_return() */
     297                 :          0 :                 ret = nfs_get_delegation(delegation);
     298                 :            :         }
     299                 :          0 :         spin_unlock(&delegation->lock);
     300         [ #  # ]:          0 :         if (ret)
     301                 :          0 :                 nfs_clear_verifier_delegated(&nfsi->vfs_inode);
     302                 :          0 : out:
     303                 :          0 :         return ret;
     304                 :            : }
     305                 :            : 
     306                 :            : static struct nfs_delegation *
     307                 :          0 : nfs_start_delegation_return(struct nfs_inode *nfsi)
     308                 :            : {
     309                 :          0 :         struct nfs_delegation *delegation;
     310                 :            : 
     311                 :          0 :         rcu_read_lock();
     312                 :          0 :         delegation = nfs_start_delegation_return_locked(nfsi);
     313                 :          0 :         rcu_read_unlock();
     314                 :          0 :         return delegation;
     315                 :            : }
     316                 :            : 
     317                 :            : static void
     318                 :          0 : nfs_abort_delegation_return(struct nfs_delegation *delegation,
     319                 :            :                 struct nfs_client *clp)
     320                 :            : {
     321                 :            : 
     322                 :          0 :         spin_lock(&delegation->lock);
     323                 :          0 :         clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
     324                 :          0 :         set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
     325                 :          0 :         spin_unlock(&delegation->lock);
     326                 :          0 :         set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
     327                 :          0 : }
     328                 :            : 
     329                 :            : static struct nfs_delegation *
     330                 :            : nfs_detach_delegation_locked(struct nfs_inode *nfsi,
     331                 :            :                 struct nfs_delegation *delegation,
     332                 :            :                 struct nfs_client *clp)
     333                 :            : {
     334                 :            :         struct nfs_delegation *deleg_cur =
     335                 :            :                 rcu_dereference_protected(nfsi->delegation,
     336                 :            :                                 lockdep_is_held(&clp->cl_lock));
     337                 :            : 
     338                 :            :         if (deleg_cur == NULL || delegation != deleg_cur)
     339                 :            :                 return NULL;
     340                 :            : 
     341                 :            :         spin_lock(&delegation->lock);
     342                 :            :         if (!delegation->inode) {
     343                 :            :                 spin_unlock(&delegation->lock);
     344                 :            :                 return NULL;
     345                 :            :         }
     346                 :            :         list_del_rcu(&delegation->super_list);
     347                 :            :         delegation->inode = NULL;
     348                 :            :         rcu_assign_pointer(nfsi->delegation, NULL);
     349                 :            :         spin_unlock(&delegation->lock);
     350                 :            :         return delegation;
     351                 :            : }
     352                 :            : 
     353                 :          0 : static struct nfs_delegation *nfs_detach_delegation(struct nfs_inode *nfsi,
     354                 :            :                 struct nfs_delegation *delegation,
     355                 :            :                 struct nfs_server *server)
     356                 :            : {
     357                 :          0 :         struct nfs_client *clp = server->nfs_client;
     358                 :            : 
     359                 :          0 :         spin_lock(&clp->cl_lock);
     360                 :          0 :         delegation = nfs_detach_delegation_locked(nfsi, delegation, clp);
     361                 :          0 :         spin_unlock(&clp->cl_lock);
     362                 :          0 :         return delegation;
     363                 :            : }
     364                 :            : 
     365                 :            : static struct nfs_delegation *
     366                 :          0 : nfs_inode_detach_delegation(struct inode *inode)
     367                 :            : {
     368                 :          0 :         struct nfs_inode *nfsi = NFS_I(inode);
     369                 :          0 :         struct nfs_server *server = NFS_SERVER(inode);
     370                 :          0 :         struct nfs_delegation *delegation;
     371                 :            : 
     372                 :          0 :         rcu_read_lock();
     373         [ #  # ]:          0 :         delegation = rcu_dereference(nfsi->delegation);
     374         [ #  # ]:          0 :         if (delegation != NULL)
     375                 :          0 :                 delegation = nfs_detach_delegation(nfsi, delegation, server);
     376                 :          0 :         rcu_read_unlock();
     377                 :          0 :         return delegation;
     378                 :            : }
     379                 :            : 
     380                 :            : static void
     381                 :          0 : nfs_update_inplace_delegation(struct nfs_delegation *delegation,
     382                 :            :                 const struct nfs_delegation *update)
     383                 :            : {
     384         [ #  # ]:          0 :         if (nfs4_stateid_is_newer(&update->stateid, &delegation->stateid)) {
     385                 :          0 :                 delegation->stateid.seqid = update->stateid.seqid;
     386                 :          0 :                 smp_wmb();
     387                 :          0 :                 delegation->type = update->type;
     388         [ #  # ]:          0 :                 if (test_and_clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
     389                 :          0 :                         atomic_long_inc(&nfs_active_delegations);
     390                 :            :         }
     391                 :          0 : }
     392                 :            : 
     393                 :            : /**
     394                 :            :  * nfs_inode_set_delegation - set up a delegation on an inode
     395                 :            :  * @inode: inode to which delegation applies
     396                 :            :  * @cred: cred to use for subsequent delegation processing
     397                 :            :  * @type: delegation type
     398                 :            :  * @stateid: delegation stateid
     399                 :            :  * @pagemod_limit: write delegation "space_limit"
     400                 :            :  *
     401                 :            :  * Returns zero on success, or a negative errno value.
     402                 :            :  */
     403                 :          0 : int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
     404                 :            :                                   fmode_t type,
     405                 :            :                                   const nfs4_stateid *stateid,
     406                 :            :                                   unsigned long pagemod_limit)
     407                 :            : {
     408                 :          0 :         struct nfs_server *server = NFS_SERVER(inode);
     409                 :          0 :         struct nfs_client *clp = server->nfs_client;
     410                 :          0 :         struct nfs_inode *nfsi = NFS_I(inode);
     411                 :          0 :         struct nfs_delegation *delegation, *old_delegation;
     412                 :          0 :         struct nfs_delegation *freeme = NULL;
     413                 :          0 :         int status = 0;
     414                 :            : 
     415                 :          0 :         delegation = kmalloc(sizeof(*delegation), GFP_NOFS);
     416         [ #  # ]:          0 :         if (delegation == NULL)
     417                 :            :                 return -ENOMEM;
     418                 :          0 :         nfs4_stateid_copy(&delegation->stateid, stateid);
     419                 :          0 :         refcount_set(&delegation->refcount, 1);
     420                 :          0 :         delegation->type = type;
     421                 :          0 :         delegation->pagemod_limit = pagemod_limit;
     422                 :          0 :         delegation->change_attr = inode_peek_iversion_raw(inode);
     423         [ #  # ]:          0 :         delegation->cred = get_cred(cred);
     424                 :          0 :         delegation->inode = inode;
     425                 :          0 :         delegation->flags = 1<<NFS_DELEGATION_REFERENCED;
     426                 :          0 :         spin_lock_init(&delegation->lock);
     427                 :            : 
     428                 :          0 :         spin_lock(&clp->cl_lock);
     429                 :          0 :         old_delegation = rcu_dereference_protected(nfsi->delegation,
     430                 :            :                                         lockdep_is_held(&clp->cl_lock));
     431         [ #  # ]:          0 :         if (old_delegation == NULL)
     432                 :          0 :                 goto add_new;
     433                 :            :         /* Is this an update of the existing delegation? */
     434         [ #  # ]:          0 :         if (nfs4_stateid_match_other(&old_delegation->stateid,
     435                 :            :                                 &delegation->stateid)) {
     436                 :          0 :                 spin_lock(&old_delegation->lock);
     437                 :          0 :                 nfs_update_inplace_delegation(old_delegation,
     438                 :            :                                 delegation);
     439                 :          0 :                 spin_unlock(&old_delegation->lock);
     440                 :          0 :                 goto out;
     441                 :            :         }
     442         [ #  # ]:          0 :         if (!test_bit(NFS_DELEGATION_REVOKED, &old_delegation->flags)) {
     443                 :            :                 /*
     444                 :            :                  * Deal with broken servers that hand out two
     445                 :            :                  * delegations for the same file.
     446                 :            :                  * Allow for upgrades to a WRITE delegation, but
     447                 :            :                  * nothing else.
     448                 :            :                  */
     449                 :          0 :                 dfprintk(FILE, "%s: server %s handed out "
     450                 :            :                                 "a duplicate delegation!\n",
     451                 :            :                                 __func__, clp->cl_hostname);
     452         [ #  # ]:          0 :                 if (delegation->type == old_delegation->type ||
     453         [ #  # ]:          0 :                     !(delegation->type & FMODE_WRITE)) {
     454                 :          0 :                         freeme = delegation;
     455                 :          0 :                         delegation = NULL;
     456                 :          0 :                         goto out;
     457                 :            :                 }
     458         [ #  # ]:          0 :                 if (test_and_set_bit(NFS_DELEGATION_RETURNING,
     459                 :            :                                         &old_delegation->flags))
     460                 :          0 :                         goto out;
     461                 :            :         }
     462                 :          0 :         freeme = nfs_detach_delegation_locked(nfsi, old_delegation, clp);
     463         [ #  # ]:          0 :         if (freeme == NULL)
     464                 :          0 :                 goto out;
     465                 :          0 : add_new:
     466                 :          0 :         list_add_tail_rcu(&delegation->super_list, &server->delegations);
     467                 :          0 :         rcu_assign_pointer(nfsi->delegation, delegation);
     468                 :          0 :         delegation = NULL;
     469                 :            : 
     470                 :          0 :         atomic_long_inc(&nfs_active_delegations);
     471                 :            : 
     472                 :          0 :         trace_nfs4_set_delegation(inode, type);
     473                 :            : 
     474                 :          0 :         spin_lock(&inode->i_lock);
     475         [ #  # ]:          0 :         if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME))
     476                 :          0 :                 NFS_I(inode)->cache_validity |= NFS_INO_REVAL_FORCED;
     477                 :          0 :         spin_unlock(&inode->i_lock);
     478                 :          0 : out:
     479                 :          0 :         spin_unlock(&clp->cl_lock);
     480         [ #  # ]:          0 :         if (delegation != NULL)
     481                 :          0 :                 __nfs_free_delegation(delegation);
     482         [ #  # ]:          0 :         if (freeme != NULL) {
     483                 :          0 :                 nfs_do_return_delegation(inode, freeme, 0);
     484                 :          0 :                 nfs_free_delegation(freeme);
     485                 :            :         }
     486                 :            :         return status;
     487                 :            : }
     488                 :            : 
     489                 :            : /*
     490                 :            :  * Basic procedure for returning a delegation to the server
     491                 :            :  */
     492                 :          0 : static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync)
     493                 :            : {
     494         [ #  # ]:          0 :         struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
     495                 :          0 :         int err = 0;
     496                 :            : 
     497         [ #  # ]:          0 :         if (delegation == NULL)
     498                 :            :                 return 0;
     499                 :          0 :         do {
     500         [ #  # ]:          0 :                 if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
     501                 :            :                         break;
     502                 :          0 :                 err = nfs_delegation_claim_opens(inode, &delegation->stateid,
     503                 :            :                                 delegation->type);
     504         [ #  # ]:          0 :                 if (!issync || err != -EAGAIN)
     505                 :            :                         break;
     506                 :            :                 /*
     507                 :            :                  * Guard against state recovery
     508                 :            :                  */
     509                 :          0 :                 err = nfs4_wait_clnt_recover(clp);
     510         [ #  # ]:          0 :         } while (err == 0);
     511                 :            : 
     512         [ #  # ]:          0 :         if (err) {
     513                 :          0 :                 nfs_abort_delegation_return(delegation, clp);
     514                 :          0 :                 goto out;
     515                 :            :         }
     516                 :            : 
     517                 :          0 :         err = nfs_do_return_delegation(inode, delegation, issync);
     518                 :          0 : out:
     519                 :            :         /* Refcount matched in nfs_start_delegation_return_locked() */
     520                 :          0 :         nfs_put_delegation(delegation);
     521                 :          0 :         return err;
     522                 :            : }
     523                 :            : 
     524                 :          0 : static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
     525                 :            : {
     526                 :          0 :         bool ret = false;
     527                 :            : 
     528         [ #  # ]:          0 :         if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
     529                 :            :                 ret = true;
     530         [ #  # ]:          0 :         else if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) {
     531                 :          0 :                 struct inode *inode;
     532                 :            : 
     533                 :          0 :                 spin_lock(&delegation->lock);
     534                 :          0 :                 inode = delegation->inode;
     535   [ #  #  #  # ]:          0 :                 if (inode && list_empty(&NFS_I(inode)->open_files))
     536                 :          0 :                         ret = true;
     537                 :          0 :                 spin_unlock(&delegation->lock);
     538                 :            :         }
     539         [ #  # ]:          0 :         if (ret)
     540                 :          0 :                 clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
     541   [ #  #  #  # ]:          0 :         if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags) ||
     542                 :            :             test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
     543                 :            :                 ret = false;
     544                 :            : 
     545                 :          0 :         return ret;
     546                 :            : }
     547                 :            : 
     548                 :            : /**
     549                 :            :  * nfs_client_return_marked_delegations - return previously marked delegations
     550                 :            :  * @clp: nfs_client to process
     551                 :            :  *
     552                 :            :  * Note that this function is designed to be called by the state
     553                 :            :  * manager thread. For this reason, it cannot flush the dirty data,
     554                 :            :  * since that could deadlock in case of a state recovery error.
     555                 :            :  *
     556                 :            :  * Returns zero on success, or a negative errno value.
     557                 :            :  */
     558                 :          0 : int nfs_client_return_marked_delegations(struct nfs_client *clp)
     559                 :            : {
     560                 :          0 :         struct nfs_delegation *delegation;
     561                 :          0 :         struct nfs_delegation *prev;
     562                 :          0 :         struct nfs_server *server;
     563                 :          0 :         struct inode *inode;
     564                 :          0 :         struct inode *place_holder = NULL;
     565                 :          0 :         struct nfs_delegation *place_holder_deleg = NULL;
     566                 :          0 :         int err = 0;
     567                 :            : 
     568                 :            : restart:
     569                 :            :         /*
     570                 :            :          * To avoid quadratic looping we hold a reference
     571                 :            :          * to an inode place_holder.  Each time we restart, we
     572                 :            :          * list nfs_servers from the server of that inode, and
     573                 :            :          * delegation in the server from the delegations of that
     574                 :            :          * inode.
     575                 :            :          * prev is an RCU-protected pointer to a delegation which
     576                 :            :          * wasn't marked for return and might be a good choice for
     577                 :            :          * the next place_holder.
     578                 :            :          */
     579                 :          0 :         rcu_read_lock();
     580                 :          0 :         prev = NULL;
     581         [ #  # ]:          0 :         if (place_holder)
     582                 :          0 :                 server = NFS_SERVER(place_holder);
     583                 :            :         else
     584                 :          0 :                 server = list_entry_rcu(clp->cl_superblocks.next,
     585                 :            :                                         struct nfs_server, client_link);
     586         [ #  # ]:          0 :         list_for_each_entry_from_rcu(server, &clp->cl_superblocks, client_link) {
     587                 :          0 :                 delegation = NULL;
     588   [ #  #  #  # ]:          0 :                 if (place_holder && server == NFS_SERVER(place_holder))
     589                 :          0 :                         delegation = rcu_dereference(NFS_I(place_holder)->delegation);
     590         [ #  # ]:          0 :                 if (!delegation || delegation != place_holder_deleg)
     591                 :          0 :                         delegation = list_entry_rcu(server->delegations.next,
     592                 :            :                                                     struct nfs_delegation, super_list);
     593         [ #  # ]:          0 :                 list_for_each_entry_from_rcu(delegation, &server->delegations, super_list) {
     594                 :          0 :                         struct inode *to_put = NULL;
     595                 :            : 
     596         [ #  # ]:          0 :                         if (!nfs_delegation_need_return(delegation)) {
     597                 :          0 :                                 prev = delegation;
     598                 :          0 :                                 continue;
     599                 :            :                         }
     600         [ #  # ]:          0 :                         if (!nfs_sb_active(server->super))
     601                 :            :                                 break; /* continue in outer loop */
     602                 :            : 
     603         [ #  # ]:          0 :                         if (prev) {
     604                 :          0 :                                 struct inode *tmp;
     605                 :            : 
     606                 :          0 :                                 tmp = nfs_delegation_grab_inode(prev);
     607         [ #  # ]:          0 :                                 if (tmp) {
     608                 :          0 :                                         to_put = place_holder;
     609                 :          0 :                                         place_holder = tmp;
     610                 :          0 :                                         place_holder_deleg = prev;
     611                 :            :                                 }
     612                 :            :                         }
     613                 :            : 
     614                 :          0 :                         inode = nfs_delegation_grab_inode(delegation);
     615         [ #  # ]:          0 :                         if (inode == NULL) {
     616                 :          0 :                                 rcu_read_unlock();
     617         [ #  # ]:          0 :                                 if (to_put)
     618                 :          0 :                                         iput(to_put);
     619                 :          0 :                                 nfs_sb_deactive(server->super);
     620                 :          0 :                                 goto restart;
     621                 :            :                         }
     622                 :          0 :                         delegation = nfs_start_delegation_return_locked(NFS_I(inode));
     623                 :          0 :                         rcu_read_unlock();
     624                 :            : 
     625         [ #  # ]:          0 :                         if (to_put)
     626                 :          0 :                                 iput(to_put);
     627                 :            : 
     628                 :          0 :                         err = nfs_end_delegation_return(inode, delegation, 0);
     629                 :          0 :                         iput(inode);
     630                 :          0 :                         nfs_sb_deactive(server->super);
     631                 :          0 :                         cond_resched();
     632         [ #  # ]:          0 :                         if (!err)
     633                 :          0 :                                 goto restart;
     634                 :          0 :                         set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
     635         [ #  # ]:          0 :                         if (place_holder)
     636                 :          0 :                                 iput(place_holder);
     637                 :            :                         return err;
     638                 :            :                 }
     639                 :            :         }
     640                 :          0 :         rcu_read_unlock();
     641         [ #  # ]:          0 :         if (place_holder)
     642                 :          0 :                 iput(place_holder);
     643                 :            :         return 0;
     644                 :            : }
     645                 :            : 
     646                 :            : /**
     647                 :            :  * nfs_inode_evict_delegation - return delegation, don't reclaim opens
     648                 :            :  * @inode: inode to process
     649                 :            :  *
     650                 :            :  * Does not protect against delegation reclaims, therefore really only safe
     651                 :            :  * to be called from nfs4_clear_inode(). Guaranteed to always free
     652                 :            :  * the delegation structure.
     653                 :            :  */
     654                 :          0 : void nfs_inode_evict_delegation(struct inode *inode)
     655                 :            : {
     656                 :          0 :         struct nfs_delegation *delegation;
     657                 :            : 
     658                 :          0 :         delegation = nfs_inode_detach_delegation(inode);
     659         [ #  # ]:          0 :         if (delegation != NULL) {
     660                 :          0 :                 set_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
     661                 :          0 :                 set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags);
     662                 :          0 :                 nfs_do_return_delegation(inode, delegation, 1);
     663                 :          0 :                 nfs_free_delegation(delegation);
     664                 :            :         }
     665                 :          0 : }
     666                 :            : 
     667                 :            : /**
     668                 :            :  * nfs_inode_return_delegation - synchronously return a delegation
     669                 :            :  * @inode: inode to process
     670                 :            :  *
     671                 :            :  * This routine will always flush any dirty data to disk on the
     672                 :            :  * assumption that if we need to return the delegation, then
     673                 :            :  * we should stop caching.
     674                 :            :  *
     675                 :            :  * Returns zero on success, or a negative errno value.
     676                 :            :  */
     677                 :          0 : int nfs4_inode_return_delegation(struct inode *inode)
     678                 :            : {
     679                 :          0 :         struct nfs_inode *nfsi = NFS_I(inode);
     680                 :          0 :         struct nfs_delegation *delegation;
     681                 :          0 :         int err = 0;
     682                 :            : 
     683                 :          0 :         nfs_wb_all(inode);
     684                 :          0 :         delegation = nfs_start_delegation_return(nfsi);
     685         [ #  # ]:          0 :         if (delegation != NULL)
     686                 :          0 :                 err = nfs_end_delegation_return(inode, delegation, 1);
     687                 :          0 :         return err;
     688                 :            : }
     689                 :            : 
     690                 :            : /**
     691                 :            :  * nfs_inode_return_delegation_on_close - asynchronously return a delegation
     692                 :            :  * @inode: inode to process
     693                 :            :  *
     694                 :            :  * This routine is called on file close in order to determine if the
     695                 :            :  * inode delegation needs to be returned immediately.
     696                 :            :  */
     697                 :          0 : void nfs4_inode_return_delegation_on_close(struct inode *inode)
     698                 :            : {
     699                 :          0 :         struct nfs_delegation *delegation;
     700                 :          0 :         struct nfs_delegation *ret = NULL;
     701                 :            : 
     702         [ #  # ]:          0 :         if (!inode)
     703                 :            :                 return;
     704                 :          0 :         rcu_read_lock();
     705                 :          0 :         delegation = nfs4_get_valid_delegation(inode);
     706         [ #  # ]:          0 :         if (!delegation)
     707                 :          0 :                 goto out;
     708         [ #  # ]:          0 :         if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) ||
     709         [ #  # ]:          0 :             atomic_long_read(&nfs_active_delegations) >= nfs_delegation_watermark) {
     710                 :          0 :                 spin_lock(&delegation->lock);
     711   [ #  #  #  # ]:          0 :                 if (delegation->inode &&
     712   [ #  #  #  # ]:          0 :                     list_empty(&NFS_I(inode)->open_files) &&
     713                 :          0 :                     !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
     714                 :          0 :                         clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
     715                 :            :                         /* Refcount matched in nfs_end_delegation_return() */
     716                 :          0 :                         ret = nfs_get_delegation(delegation);
     717                 :            :                 }
     718                 :          0 :                 spin_unlock(&delegation->lock);
     719         [ #  # ]:          0 :                 if (ret)
     720                 :          0 :                         nfs_clear_verifier_delegated(inode);
     721                 :            :         }
     722                 :          0 : out:
     723                 :          0 :         rcu_read_unlock();
     724                 :          0 :         nfs_end_delegation_return(inode, ret, 0);
     725                 :            : }
     726                 :            : 
     727                 :            : /**
     728                 :            :  * nfs4_inode_make_writeable
     729                 :            :  * @inode: pointer to inode
     730                 :            :  *
     731                 :            :  * Make the inode writeable by returning the delegation if necessary
     732                 :            :  *
     733                 :            :  * Returns zero on success, or a negative errno value.
     734                 :            :  */
     735                 :          0 : int nfs4_inode_make_writeable(struct inode *inode)
     736                 :            : {
     737                 :          0 :         struct nfs_delegation *delegation;
     738                 :            : 
     739                 :          0 :         rcu_read_lock();
     740                 :          0 :         delegation = nfs4_get_valid_delegation(inode);
     741         [ #  # ]:          0 :         if (delegation == NULL ||
     742                 :            :             (nfs4_has_session(NFS_SERVER(inode)->nfs_client) &&
     743                 :            :              (delegation->type & FMODE_WRITE))) {
     744                 :          0 :                 rcu_read_unlock();
     745                 :          0 :                 return 0;
     746                 :            :         }
     747                 :          0 :         rcu_read_unlock();
     748                 :          0 :         return nfs4_inode_return_delegation(inode);
     749                 :            : }
     750                 :            : 
     751                 :          0 : static void nfs_mark_return_if_closed_delegation(struct nfs_server *server,
     752                 :            :                 struct nfs_delegation *delegation)
     753                 :            : {
     754                 :          0 :         set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
     755                 :          0 :         set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
     756                 :          0 : }
     757                 :            : 
     758                 :          0 : static void nfs_mark_return_delegation(struct nfs_server *server,
     759                 :            :                 struct nfs_delegation *delegation)
     760                 :            : {
     761                 :          0 :         set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
     762                 :          0 :         set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
     763                 :            : }
     764                 :            : 
     765                 :          0 : static bool nfs_server_mark_return_all_delegations(struct nfs_server *server)
     766                 :            : {
     767                 :          0 :         struct nfs_delegation *delegation;
     768                 :          0 :         bool ret = false;
     769                 :            : 
     770         [ #  # ]:          0 :         list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
     771                 :          0 :                 nfs_mark_return_delegation(server, delegation);
     772                 :          0 :                 ret = true;
     773                 :            :         }
     774                 :          0 :         return ret;
     775                 :            : }
     776                 :            : 
     777                 :          0 : static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
     778                 :            : {
     779                 :          0 :         struct nfs_server *server;
     780                 :            : 
     781                 :          0 :         rcu_read_lock();
     782         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
     783                 :          0 :                 nfs_server_mark_return_all_delegations(server);
     784                 :          0 :         rcu_read_unlock();
     785                 :          0 : }
     786                 :            : 
     787                 :          0 : static void nfs_delegation_run_state_manager(struct nfs_client *clp)
     788                 :            : {
     789         [ #  # ]:          0 :         if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
     790                 :          0 :                 nfs4_schedule_state_manager(clp);
     791                 :          0 : }
     792                 :            : 
     793                 :            : /**
     794                 :            :  * nfs_expire_all_delegations
     795                 :            :  * @clp: client to process
     796                 :            :  *
     797                 :            :  */
     798                 :          0 : void nfs_expire_all_delegations(struct nfs_client *clp)
     799                 :            : {
     800                 :          0 :         nfs_client_mark_return_all_delegations(clp);
     801                 :          0 :         nfs_delegation_run_state_manager(clp);
     802                 :          0 : }
     803                 :            : 
     804                 :            : /**
     805                 :            :  * nfs_super_return_all_delegations - return delegations for one superblock
     806                 :            :  * @server: pointer to nfs_server to process
     807                 :            :  *
     808                 :            :  */
     809                 :          0 : void nfs_server_return_all_delegations(struct nfs_server *server)
     810                 :            : {
     811                 :          0 :         struct nfs_client *clp = server->nfs_client;
     812                 :          0 :         bool need_wait;
     813                 :            : 
     814         [ #  # ]:          0 :         if (clp == NULL)
     815                 :            :                 return;
     816                 :            : 
     817                 :          0 :         rcu_read_lock();
     818                 :          0 :         need_wait = nfs_server_mark_return_all_delegations(server);
     819                 :          0 :         rcu_read_unlock();
     820                 :            : 
     821         [ #  # ]:          0 :         if (need_wait) {
     822                 :          0 :                 nfs4_schedule_state_manager(clp);
     823                 :          0 :                 nfs4_wait_clnt_recover(clp);
     824                 :            :         }
     825                 :            : }
     826                 :            : 
     827                 :          0 : static void nfs_mark_return_unused_delegation_types(struct nfs_server *server,
     828                 :            :                                                  fmode_t flags)
     829                 :            : {
     830                 :          0 :         struct nfs_delegation *delegation;
     831                 :            : 
     832         [ #  # ]:          0 :         list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
     833   [ #  #  #  # ]:          0 :                 if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
     834                 :          0 :                         continue;
     835         [ #  # ]:          0 :                 if (delegation->type & flags)
     836                 :          0 :                         nfs_mark_return_if_closed_delegation(server, delegation);
     837                 :            :         }
     838                 :          0 : }
     839                 :            : 
     840                 :          0 : static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *clp,
     841                 :            :                                                         fmode_t flags)
     842                 :            : {
     843                 :          0 :         struct nfs_server *server;
     844                 :            : 
     845                 :          0 :         rcu_read_lock();
     846         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
     847                 :          0 :                 nfs_mark_return_unused_delegation_types(server, flags);
     848                 :          0 :         rcu_read_unlock();
     849                 :          0 : }
     850                 :            : 
     851                 :          0 : static void nfs_revoke_delegation(struct inode *inode,
     852                 :            :                 const nfs4_stateid *stateid)
     853                 :            : {
     854                 :          0 :         struct nfs_delegation *delegation;
     855                 :          0 :         nfs4_stateid tmp;
     856                 :          0 :         bool ret = false;
     857                 :            : 
     858                 :          0 :         rcu_read_lock();
     859         [ #  # ]:          0 :         delegation = rcu_dereference(NFS_I(inode)->delegation);
     860         [ #  # ]:          0 :         if (delegation == NULL)
     861                 :          0 :                 goto out;
     862         [ #  # ]:          0 :         if (stateid == NULL) {
     863                 :          0 :                 nfs4_stateid_copy(&tmp, &delegation->stateid);
     864                 :          0 :                 stateid = &tmp;
     865                 :            :         } else {
     866         [ #  # ]:          0 :                 if (!nfs4_stateid_match_other(stateid, &delegation->stateid))
     867                 :          0 :                         goto out;
     868                 :          0 :                 spin_lock(&delegation->lock);
     869         [ #  # ]:          0 :                 if (stateid->seqid) {
     870         [ #  # ]:          0 :                         if (nfs4_stateid_is_newer(&delegation->stateid, stateid)) {
     871                 :          0 :                                 spin_unlock(&delegation->lock);
     872                 :          0 :                                 goto out;
     873                 :            :                         }
     874                 :          0 :                         delegation->stateid.seqid = stateid->seqid;
     875                 :            :                 }
     876                 :          0 :                 spin_unlock(&delegation->lock);
     877                 :            :         }
     878                 :          0 :         nfs_mark_delegation_revoked(delegation);
     879                 :          0 :         ret = true;
     880                 :          0 : out:
     881                 :          0 :         rcu_read_unlock();
     882         [ #  # ]:          0 :         if (ret)
     883                 :          0 :                 nfs_inode_find_state_and_recover(inode, stateid);
     884                 :          0 : }
     885                 :            : 
     886                 :          0 : void nfs_remove_bad_delegation(struct inode *inode,
     887                 :            :                 const nfs4_stateid *stateid)
     888                 :            : {
     889                 :          0 :         nfs_revoke_delegation(inode, stateid);
     890                 :          0 : }
     891                 :            : EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
     892                 :            : 
     893                 :          0 : void nfs_delegation_mark_returned(struct inode *inode,
     894                 :            :                 const nfs4_stateid *stateid)
     895                 :            : {
     896                 :          0 :         struct nfs_delegation *delegation;
     897                 :            : 
     898         [ #  # ]:          0 :         if (!inode)
     899                 :            :                 return;
     900                 :            : 
     901                 :          0 :         rcu_read_lock();
     902         [ #  # ]:          0 :         delegation = rcu_dereference(NFS_I(inode)->delegation);
     903         [ #  # ]:          0 :         if (!delegation)
     904                 :          0 :                 goto out_rcu_unlock;
     905                 :            : 
     906                 :          0 :         spin_lock(&delegation->lock);
     907         [ #  # ]:          0 :         if (!nfs4_stateid_match_other(stateid, &delegation->stateid))
     908                 :          0 :                 goto out_spin_unlock;
     909         [ #  # ]:          0 :         if (stateid->seqid) {
     910                 :            :                 /* If delegation->stateid is newer, dont mark as returned */
     911         [ #  # ]:          0 :                 if (nfs4_stateid_is_newer(&delegation->stateid, stateid))
     912                 :          0 :                         goto out_clear_returning;
     913         [ #  # ]:          0 :                 if (delegation->stateid.seqid != stateid->seqid)
     914                 :          0 :                         delegation->stateid.seqid = stateid->seqid;
     915                 :            :         }
     916                 :            : 
     917                 :          0 :         nfs_mark_delegation_revoked(delegation);
     918                 :            : 
     919                 :          0 : out_clear_returning:
     920                 :          0 :         clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
     921                 :          0 : out_spin_unlock:
     922                 :          0 :         spin_unlock(&delegation->lock);
     923                 :          0 : out_rcu_unlock:
     924                 :          0 :         rcu_read_unlock();
     925                 :            : 
     926                 :          0 :         nfs_inode_find_state_and_recover(inode, stateid);
     927                 :            : }
     928                 :            : 
     929                 :            : /**
     930                 :            :  * nfs_expire_unused_delegation_types
     931                 :            :  * @clp: client to process
     932                 :            :  * @flags: delegation types to expire
     933                 :            :  *
     934                 :            :  */
     935                 :          0 : void nfs_expire_unused_delegation_types(struct nfs_client *clp, fmode_t flags)
     936                 :            : {
     937                 :          0 :         nfs_client_mark_return_unused_delegation_types(clp, flags);
     938                 :          0 :         nfs_delegation_run_state_manager(clp);
     939                 :          0 : }
     940                 :            : 
     941                 :          0 : static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
     942                 :            : {
     943                 :          0 :         struct nfs_delegation *delegation;
     944                 :            : 
     945         [ #  # ]:          0 :         list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
     946         [ #  # ]:          0 :                 if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
     947                 :          0 :                         continue;
     948                 :          0 :                 nfs_mark_return_if_closed_delegation(server, delegation);
     949                 :            :         }
     950                 :          0 : }
     951                 :            : 
     952                 :            : /**
     953                 :            :  * nfs_expire_unreferenced_delegations - Eliminate unused delegations
     954                 :            :  * @clp: nfs_client to process
     955                 :            :  *
     956                 :            :  */
     957                 :          0 : void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
     958                 :            : {
     959                 :          0 :         struct nfs_server *server;
     960                 :            : 
     961                 :          0 :         rcu_read_lock();
     962         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
     963                 :          0 :                 nfs_mark_return_unreferenced_delegations(server);
     964                 :          0 :         rcu_read_unlock();
     965                 :            : 
     966                 :          0 :         nfs_delegation_run_state_manager(clp);
     967                 :          0 : }
     968                 :            : 
     969                 :            : /**
     970                 :            :  * nfs_async_inode_return_delegation - asynchronously return a delegation
     971                 :            :  * @inode: inode to process
     972                 :            :  * @stateid: state ID information
     973                 :            :  *
     974                 :            :  * Returns zero on success, or a negative errno value.
     975                 :            :  */
     976                 :          0 : int nfs_async_inode_return_delegation(struct inode *inode,
     977                 :            :                                       const nfs4_stateid *stateid)
     978                 :            : {
     979                 :          0 :         struct nfs_server *server = NFS_SERVER(inode);
     980                 :          0 :         struct nfs_client *clp = server->nfs_client;
     981                 :          0 :         struct nfs_delegation *delegation;
     982                 :            : 
     983                 :          0 :         rcu_read_lock();
     984                 :          0 :         delegation = nfs4_get_valid_delegation(inode);
     985         [ #  # ]:          0 :         if (delegation == NULL)
     986                 :          0 :                 goto out_enoent;
     987   [ #  #  #  # ]:          0 :         if (stateid != NULL &&
     988                 :          0 :             !clp->cl_mvops->match_stateid(&delegation->stateid, stateid))
     989                 :          0 :                 goto out_enoent;
     990                 :          0 :         nfs_mark_return_delegation(server, delegation);
     991                 :          0 :         rcu_read_unlock();
     992                 :            : 
     993                 :          0 :         nfs_delegation_run_state_manager(clp);
     994                 :          0 :         return 0;
     995                 :          0 : out_enoent:
     996                 :          0 :         rcu_read_unlock();
     997                 :          0 :         return -ENOENT;
     998                 :            : }
     999                 :            : 
    1000                 :            : static struct inode *
    1001                 :          0 : nfs_delegation_find_inode_server(struct nfs_server *server,
    1002                 :            :                                  const struct nfs_fh *fhandle)
    1003                 :            : {
    1004                 :          0 :         struct nfs_delegation *delegation;
    1005                 :          0 :         struct inode *freeme, *res = NULL;
    1006                 :            : 
    1007         [ #  # ]:          0 :         list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
    1008                 :          0 :                 spin_lock(&delegation->lock);
    1009   [ #  #  #  # ]:          0 :                 if (delegation->inode != NULL &&
    1010                 :          0 :                     !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) &&
    1011         [ #  # ]:          0 :                     nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
    1012                 :          0 :                         freeme = igrab(delegation->inode);
    1013   [ #  #  #  # ]:          0 :                         if (freeme && nfs_sb_active(freeme->i_sb))
    1014                 :          0 :                                 res = freeme;
    1015                 :          0 :                         spin_unlock(&delegation->lock);
    1016         [ #  # ]:          0 :                         if (res != NULL)
    1017                 :            :                                 return res;
    1018         [ #  # ]:          0 :                         if (freeme) {
    1019                 :          0 :                                 rcu_read_unlock();
    1020                 :          0 :                                 iput(freeme);
    1021                 :          0 :                                 rcu_read_lock();
    1022                 :            :                         }
    1023                 :          0 :                         return ERR_PTR(-EAGAIN);
    1024                 :            :                 }
    1025                 :          0 :                 spin_unlock(&delegation->lock);
    1026                 :            :         }
    1027                 :            :         return ERR_PTR(-ENOENT);
    1028                 :            : }
    1029                 :            : 
    1030                 :            : /**
    1031                 :            :  * nfs_delegation_find_inode - retrieve the inode associated with a delegation
    1032                 :            :  * @clp: client state handle
    1033                 :            :  * @fhandle: filehandle from a delegation recall
    1034                 :            :  *
    1035                 :            :  * Returns pointer to inode matching "fhandle," or NULL if a matching inode
    1036                 :            :  * cannot be found.
    1037                 :            :  */
    1038                 :          0 : struct inode *nfs_delegation_find_inode(struct nfs_client *clp,
    1039                 :            :                                         const struct nfs_fh *fhandle)
    1040                 :            : {
    1041                 :          0 :         struct nfs_server *server;
    1042                 :          0 :         struct inode *res;
    1043                 :            : 
    1044                 :          0 :         rcu_read_lock();
    1045         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
    1046                 :          0 :                 res = nfs_delegation_find_inode_server(server, fhandle);
    1047         [ #  # ]:          0 :                 if (res != ERR_PTR(-ENOENT)) {
    1048                 :          0 :                         rcu_read_unlock();
    1049                 :          0 :                         return res;
    1050                 :            :                 }
    1051                 :            :         }
    1052                 :          0 :         rcu_read_unlock();
    1053                 :          0 :         return ERR_PTR(-ENOENT);
    1054                 :            : }
    1055                 :            : 
    1056                 :          0 : static void nfs_delegation_mark_reclaim_server(struct nfs_server *server)
    1057                 :            : {
    1058                 :          0 :         struct nfs_delegation *delegation;
    1059                 :            : 
    1060         [ #  # ]:          0 :         list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
    1061                 :            :                 /*
    1062                 :            :                  * If the delegation may have been admin revoked, then we
    1063                 :            :                  * cannot reclaim it.
    1064                 :            :                  */
    1065         [ #  # ]:          0 :                 if (test_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags))
    1066                 :          0 :                         continue;
    1067                 :          0 :                 set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
    1068                 :            :         }
    1069                 :          0 : }
    1070                 :            : 
    1071                 :            : /**
    1072                 :            :  * nfs_delegation_mark_reclaim - mark all delegations as needing to be reclaimed
    1073                 :            :  * @clp: nfs_client to process
    1074                 :            :  *
    1075                 :            :  */
    1076                 :          0 : void nfs_delegation_mark_reclaim(struct nfs_client *clp)
    1077                 :            : {
    1078                 :          0 :         struct nfs_server *server;
    1079                 :            : 
    1080                 :          0 :         rcu_read_lock();
    1081         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
    1082                 :          0 :                 nfs_delegation_mark_reclaim_server(server);
    1083                 :          0 :         rcu_read_unlock();
    1084                 :          0 : }
    1085                 :            : 
    1086                 :            : /**
    1087                 :            :  * nfs_delegation_reap_unclaimed - reap unclaimed delegations after reboot recovery is done
    1088                 :            :  * @clp: nfs_client to process
    1089                 :            :  *
    1090                 :            :  */
    1091                 :          0 : void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
    1092                 :            : {
    1093                 :          0 :         struct nfs_delegation *delegation;
    1094                 :          0 :         struct nfs_server *server;
    1095                 :          0 :         struct inode *inode;
    1096                 :            : 
    1097                 :            : restart:
    1098                 :          0 :         rcu_read_lock();
    1099         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
    1100         [ #  # ]:          0 :                 list_for_each_entry_rcu(delegation, &server->delegations,
    1101                 :            :                                                                 super_list) {
    1102         [ #  # ]:          0 :                         if (test_bit(NFS_DELEGATION_INODE_FREEING,
    1103         [ #  # ]:          0 :                                                 &delegation->flags) ||
    1104                 :            :                             test_bit(NFS_DELEGATION_RETURNING,
    1105         [ #  # ]:          0 :                                                 &delegation->flags) ||
    1106                 :            :                             test_bit(NFS_DELEGATION_NEED_RECLAIM,
    1107                 :            :                                                 &delegation->flags) == 0)
    1108                 :          0 :                                 continue;
    1109         [ #  # ]:          0 :                         if (!nfs_sb_active(server->super))
    1110                 :            :                                 break; /* continue in outer loop */
    1111                 :          0 :                         inode = nfs_delegation_grab_inode(delegation);
    1112         [ #  # ]:          0 :                         if (inode == NULL) {
    1113                 :          0 :                                 rcu_read_unlock();
    1114                 :          0 :                                 nfs_sb_deactive(server->super);
    1115                 :          0 :                                 goto restart;
    1116                 :            :                         }
    1117                 :          0 :                         delegation = nfs_start_delegation_return_locked(NFS_I(inode));
    1118                 :          0 :                         rcu_read_unlock();
    1119         [ #  # ]:          0 :                         if (delegation != NULL) {
    1120         [ #  # ]:          0 :                                 if (nfs_detach_delegation(NFS_I(inode), delegation,
    1121                 :            :                                                         server) != NULL)
    1122                 :          0 :                                         nfs_free_delegation(delegation);
    1123                 :            :                                 /* Match nfs_start_delegation_return_locked */
    1124                 :          0 :                                 nfs_put_delegation(delegation);
    1125                 :            :                         }
    1126                 :          0 :                         iput(inode);
    1127                 :          0 :                         nfs_sb_deactive(server->super);
    1128                 :          0 :                         cond_resched();
    1129                 :          0 :                         goto restart;
    1130                 :            :                 }
    1131                 :            :         }
    1132                 :          0 :         rcu_read_unlock();
    1133                 :          0 : }
    1134                 :            : 
    1135                 :          0 : static inline bool nfs4_server_rebooted(const struct nfs_client *clp)
    1136                 :            : {
    1137                 :          0 :         return (clp->cl_state & (BIT(NFS4CLNT_CHECK_LEASE) |
    1138                 :            :                                 BIT(NFS4CLNT_LEASE_EXPIRED) |
    1139                 :            :                                 BIT(NFS4CLNT_SESSION_RESET))) != 0;
    1140                 :            : }
    1141                 :            : 
    1142                 :            : static void nfs_mark_test_expired_delegation(struct nfs_server *server,
    1143                 :            :             struct nfs_delegation *delegation)
    1144                 :            : {
    1145                 :            :         if (delegation->stateid.type == NFS4_INVALID_STATEID_TYPE)
    1146                 :            :                 return;
    1147                 :            :         clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
    1148                 :            :         set_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
    1149                 :            :         set_bit(NFS4CLNT_DELEGATION_EXPIRED, &server->nfs_client->cl_state);
    1150                 :            : }
    1151                 :            : 
    1152                 :          0 : static void nfs_inode_mark_test_expired_delegation(struct nfs_server *server,
    1153                 :            :                 struct inode *inode)
    1154                 :            : {
    1155                 :          0 :         struct nfs_delegation *delegation;
    1156                 :            : 
    1157                 :          0 :         rcu_read_lock();
    1158         [ #  # ]:          0 :         delegation = rcu_dereference(NFS_I(inode)->delegation);
    1159         [ #  # ]:          0 :         if (delegation)
    1160                 :          0 :                 nfs_mark_test_expired_delegation(server, delegation);
    1161                 :          0 :         rcu_read_unlock();
    1162                 :            : 
    1163                 :            : }
    1164                 :            : 
    1165                 :          0 : static void nfs_delegation_mark_test_expired_server(struct nfs_server *server)
    1166                 :            : {
    1167                 :          0 :         struct nfs_delegation *delegation;
    1168                 :            : 
    1169         [ #  # ]:          0 :         list_for_each_entry_rcu(delegation, &server->delegations, super_list)
    1170                 :          0 :                 nfs_mark_test_expired_delegation(server, delegation);
    1171                 :            : }
    1172                 :            : 
    1173                 :            : /**
    1174                 :            :  * nfs_mark_test_expired_all_delegations - mark all delegations for testing
    1175                 :            :  * @clp: nfs_client to process
    1176                 :            :  *
    1177                 :            :  * Iterates through all the delegations associated with this server and
    1178                 :            :  * marks them as needing to be checked for validity.
    1179                 :            :  */
    1180                 :          0 : void nfs_mark_test_expired_all_delegations(struct nfs_client *clp)
    1181                 :            : {
    1182                 :          0 :         struct nfs_server *server;
    1183                 :            : 
    1184                 :          0 :         rcu_read_lock();
    1185         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
    1186                 :          0 :                 nfs_delegation_mark_test_expired_server(server);
    1187                 :          0 :         rcu_read_unlock();
    1188                 :          0 : }
    1189                 :            : 
    1190                 :            : /**
    1191                 :            :  * nfs_test_expired_all_delegations - test all delegations for a client
    1192                 :            :  * @clp: nfs_client to process
    1193                 :            :  *
    1194                 :            :  * Helper for handling "recallable state revoked" status from server.
    1195                 :            :  */
    1196                 :          0 : void nfs_test_expired_all_delegations(struct nfs_client *clp)
    1197                 :            : {
    1198                 :          0 :         nfs_mark_test_expired_all_delegations(clp);
    1199                 :          0 :         nfs4_schedule_state_manager(clp);
    1200                 :          0 : }
    1201                 :            : 
    1202                 :            : static void
    1203                 :          0 : nfs_delegation_test_free_expired(struct inode *inode,
    1204                 :            :                 nfs4_stateid *stateid,
    1205                 :            :                 const struct cred *cred)
    1206                 :            : {
    1207         [ #  # ]:          0 :         struct nfs_server *server = NFS_SERVER(inode);
    1208                 :          0 :         const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops;
    1209                 :          0 :         int status;
    1210                 :            : 
    1211         [ #  # ]:          0 :         if (!cred)
    1212                 :            :                 return;
    1213                 :          0 :         status = ops->test_and_free_expired(server, stateid, cred);
    1214         [ #  # ]:          0 :         if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
    1215                 :          0 :                 nfs_remove_bad_delegation(inode, stateid);
    1216                 :            : }
    1217                 :            : 
    1218                 :            : /**
    1219                 :            :  * nfs_reap_expired_delegations - reap expired delegations
    1220                 :            :  * @clp: nfs_client to process
    1221                 :            :  *
    1222                 :            :  * Iterates through all the delegations associated with this server and
    1223                 :            :  * checks if they have may have been revoked. This function is usually
    1224                 :            :  * expected to be called in cases where the server may have lost its
    1225                 :            :  * lease.
    1226                 :            :  */
    1227                 :          0 : void nfs_reap_expired_delegations(struct nfs_client *clp)
    1228                 :            : {
    1229                 :          0 :         struct nfs_delegation *delegation;
    1230                 :          0 :         struct nfs_server *server;
    1231                 :          0 :         struct inode *inode;
    1232                 :          0 :         const struct cred *cred;
    1233                 :          0 :         nfs4_stateid stateid;
    1234                 :            : 
    1235                 :            : restart:
    1236                 :          0 :         rcu_read_lock();
    1237         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
    1238         [ #  # ]:          0 :                 list_for_each_entry_rcu(delegation, &server->delegations,
    1239                 :            :                                                                 super_list) {
    1240         [ #  # ]:          0 :                         if (test_bit(NFS_DELEGATION_INODE_FREEING,
    1241         [ #  # ]:          0 :                                                 &delegation->flags) ||
    1242                 :            :                             test_bit(NFS_DELEGATION_RETURNING,
    1243         [ #  # ]:          0 :                                                 &delegation->flags) ||
    1244                 :            :                             test_bit(NFS_DELEGATION_TEST_EXPIRED,
    1245                 :            :                                                 &delegation->flags) == 0)
    1246                 :          0 :                                 continue;
    1247         [ #  # ]:          0 :                         if (!nfs_sb_active(server->super))
    1248                 :            :                                 break; /* continue in outer loop */
    1249                 :          0 :                         inode = nfs_delegation_grab_inode(delegation);
    1250         [ #  # ]:          0 :                         if (inode == NULL) {
    1251                 :          0 :                                 rcu_read_unlock();
    1252                 :          0 :                                 nfs_sb_deactive(server->super);
    1253                 :          0 :                                 goto restart;
    1254                 :            :                         }
    1255         [ #  # ]:          0 :                         cred = get_cred_rcu(delegation->cred);
    1256                 :          0 :                         nfs4_stateid_copy(&stateid, &delegation->stateid);
    1257                 :          0 :                         clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
    1258                 :          0 :                         rcu_read_unlock();
    1259                 :          0 :                         nfs_delegation_test_free_expired(inode, &stateid, cred);
    1260                 :          0 :                         put_cred(cred);
    1261         [ #  # ]:          0 :                         if (nfs4_server_rebooted(clp)) {
    1262                 :          0 :                                 nfs_inode_mark_test_expired_delegation(server,inode);
    1263                 :          0 :                                 iput(inode);
    1264                 :          0 :                                 nfs_sb_deactive(server->super);
    1265                 :          0 :                                 return;
    1266                 :            :                         }
    1267                 :          0 :                         iput(inode);
    1268                 :          0 :                         nfs_sb_deactive(server->super);
    1269                 :          0 :                         cond_resched();
    1270                 :          0 :                         goto restart;
    1271                 :            :                 }
    1272                 :            :         }
    1273                 :          0 :         rcu_read_unlock();
    1274                 :            : }
    1275                 :            : 
    1276                 :          0 : void nfs_inode_find_delegation_state_and_recover(struct inode *inode,
    1277                 :            :                 const nfs4_stateid *stateid)
    1278                 :            : {
    1279                 :          0 :         struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
    1280                 :          0 :         struct nfs_delegation *delegation;
    1281                 :          0 :         bool found = false;
    1282                 :            : 
    1283                 :          0 :         rcu_read_lock();
    1284         [ #  # ]:          0 :         delegation = rcu_dereference(NFS_I(inode)->delegation);
    1285         [ #  # ]:          0 :         if (delegation &&
    1286   [ #  #  #  # ]:          0 :             nfs4_stateid_match_or_older(&delegation->stateid, stateid) &&
    1287                 :          0 :             !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
    1288                 :          0 :                 nfs_mark_test_expired_delegation(NFS_SERVER(inode), delegation);
    1289                 :          0 :                 found = true;
    1290                 :            :         }
    1291                 :          0 :         rcu_read_unlock();
    1292                 :          0 :         if (found)
    1293                 :          0 :                 nfs4_schedule_state_manager(clp);
    1294                 :          0 : }
    1295                 :            : 
    1296                 :            : /**
    1297                 :            :  * nfs_delegations_present - check for existence of delegations
    1298                 :            :  * @clp: client state handle
    1299                 :            :  *
    1300                 :            :  * Returns one if there are any nfs_delegation structures attached
    1301                 :            :  * to this nfs_client.
    1302                 :            :  */
    1303                 :          0 : int nfs_delegations_present(struct nfs_client *clp)
    1304                 :            : {
    1305                 :          0 :         struct nfs_server *server;
    1306                 :          0 :         int ret = 0;
    1307                 :            : 
    1308                 :          0 :         rcu_read_lock();
    1309         [ #  # ]:          0 :         list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
    1310         [ #  # ]:          0 :                 if (!list_empty(&server->delegations)) {
    1311                 :            :                         ret = 1;
    1312                 :            :                         break;
    1313                 :            :                 }
    1314                 :          0 :         rcu_read_unlock();
    1315                 :          0 :         return ret;
    1316                 :            : }
    1317                 :            : 
    1318                 :            : /**
    1319                 :            :  * nfs4_refresh_delegation_stateid - Update delegation stateid seqid
    1320                 :            :  * @dst: stateid to refresh
    1321                 :            :  * @inode: inode to check
    1322                 :            :  *
    1323                 :            :  * Returns "true" and updates "dst->seqid" * if inode had a delegation
    1324                 :            :  * that matches our delegation stateid. Otherwise "false" is returned.
    1325                 :            :  */
    1326                 :          0 : bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
    1327                 :            : {
    1328                 :          0 :         struct nfs_delegation *delegation;
    1329                 :          0 :         bool ret = false;
    1330         [ #  # ]:          0 :         if (!inode)
    1331                 :          0 :                 goto out;
    1332                 :            : 
    1333                 :          0 :         rcu_read_lock();
    1334         [ #  # ]:          0 :         delegation = rcu_dereference(NFS_I(inode)->delegation);
    1335   [ #  #  #  # ]:          0 :         if (delegation != NULL &&
    1336         [ #  # ]:          0 :             nfs4_stateid_match_other(dst, &delegation->stateid) &&
    1337   [ #  #  #  # ]:          0 :             nfs4_stateid_is_newer(&delegation->stateid, dst) &&
    1338                 :          0 :             !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
    1339                 :          0 :                 dst->seqid = delegation->stateid.seqid;
    1340                 :          0 :                 ret = true;
    1341                 :            :         }
    1342                 :          0 :         rcu_read_unlock();
    1343                 :          0 : out:
    1344                 :          0 :         return ret;
    1345                 :            : }
    1346                 :            : 
    1347                 :            : /**
    1348                 :            :  * nfs4_copy_delegation_stateid - Copy inode's state ID information
    1349                 :            :  * @inode: inode to check
    1350                 :            :  * @flags: delegation type requirement
    1351                 :            :  * @dst: stateid data structure to fill in
    1352                 :            :  * @cred: optional argument to retrieve credential
    1353                 :            :  *
    1354                 :            :  * Returns "true" and fills in "dst->data" * if inode had a delegation,
    1355                 :            :  * otherwise "false" is returned.
    1356                 :            :  */
    1357                 :          0 : bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags,
    1358                 :            :                 nfs4_stateid *dst, const struct cred **cred)
    1359                 :            : {
    1360                 :          0 :         struct nfs_inode *nfsi = NFS_I(inode);
    1361                 :          0 :         struct nfs_delegation *delegation;
    1362                 :          0 :         bool ret;
    1363                 :            : 
    1364                 :          0 :         flags &= FMODE_READ|FMODE_WRITE;
    1365                 :          0 :         rcu_read_lock();
    1366                 :          0 :         delegation = rcu_dereference(nfsi->delegation);
    1367                 :          0 :         ret = nfs4_is_valid_delegation(delegation, flags);
    1368         [ #  # ]:          0 :         if (ret) {
    1369                 :          0 :                 nfs4_stateid_copy(dst, &delegation->stateid);
    1370                 :          0 :                 nfs_mark_delegation_referenced(delegation);
    1371         [ #  # ]:          0 :                 if (cred)
    1372         [ #  # ]:          0 :                         *cred = get_cred(delegation->cred);
    1373                 :            :         }
    1374                 :          0 :         rcu_read_unlock();
    1375                 :          0 :         return ret;
    1376                 :            : }
    1377                 :            : 
    1378                 :            : /**
    1379                 :            :  * nfs4_delegation_flush_on_close - Check if we must flush file on close
    1380                 :            :  * @inode: inode to check
    1381                 :            :  *
    1382                 :            :  * This function checks the number of outstanding writes to the file
    1383                 :            :  * against the delegation 'space_limit' field to see if
    1384                 :            :  * the spec requires us to flush the file on close.
    1385                 :            :  */
    1386                 :          0 : bool nfs4_delegation_flush_on_close(const struct inode *inode)
    1387                 :            : {
    1388                 :          0 :         struct nfs_inode *nfsi = NFS_I(inode);
    1389                 :          0 :         struct nfs_delegation *delegation;
    1390                 :          0 :         bool ret = true;
    1391                 :            : 
    1392                 :          0 :         rcu_read_lock();
    1393         [ #  # ]:          0 :         delegation = rcu_dereference(nfsi->delegation);
    1394   [ #  #  #  # ]:          0 :         if (delegation == NULL || !(delegation->type & FMODE_WRITE))
    1395                 :          0 :                 goto out;
    1396         [ #  # ]:          0 :         if (atomic_long_read(&nfsi->nrequests) < delegation->pagemod_limit)
    1397                 :          0 :                 ret = false;
    1398                 :          0 : out:
    1399                 :          0 :         rcu_read_unlock();
    1400                 :          0 :         return ret;
    1401                 :            : }
    1402                 :            : 
    1403                 :            : module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644);

Generated by: LCOV version 1.14