2019-10-24 10:56:44

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 05/14] NFSv4: fail nfs4_refresh_delegation_stateid() when the delegation was revoked

If the delegation was revoked, we don't want to retry the delegreturn.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/delegation.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 4bc40c27141b..f90c3cf82f8f 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -1179,6 +1179,7 @@ bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
rcu_read_lock();
delegation = rcu_dereference(NFS_I(inode)->delegation);
if (delegation != NULL &&
+ !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) &&
nfs4_stateid_match_other(dst, &delegation->stateid)) {
dst->seqid = delegation->stateid.seqid;
return ret;
--
2.21.0


2019-10-24 10:56:44

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 06/14] NFS: Rename nfs_inode_return_delegation_noreclaim()

Rename nfs_inode_return_delegation_noreclaim() to
nfs_inode_evict_delegation(), which better describes what it
does.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/delegation.c | 11 +++++++----
fs/nfs/delegation.h | 2 +-
fs/nfs/nfs4super.c | 4 ++--
3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index f90c3cf82f8f..e60737be6f26 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -574,19 +574,22 @@ int nfs_client_return_marked_delegations(struct nfs_client *clp)
}

/**
- * nfs_inode_return_delegation_noreclaim - return delegation, don't reclaim opens
+ * nfs_inode_evict_delegation - return delegation, don't reclaim opens
* @inode: inode to process
*
* Does not protect against delegation reclaims, therefore really only safe
- * to be called from nfs4_clear_inode().
+ * to be called from nfs4_clear_inode(). Guaranteed to always free
+ * the delegation structure.
*/
-void nfs_inode_return_delegation_noreclaim(struct inode *inode)
+void nfs_inode_evict_delegation(struct inode *inode)
{
struct nfs_delegation *delegation;

delegation = nfs_inode_detach_delegation(inode);
- if (delegation != NULL)
+ if (delegation != NULL) {
+ set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags);
nfs_do_return_delegation(inode, delegation, 1);
+ }
}

/**
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 2b35a99929a0..9a14a7ca1df9 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -43,7 +43,7 @@ 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);
int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
-void nfs_inode_return_delegation_noreclaim(struct inode *inode);
+void nfs_inode_evict_delegation(struct inode *inode);

struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
void nfs_server_return_all_delegations(struct nfs_server *);
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 04c57066a11a..2c9cbade561a 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -92,8 +92,8 @@ static void nfs4_evict_inode(struct inode *inode)
{
truncate_inode_pages_final(&inode->i_data);
clear_inode(inode);
- /* If we are holding a delegation, return it! */
- nfs_inode_return_delegation_noreclaim(inode);
+ /* If we are holding a delegation, return and free it */
+ nfs_inode_evict_delegation(inode);
/* Note that above delegreturn would trigger pnfs return-on-close */
pnfs_return_layout(inode);
pnfs_destroy_layout(NFS_I(inode));
--
2.21.0

2019-10-24 10:57:38

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 07/14] NFSv4: Don't remove the delegation from the super_list more than once

Add a check to ensure that we haven't already removed the delegation
from the inode after we take all the relevant locks.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/delegation.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index e60737be6f26..b49faf1b3d91 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -287,6 +287,10 @@ nfs_detach_delegation_locked(struct nfs_inode *nfsi,
return NULL;

spin_lock(&delegation->lock);
+ if (!delegation->inode) {
+ spin_unlock(&delegation->lock);
+ return NULL;
+ }
set_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
list_del_rcu(&delegation->super_list);
delegation->inode = NULL;
--
2.21.0