mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
rpc_pipe: don't overdo directory locking
Don't try to hold directories locked more than VFS requires; lock just before getting a child to be made positive (using simple_start_creating()) and unlock as soon as the child is created. There's no benefit in keeping the parent locked while populating the child - it won't stop dcache lookups anyway. Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
19a6314a99
commit
41a6b9e52b
|
|
@ -594,22 +594,6 @@ static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
|
||||
const char *name)
|
||||
{
|
||||
struct qstr q = QSTR(name);
|
||||
struct dentry *dentry = try_lookup_noperm(&q, parent);
|
||||
if (!dentry) {
|
||||
dentry = d_alloc(parent, &q);
|
||||
if (!dentry)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
if (d_really_is_negative(dentry))
|
||||
return dentry;
|
||||
dput(dentry);
|
||||
return ERR_PTR(-EEXIST);
|
||||
}
|
||||
|
||||
static int rpc_populate(struct dentry *parent,
|
||||
const struct rpc_filelist *files,
|
||||
int start, int eof,
|
||||
|
|
@ -619,9 +603,8 @@ static int rpc_populate(struct dentry *parent,
|
|||
struct dentry *dentry;
|
||||
int i, err;
|
||||
|
||||
inode_lock(dir);
|
||||
for (i = start; i < eof; i++) {
|
||||
dentry = __rpc_lookup_create_exclusive(parent, files[i].name);
|
||||
dentry = simple_start_creating(parent, files[i].name);
|
||||
err = PTR_ERR(dentry);
|
||||
if (IS_ERR(dentry))
|
||||
goto out_bad;
|
||||
|
|
@ -633,20 +616,20 @@ static int rpc_populate(struct dentry *parent,
|
|||
files[i].mode,
|
||||
files[i].i_fop,
|
||||
private);
|
||||
inode_unlock(dir);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
err = __rpc_mkdir(dir, dentry,
|
||||
files[i].mode,
|
||||
NULL,
|
||||
private);
|
||||
inode_unlock(dir);
|
||||
}
|
||||
if (err != 0)
|
||||
goto out_bad;
|
||||
}
|
||||
inode_unlock(dir);
|
||||
return 0;
|
||||
out_bad:
|
||||
inode_unlock(dir);
|
||||
printk(KERN_WARNING "%s: %s failed to populate directory %pd\n",
|
||||
__FILE__, __func__, parent);
|
||||
return err;
|
||||
|
|
@ -660,27 +643,21 @@ static struct dentry *rpc_mkdir_populate(struct dentry *parent,
|
|||
struct inode *dir = d_inode(parent);
|
||||
int error;
|
||||
|
||||
inode_lock_nested(dir, I_MUTEX_PARENT);
|
||||
dentry = __rpc_lookup_create_exclusive(parent, name);
|
||||
dentry = simple_start_creating(parent, name);
|
||||
if (IS_ERR(dentry))
|
||||
goto out;
|
||||
return dentry;
|
||||
error = __rpc_mkdir(dir, dentry, mode, NULL, private);
|
||||
inode_unlock(dir);
|
||||
if (error != 0)
|
||||
goto out_err;
|
||||
return ERR_PTR(error);
|
||||
if (populate != NULL) {
|
||||
error = populate(dentry, args_populate);
|
||||
if (error) {
|
||||
inode_unlock(dir);
|
||||
simple_recursive_removal(dentry, NULL);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
}
|
||||
out:
|
||||
inode_unlock(dir);
|
||||
return dentry;
|
||||
out_err:
|
||||
dentry = ERR_PTR(error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -715,12 +692,9 @@ int rpc_mkpipe_dentry(struct dentry *parent, const char *name,
|
|||
if (pipe->ops->downcall == NULL)
|
||||
umode &= ~0222;
|
||||
|
||||
inode_lock_nested(dir, I_MUTEX_PARENT);
|
||||
dentry = __rpc_lookup_create_exclusive(parent, name);
|
||||
if (IS_ERR(dentry)) {
|
||||
inode_unlock(dir);
|
||||
dentry = simple_start_creating(parent, name);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
}
|
||||
err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
|
||||
private, pipe);
|
||||
if (unlikely(err))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user