From: Trond Myklebust trond.myklebust@hammerspace.com
mainline inclusion from mainline-v5.3-rc4 commit ad11408970df79d5f481aa9964e91f183133424c category: bugfix bugzilla: NA CVE: NA
--------------------------------
Fix nfs_reap_expired_delegations() to ensure that we only reap delegations that are actually expired, rather than triggering on random errors.
Fixes: 45870d6909d5a ("NFSv4.1: Test delegation stateids when server...") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com
Conflicts: fs/nfs/delegation.c
Signed-off-by: Zhang Xiaoxu zhangxiaoxu5@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/nfs/delegation.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index b0c0c2fc2fbac..9a91a1c9fb4eb 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -1044,6 +1044,21 @@ void nfs_mark_test_expired_all_delegations(struct nfs_client *clp) rcu_read_unlock(); }
+static void +nfs_delegation_test_free_expired(struct inode *inode, + nfs4_stateid *stateid, struct rpc_cred *cred) +{ + struct nfs_server *server = NFS_SERVER(inode); + const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops; + int status; + + if (!cred) + return; + status = ops->test_and_free_expired(server, stateid, cred); + if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID) + nfs_remove_bad_delegation(inode, stateid); +} + /** * nfs_reap_expired_delegations - reap expired delegations * @clp: nfs_client to process @@ -1055,7 +1070,6 @@ void nfs_mark_test_expired_all_delegations(struct nfs_client *clp) */ void nfs_reap_expired_delegations(struct nfs_client *clp) { - const struct nfs4_minor_version_ops *ops = clp->cl_mvops; struct nfs_delegation *delegation; struct nfs_server *server; struct inode *inode; @@ -1086,11 +1100,7 @@ void nfs_reap_expired_delegations(struct nfs_client *clp) nfs4_stateid_copy(&stateid, &delegation->stateid); clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags); rcu_read_unlock(); - if (cred != NULL && - ops->test_and_free_expired(server, &stateid, cred) < 0) { - nfs_revoke_delegation(inode, &stateid); - nfs_inode_find_state_and_recover(inode, &stateid); - } + nfs_delegation_test_free_expired(inode, &stateid, cred); put_rpccred(cred); if (nfs4_server_rebooted(clp)) { nfs_inode_mark_test_expired_delegation(server,inode);