]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
rpc_pipe: don't overdo directory locking
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 22 Mar 2025 23:39:40 +0000 (19:39 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 3 Jul 2025 02:44:55 +0000 (22:44 -0400)
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>
net/sunrpc/rpc_pipe.c

index dac1c35a642f1d2057eb972b5bfaf9f77a8a62c8..a61c1173738cdb9fd2f687c95fb382a56ea804c0 100644 (file)
@@ -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))