Skip to content

Commit 9019fb3

Browse files
author
Trond Myklebust
committed
NFS: Label the dentry with a verifier in nfs_rmdir() and nfs_unlink()
After the success of an operation such as rmdir() or unlink(), we expect to add the dentry back to the dcache as an ordinary negative dentry. However in NFS, unless it is labelled with the appropriate verifier for the parent directory state, then nfs_lookup_revalidate will end up discarding that dentry and forcing a new lookup. The fix is to ensure that we relabel the dentry appropriately on success. Signed-off-by: Trond Myklebust <[email protected]>
1 parent 342a67f commit 9019fb3

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

fs/nfs/dir.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,6 +2197,18 @@ static void nfs_dentry_handle_enoent(struct dentry *dentry)
21972197
d_delete(dentry);
21982198
}
21992199

2200+
static void nfs_dentry_remove_handle_error(struct inode *dir,
2201+
struct dentry *dentry, int error)
2202+
{
2203+
switch (error) {
2204+
case -ENOENT:
2205+
d_delete(dentry);
2206+
fallthrough;
2207+
case 0:
2208+
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
2209+
}
2210+
}
2211+
22002212
int nfs_rmdir(struct inode *dir, struct dentry *dentry)
22012213
{
22022214
int error;
@@ -2219,6 +2231,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
22192231
up_write(&NFS_I(d_inode(dentry))->rmdir_sem);
22202232
} else
22212233
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
2234+
nfs_dentry_remove_handle_error(dir, dentry, error);
22222235
trace_nfs_rmdir_exit(dir, dentry, error);
22232236

22242237
return error;
@@ -2288,9 +2301,8 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
22882301
}
22892302
spin_unlock(&dentry->d_lock);
22902303
error = nfs_safe_remove(dentry);
2291-
if (!error || error == -ENOENT) {
2292-
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
2293-
} else if (need_rehash)
2304+
nfs_dentry_remove_handle_error(dir, dentry, error);
2305+
if (need_rehash)
22942306
d_rehash(dentry);
22952307
out:
22962308
trace_nfs_unlink_exit(dir, dentry, error);

0 commit comments

Comments
 (0)