nfs: per-name sillyunlink exclusion
use d_alloc_parallel() for sillyunlink/lookup exclusion and explicit rwsem (nfs_rmdir() being a writer and nfs_call_unlink() - a reader) for rmdir/sillyunlink one. That ought to make lookup/readdir/!O_CREAT atomic_open really parallel on NFS. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -909,7 +909,6 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
desc->decode = NFS_PROTO(inode)->decode_dirent;
|
||||
desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
|
||||
|
||||
nfs_block_sillyrename(dentry);
|
||||
if (ctx->pos == 0 || nfs_dir_mapping_need_revalidate(inode))
|
||||
res = nfs_revalidate_mapping(inode, file->f_mapping);
|
||||
if (res < 0)
|
||||
@@ -945,7 +944,6 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
break;
|
||||
} while (!desc->eof);
|
||||
out:
|
||||
nfs_unblock_sillyrename(dentry);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
dfprintk(FILE, "NFS: readdir(%pD2) returns %d\n", file, res);
|
||||
@@ -1398,7 +1396,6 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
|
||||
parent = dentry->d_parent;
|
||||
/* Protect against concurrent sillydeletes */
|
||||
trace_nfs_lookup_enter(dir, dentry, flags);
|
||||
nfs_block_sillyrename(parent);
|
||||
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
|
||||
if (error == -ENOENT)
|
||||
goto no_entry;
|
||||
@@ -1423,7 +1420,6 @@ no_entry:
|
||||
}
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
out_unblock_sillyrename:
|
||||
nfs_unblock_sillyrename(parent);
|
||||
trace_nfs_lookup_exit(dir, dentry, flags, error);
|
||||
nfs4_label_free(label);
|
||||
out:
|
||||
@@ -1535,9 +1531,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
goto out;
|
||||
|
||||
trace_nfs_atomic_open_enter(dir, ctx, open_flags);
|
||||
nfs_block_sillyrename(dentry->d_parent);
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, opened);
|
||||
nfs_unblock_sillyrename(dentry->d_parent);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
|
||||
@@ -1781,7 +1775,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
|
||||
trace_nfs_rmdir_enter(dir, dentry);
|
||||
if (d_really_is_positive(dentry)) {
|
||||
nfs_wait_on_sillyrename(dentry);
|
||||
down_write(&NFS_I(d_inode(dentry))->rmdir_sem);
|
||||
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
|
||||
/* Ensure the VFS deletes this inode */
|
||||
switch (error) {
|
||||
@@ -1791,6 +1785,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
case -ENOENT:
|
||||
nfs_dentry_handle_enoent(dentry);
|
||||
}
|
||||
up_write(&NFS_I(d_inode(dentry))->rmdir_sem);
|
||||
} else
|
||||
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
|
||||
trace_nfs_rmdir_exit(dir, dentry, error);
|
||||
|
Reference in New Issue
Block a user