]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFSv4.x: Directory delegations don't require any state recovery
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Tue, 6 Jan 2026 16:54:32 +0000 (11:54 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Wed, 7 Jan 2026 17:28:26 +0000 (12:28 -0500)
The state recovery code in nfs_end_delegation_return() is intended to
allow regular files to recover cached open and lock state. It has no
function for directory delegations, and may cause corruption.

Fixes: 156b09482933 ("NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/delegation.c
fs/nfs/nfs4state.c

index 2248e3ad089a7c184a5546a7981244b22b34c09f..c9fa4c1f68fce452d698b18be9a1a1a4dba3377a 100644 (file)
@@ -581,6 +581,10 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
        if (delegation == NULL)
                return 0;
 
+       /* Directory delegations don't require any state recovery */
+       if (!S_ISREG(inode->i_mode))
+               goto out_return;
+
        if (!issync)
                mode |= O_NONBLOCK;
        /* Recall of any remaining application leases */
@@ -604,6 +608,7 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
                goto out;
        }
 
+out_return:
        err = nfs_do_return_delegation(inode, delegation, issync);
 out:
        /* Refcount matched in nfs_start_delegation_return_locked() */
index 01179f7de3225612dc78d3629d0d99f7e6194208..dba51c622cf36aacb7d982251547fc163f1aa005 100644 (file)
@@ -1445,6 +1445,8 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
        struct nfs4_state *state;
        bool found = false;
 
+       if (!S_ISREG(inode->i_mode))
+               goto out;
        rcu_read_lock();
        list_for_each_entry_rcu(ctx, &nfsi->open_files, list) {
                state = ctx->state;
@@ -1466,7 +1468,7 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
                        found = true;
        }
        rcu_read_unlock();
-
+out:
        nfs_inode_find_delegation_state_and_recover(inode, stateid);
        if (found)
                nfs4_schedule_state_manager(clp);
@@ -1478,6 +1480,8 @@ static void nfs4_state_mark_open_context_bad(struct nfs4_state *state, int err)
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_open_context *ctx;
 
+       if (!S_ISREG(inode->i_mode))
+               return;
        rcu_read_lock();
        list_for_each_entry_rcu(ctx, &nfsi->open_files, list) {
                if (ctx->state != state)