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 <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
342a67f088
commit
9019fb391d
1 changed files with 15 additions and 3 deletions
18
fs/nfs/dir.c
18
fs/nfs/dir.c
|
@ -2197,6 +2197,18 @@ static void nfs_dentry_handle_enoent(struct dentry *dentry)
|
||||||
d_delete(dentry);
|
d_delete(dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nfs_dentry_remove_handle_error(struct inode *dir,
|
||||||
|
struct dentry *dentry, int error)
|
||||||
|
{
|
||||||
|
switch (error) {
|
||||||
|
case -ENOENT:
|
||||||
|
d_delete(dentry);
|
||||||
|
fallthrough;
|
||||||
|
case 0:
|
||||||
|
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int nfs_rmdir(struct inode *dir, struct dentry *dentry)
|
int nfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
@ -2219,6 +2231,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
up_write(&NFS_I(d_inode(dentry))->rmdir_sem);
|
up_write(&NFS_I(d_inode(dentry))->rmdir_sem);
|
||||||
} else
|
} else
|
||||||
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
|
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
|
||||||
|
nfs_dentry_remove_handle_error(dir, dentry, error);
|
||||||
trace_nfs_rmdir_exit(dir, dentry, error);
|
trace_nfs_rmdir_exit(dir, dentry, error);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
@ -2288,9 +2301,8 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
}
|
}
|
||||||
spin_unlock(&dentry->d_lock);
|
spin_unlock(&dentry->d_lock);
|
||||||
error = nfs_safe_remove(dentry);
|
error = nfs_safe_remove(dentry);
|
||||||
if (!error || error == -ENOENT) {
|
nfs_dentry_remove_handle_error(dir, dentry, error);
|
||||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
if (need_rehash)
|
||||||
} else if (need_rehash)
|
|
||||||
d_rehash(dentry);
|
d_rehash(dentry);
|
||||||
out:
|
out:
|
||||||
trace_nfs_unlink_exit(dir, dentry, error);
|
trace_nfs_unlink_exit(dir, dentry, error);
|
||||||
|
|
Loading…
Add table
Reference in a new issue