diff options
| author | Trond Myklebust <trond.myklebust@hammerspace.com> | 2025-11-19 08:43:21 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-12-18 14:00:08 +0100 |
| commit | 0dd9b9389521ace8eb9e0e54d125ee0f0696cf0f (patch) | |
| tree | eb1b2fac575f0b2ed7e4340577e46b3a57561d64 | |
| parent | 34c0479db10884e10374fdd4a18eed2920561034 (diff) | |
| download | linux-0dd9b9389521ace8eb9e0e54d125ee0f0696cf0f.tar.gz linux-0dd9b9389521ace8eb9e0e54d125ee0f0696cf0f.tar.bz2 linux-0dd9b9389521ace8eb9e0e54d125ee0f0696cf0f.zip | |
NFS: Initialise verifiers for visible dentries in _nfs4_open_and_get_state
[ Upstream commit 0f900f11002ff52391fc2aa4a75e59f26ed1c242 ]
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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
| -rw-r--r-- | fs/nfs/nfs4proc.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a1e95732fd03..106f0bf88137 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 */ |
