summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2025-03-22 19:39:40 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2025-07-02 22:44:55 -0400
commit41a6b9e52b21544c334830bfe68fb78d6677caa0 (patch)
tree7b9ea3db637a3e2eb27a01a759e6fe14f6ebfbd3
parent19a6314a997f6adde0c100ecf9224d1ab43c9603 (diff)
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>
-rw-r--r--net/sunrpc/rpc_pipe.c44
1 files changed, 9 insertions, 35 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index dac1c35a642f..a61c1173738c 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -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))