summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2025-11-19 08:43:21 -0500
committerTrond Myklebust <trond.myklebust@hammerspace.com>2025-11-19 11:46:50 -0500
commit0f900f11002ff52391fc2aa4a75e59f26ed1c242 (patch)
treebb9624bd29ffd4cf7637f6132c4aff31c291abe6
parent518c32a1bc4f8df1a8442ee8cdfea3e2fcff20a0 (diff)
NFS: Initialise verifiers for visible dentries in _nfs4_open_and_get_state
Ensure that the verifiers are initialised before calling d_splice_alias() in _nfs4_open_and_get_state(). Reported-by: Michael Stoler <michael.stoler@vastdata.com> Fixes: cf5b4059ba71 ("NFSv4: Fix races between open and dentry revalidation") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
-rw-r--r--fs/nfs/nfs4proc.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 93c6ce04332b..6f4e14fb7b9b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3174,18 +3174,6 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
if (opendata->o_res.rflags & NFS4_OPEN_RESULT_PRESERVE_UNLINKED)
set_bit(NFS_INO_PRESERVE_UNLINKED, &NFS_I(state->inode)->flags);
- dentry = opendata->dentry;
- if (d_really_is_negative(dentry)) {
- struct dentry *alias;
- d_drop(dentry);
- alias = d_splice_alias(igrab(state->inode), dentry);
- /* d_splice_alias() can't fail here - it's a non-directory */
- if (alias) {
- dput(ctx->dentry);
- ctx->dentry = dentry = alias;
- }
- }
-
switch(opendata->o_arg.claim) {
default:
break;
@@ -3196,7 +3184,20 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
break;
if (opendata->o_res.delegation.type != 0)
dir_verifier = nfs_save_change_attribute(dir);
- nfs_set_verifier(dentry, dir_verifier);
+ }
+
+ dentry = opendata->dentry;
+ nfs_set_verifier(dentry, dir_verifier);
+ if (d_really_is_negative(dentry)) {
+ struct dentry *alias;
+ d_drop(dentry);
+ alias = d_splice_alias(igrab(state->inode), dentry);
+ /* d_splice_alias() can't fail here - it's a non-directory */
+ if (alias) {
+ dput(ctx->dentry);
+ nfs_set_verifier(alias, dir_verifier);
+ ctx->dentry = dentry = alias;
+ }
}
/* Parse layoutget results before we check for access */