Commit 0f900f11 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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: default avatarMichael Stoler <michael.stoler@vastdata.com>
Fixes: cf5b4059 ("NFSv4: Fix races between open and dentry revalidation")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 518c32a1
Loading
Loading
Loading
Loading
+14 −13
Original line number Diff line number Diff line
@@ -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);
	}

	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 */