summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2026-01-06 11:54:32 -0500
committerTrond Myklebust <trond.myklebust@hammerspace.com>2026-01-07 12:28:26 -0500
commitdf56ddd057424d21483bd0bee4da3632706d6606 (patch)
tree17514a013c8843ebe91065aeddc621266ff569c1 /fs
parent3f77eda548c82564ae4a23c76b51d36c6e39c865 (diff)
NFSv4.x: Directory delegations don't require any state recovery
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/delegation.c5
-rw-r--r--fs/nfs/nfs4state.c6
2 files changed, 10 insertions, 1 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 2248e3ad089a..c9fa4c1f68fc 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -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() */
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 01179f7de322..dba51c622cf3 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -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)