mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
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:
parent
3829b30e77
commit
8be22c4964
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user