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>
This commit is contained in:
Al Viro 2024-02-19 23:32:22 -05:00
parent 3829b30e77
commit 8be22c4964

View File

@ -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;