]> git.baikalelectronics.ru Git - kernel.git/commitdiff
NFSv4: Try to return the delegation immediately when marked for return on close
authorTrond Myklebust <trondmy@gmail.com>
Mon, 27 Jan 2020 14:58:17 +0000 (09:58 -0500)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Mon, 3 Feb 2020 21:35:07 +0000 (16:35 -0500)
Add a routine to return the delegation immediately upon close of the
file if it was marked for return-on-close.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/nfs4state.c

index b5b14618b73e72ff4c4efd77490eab3ee26e6427..90e50f32f3e0ec5d7510d467e8d13b4282bf5015 100644 (file)
@@ -639,6 +639,39 @@ int nfs4_inode_return_delegation(struct inode *inode)
        return err;
 }
 
+/**
+ * nfs_inode_return_delegation_on_close - asynchronously return a delegation
+ * @inode: inode to process
+ *
+ * This routine is called on file close in order to determine if the
+ * inode delegation needs to be returned immediately.
+ */
+void nfs4_inode_return_delegation_on_close(struct inode *inode)
+{
+       struct nfs_delegation *delegation;
+       struct nfs_delegation *ret = NULL;
+
+       if (!inode)
+               return;
+       rcu_read_lock();
+       delegation = nfs4_get_valid_delegation(inode);
+       if (!delegation)
+               goto out;
+       if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags)) {
+               spin_lock(&delegation->lock);
+               if (delegation->inode &&
+                   list_empty(&NFS_I(inode)->open_files) &&
+                   !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
+                       clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
+                       ret = delegation;
+               }
+               spin_unlock(&delegation->lock);
+       }
+out:
+       rcu_read_unlock();
+       nfs_end_delegation_return(inode, ret, 0);
+}
+
 /**
  * nfs4_inode_make_writeable
  * @inode: pointer to inode
index 15d3484be028385031393e7dd67416ef95bd37ce..31b84604d3836c44bca2377e454efba231eb3506 100644 (file)
@@ -42,6 +42,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
 void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
                fmode_t type, const nfs4_stateid *stateid, unsigned long pagemod_limit);
 int nfs4_inode_return_delegation(struct inode *inode);
+void nfs4_inode_return_delegation_on_close(struct inode *inode);
 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
 void nfs_inode_evict_delegation(struct inode *inode);
 
index fe1b908eecc812e41295bc3a6dd4912eaaed7ca4..19b473bc560e8bc357bc3da399f455eaee7158d2 100644 (file)
@@ -766,6 +766,7 @@ void nfs4_put_open_state(struct nfs4_state *state)
        list_del(&state->open_states);
        spin_unlock(&inode->i_lock);
        spin_unlock(&owner->so_lock);
+       nfs4_inode_return_delegation_on_close(inode);
        iput(inode);
        nfs4_free_open_state(state);
        nfs4_put_state_owner(owner);