diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2024-02-19 23:32:22 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2025-07-02 22:44:55 -0400 |
commit | 8be22c49646e47452e74aa0b97ea50fb04c271ed (patch) | |
tree | d36df0f341440f0eb28048673b671e6617c927eb /net/sunrpc/rpc_pipe.c | |
parent | 3829b30e771bbfff62fbe7eff555e7a6e0d4b5cd (diff) |
rpc_populate(): lift cleanup into callers
rpc_populate() is called either from fill_super (where we don't
need to remove any files on failure - rpc_kill_sb() will take
them all out anyway) or from rpc_mkdir_populate(), where we need
to remove the directory we'd been trying to populate along with
whatever we'd put into it before we failed. Simpler to combine
that into simple_recursive_removal() there.
Note that rpc_pipe is overlocking directories quite a bit -
locked parent is no obstacle to finding a child in dcache, so
keeping it locked won't prevent userland observing a partially
built subtree.
All we need is to follow minimal VFS requirements; it's not
as if clients used directory locking for exclusion - tree
changes are serialized, but that's done on ->pipefs_sb_lock.
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/sunrpc/rpc_pipe.c')
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 71 |
1 files changed, 5 insertions, 66 deletions
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 67621a94f67b2..46fa00ac5e0e7 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -594,32 +594,6 @@ static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry, return 0; } -static int __rpc_rmdir(struct inode *dir, struct dentry *dentry) -{ - int ret; - - dget(dentry); - ret = simple_rmdir(dir, dentry); - d_drop(dentry); - if (!ret) - fsnotify_rmdir(dir, dentry); - dput(dentry); - return ret; -} - -static int __rpc_unlink(struct inode *dir, struct dentry *dentry) -{ - int ret; - - dget(dentry); - ret = simple_unlink(dir, dentry); - d_drop(dentry); - if (!ret) - fsnotify_unlink(dir, dentry); - dput(dentry); - return ret; -} - static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, const char *name) { @@ -636,41 +610,6 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, return ERR_PTR(-EEXIST); } -/* - * FIXME: This probably has races. - */ -static void __rpc_depopulate(struct dentry *parent, - const struct rpc_filelist *files, - int start, int eof) -{ - struct inode *dir = d_inode(parent); - struct dentry *dentry; - struct qstr name; - int i; - - for (i = start; i < eof; i++) { - name.name = files[i].name; - name.len = strlen(files[i].name); - dentry = try_lookup_noperm(&name, parent); - - if (dentry == NULL) - continue; - if (d_really_is_negative(dentry)) - goto next; - switch (d_inode(dentry)->i_mode & S_IFMT) { - default: - BUG(); - case S_IFREG: - __rpc_unlink(dir, dentry); - break; - case S_IFDIR: - __rpc_rmdir(dir, dentry); - } -next: - dput(dentry); - } -} - static int rpc_populate(struct dentry *parent, const struct rpc_filelist *files, int start, int eof, @@ -707,7 +646,6 @@ static int rpc_populate(struct dentry *parent, inode_unlock(dir); return 0; out_bad: - __rpc_depopulate(parent, files, start, eof); inode_unlock(dir); printk(KERN_WARNING "%s: %s failed to populate directory %pd\n", __FILE__, __func__, parent); @@ -731,14 +669,15 @@ static struct dentry *rpc_mkdir_populate(struct dentry *parent, goto out_err; if (populate != NULL) { error = populate(dentry, args_populate); - if (error) - goto err_rmdir; + if (error) { + inode_unlock(dir); + simple_recursive_removal(dentry, NULL); + return ERR_PTR(error); + } } out: inode_unlock(dir); return dentry; -err_rmdir: - __rpc_rmdir(dir, dentry); out_err: dentry = ERR_PTR(error); goto out; |