Skip to content

Commit cf5b405

Browse files
trondmyamschuma-ntap
authored andcommitted
NFSv4: Fix races between open and dentry revalidation
We want to make sure that we revalidate the dentry if and only if we've done an OPEN by filename. In order to avoid races with remote changes to the directory on the server, we want to save the verifier before calling OPEN. The exception is if the server returned a delegation with our OPEN, as we then know that the filename can't have changed on the server. Signed-off-by: Trond Myklebust <[email protected]> Reviewed-by: Benjamin Coddington <[email protected]> Tested-by: Benjamin Coddington <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent a1147b8 commit cf5b405

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

fs/nfs/nfs4file.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ nfs4_file_open(struct inode *inode, struct file *filp)
8787
if (inode != d_inode(dentry))
8888
goto out_drop;
8989

90-
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
9190
nfs_file_set_open_context(filp, ctx);
9291
nfs_fscache_open_file(inode, filp);
9392
err = 0;

fs/nfs/nfs4proc.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2974,10 +2974,13 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
29742974
struct dentry *dentry;
29752975
struct nfs4_state *state;
29762976
fmode_t acc_mode = _nfs4_ctx_to_accessmode(ctx);
2977+
struct inode *dir = d_inode(opendata->dir);
2978+
unsigned long dir_verifier;
29772979
unsigned int seq;
29782980
int ret;
29792981

29802982
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
2983+
dir_verifier = nfs_save_change_attribute(dir);
29812984

29822985
ret = _nfs4_proc_open(opendata, ctx);
29832986
if (ret != 0)
@@ -3005,8 +3008,19 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
30053008
dput(ctx->dentry);
30063009
ctx->dentry = dentry = alias;
30073010
}
3008-
nfs_set_verifier(dentry,
3009-
nfs_save_change_attribute(d_inode(opendata->dir)));
3011+
}
3012+
3013+
switch(opendata->o_arg.claim) {
3014+
default:
3015+
break;
3016+
case NFS4_OPEN_CLAIM_NULL:
3017+
case NFS4_OPEN_CLAIM_DELEGATE_CUR:
3018+
case NFS4_OPEN_CLAIM_DELEGATE_PREV:
3019+
if (!opendata->rpc_done)
3020+
break;
3021+
if (opendata->o_res.delegation_type != 0)
3022+
dir_verifier = nfs_save_change_attribute(dir);
3023+
nfs_set_verifier(dentry, dir_verifier);
30103024
}
30113025

30123026
/* Parse layoutget results before we check for access */

0 commit comments

Comments
 (0)