From e96d9ca486b8310abc3736f45b45a91f0628b041 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 7 Jan 2026 08:27:09 +0100 Subject: [PATCH] NFS: don't consume a delegation reference in nfs_end_delegation_return All callers now hold references to the delegation as part of the lookup, removing the need for an extra reference for those that are actually returned which is then dropped in nfs_end_delegation_return. Signed-off-by: Christoph Hellwig Signed-off-by: Anna Schumaker --- fs/nfs/delegation.c | 46 +++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 0e91ee9aaa1b6..684ec87dd4ebe 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -325,7 +325,6 @@ nfs_start_delegation_return(struct nfs_inode *nfsi) if (delegation->inode && !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); - /* Refcount matched in nfs_end_delegation_return() */ ret = nfs_get_delegation(delegation); } spin_unlock(&delegation->lock); @@ -578,15 +577,11 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation if (err) { nfs_abort_delegation_return(delegation, server, err); - goto out; + return err; } out_return: - err = nfs_do_return_delegation(inode, delegation, issync); -out: - /* Refcount matched in nfs_start_delegation_return() */ - nfs_put_delegation(delegation); - return err; + return nfs_do_return_delegation(inode, delegation, issync); } static int nfs_server_return_marked_delegations(struct nfs_server *server, @@ -652,7 +647,11 @@ restart: iput(to_put); - err = nfs_end_delegation_return(inode, delegation, 0); + if (delegation) { + err = nfs_end_delegation_return(inode, delegation, 0); + nfs_put_delegation(delegation); + } + iput(inode); cond_resched(); if (!err) @@ -768,6 +767,7 @@ int nfs4_inode_return_delegation(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; + int err; rcu_read_lock(); delegation = nfs_start_delegation_return(nfsi); @@ -780,7 +780,9 @@ int nfs4_inode_return_delegation(struct inode *inode) break_lease(inode, O_WRONLY | O_RDWR); if (S_ISREG(inode->i_mode)) nfs_wb_all(inode); - return nfs_end_delegation_return(inode, delegation, 1); + err = nfs_end_delegation_return(inode, delegation, 1); + nfs_put_delegation(delegation); + return err; } /** @@ -794,7 +796,7 @@ int nfs4_inode_return_delegation(struct inode *inode) void nfs4_inode_set_return_delegation_on_close(struct inode *inode) { struct nfs_delegation *delegation; - struct nfs_delegation *ret = NULL; + bool return_now = false; if (!inode) return; @@ -807,17 +809,17 @@ void nfs4_inode_set_return_delegation_on_close(struct inode *inode) if (!delegation->inode) goto out_unlock; if (list_empty(&NFS_I(inode)->open_files) && - !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { - /* Refcount matched in nfs_end_delegation_return() */ - ret = nfs_get_delegation(delegation); - } else + !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) + return_now = true; + else set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); out_unlock: spin_unlock(&delegation->lock); - if (ret) + if (return_now) { nfs_clear_verifier_delegated(inode); + nfs_end_delegation_return(inode, delegation, 0); + } nfs_put_delegation(delegation); - nfs_end_delegation_return(inode, ret, 0); } /** @@ -830,7 +832,7 @@ out_unlock: void nfs4_inode_return_delegation_on_close(struct inode *inode) { struct nfs_delegation *delegation; - struct nfs_delegation *ret = NULL; + bool return_now = false; delegation = nfs4_get_valid_delegation(inode); if (!delegation) @@ -844,16 +846,16 @@ void nfs4_inode_return_delegation_on_close(struct inode *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); - /* Refcount matched in nfs_end_delegation_return() */ - ret = nfs_get_delegation(delegation); + return_now = true; } spin_unlock(&delegation->lock); - if (ret) - nfs_clear_verifier_delegated(inode); } + if (return_now) { + nfs_clear_verifier_delegated(inode); + nfs_end_delegation_return(inode, delegation, 0); + } nfs_put_delegation(delegation); - nfs_end_delegation_return(inode, ret, 0); } /** -- 2.47.3