From: Al Viro Date: Sat, 22 Mar 2025 23:50:20 +0000 (-0400) Subject: rpc_pipe: saner primitive for creating subdirectories X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc1abdca51ed7ddfe3fa8090a5b1f9ef9a792a22;p=thirdparty%2Fkernel%2Fstable.git rpc_pipe: saner primitive for creating subdirectories All users of __rpc_mkdir() have the same form - start_creating(), followed, in case of success, by __rpc_mkdir() and unlocking parent. Combine that into a single helper, expanding __rpc_mkdir() into it, along with the call of __rpc_create_common() in it. Don't mess with d_drop() + d_add() - just d_instantiate() and be done with that. The reason __rpc_create_common() goes for that dance is that dentry it gets might or might not be hashed; here we know it's hashed. Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a61c1173738cd..c3f269aadcaf5 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -524,21 +524,6 @@ static int __rpc_create(struct inode *dir, struct dentry *dentry, return 0; } -static int __rpc_mkdir(struct inode *dir, struct dentry *dentry, - umode_t mode, - const struct file_operations *i_fop, - void *private) -{ - int err; - - err = __rpc_create_common(dir, dentry, S_IFDIR | mode, i_fop, private); - if (err) - return err; - inc_nlink(dir); - fsnotify_mkdir(dir, dentry); - return 0; -} - static void init_pipe(struct rpc_pipe *pipe) { @@ -594,6 +579,35 @@ static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry, return 0; } +static struct dentry *rpc_new_dir(struct dentry *parent, + const char *name, + umode_t mode, + void *private) +{ + struct dentry *dentry = simple_start_creating(parent, name); + struct inode *dir = parent->d_inode; + struct inode *inode; + + if (IS_ERR(dentry)) + return dentry; + + inode = rpc_get_inode(dir->i_sb, S_IFDIR | mode); + if (unlikely(!inode)) { + dput(dentry); + inode_unlock(dir); + return ERR_PTR(-ENOMEM); + } + + inode->i_ino = iunique(dir->i_sb, 100); + rpc_inode_setowner(inode, private); + inc_nlink(dir); + d_instantiate(dentry, inode); + fsnotify_mkdir(dir, dentry); + inode_unlock(dir); + + return dentry; +} + static int rpc_populate(struct dentry *parent, const struct rpc_filelist *files, int start, int eof, @@ -604,14 +618,14 @@ static int rpc_populate(struct dentry *parent, int i, err; for (i = start; i < eof; i++) { - dentry = simple_start_creating(parent, files[i].name); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - goto out_bad; switch (files[i].mode & S_IFMT) { default: BUG(); case S_IFREG: + dentry = simple_start_creating(parent, files[i].name); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto out_bad; err = __rpc_create(dir, dentry, files[i].mode, files[i].i_fop, @@ -619,11 +633,13 @@ static int rpc_populate(struct dentry *parent, inode_unlock(dir); break; case S_IFDIR: - err = __rpc_mkdir(dir, dentry, + dentry = rpc_new_dir(parent, + files[i].name, files[i].mode, - NULL, private); - inode_unlock(dir); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto out_bad; } if (err != 0) goto out_bad; @@ -640,16 +656,11 @@ static struct dentry *rpc_mkdir_populate(struct dentry *parent, int (*populate)(struct dentry *, void *), void *args_populate) { struct dentry *dentry; - struct inode *dir = d_inode(parent); int error; - dentry = simple_start_creating(parent, name); + dentry = rpc_new_dir(parent, name, mode, private); if (IS_ERR(dentry)) return dentry; - error = __rpc_mkdir(dir, dentry, mode, NULL, private); - inode_unlock(dir); - if (error != 0) - return ERR_PTR(error); if (populate != NULL) { error = populate(dentry, args_populate); if (error) {