removals are done with locked_recursive_removal(); switch creations to
simple_start_creating()/d_make_persistent()/simple_done_creating() and
take them to a helper (add_entry()), while we are at it - simpler control
flow that way.

Signed-off-by: Al Viro <v...@zeniv.linux.org.uk>
---
 fs/binfmt_misc.c | 69 ++++++++++++++++++++++--------------------------
 1 file changed, 32 insertions(+), 37 deletions(-)

diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index a839f960cd4a..2093f9dcd321 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -765,14 +765,41 @@ static const struct file_operations bm_entry_operations = 
{
 
 /* /register */
 
+/* add to filesystem */
+static int add_entry(Node *e, struct super_block *sb)
+{
+       struct dentry *dentry = simple_start_creating(sb->s_root, e->name);
+       struct inode *inode;
+       struct binfmt_misc *misc;
+
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+
+       inode = bm_get_inode(sb, S_IFREG | 0644);
+       if (unlikely(!inode)) {
+               simple_done_creating(dentry);
+               return -ENOMEM;
+       }
+
+       refcount_set(&e->users, 1);
+       e->dentry = dentry;
+       inode->i_private = e;
+       inode->i_fop = &bm_entry_operations;
+
+       d_make_persistent(dentry, inode);
+       misc = i_binfmt_misc(inode);
+       write_lock(&misc->entries_lock);
+       list_add(&e->list, &misc->entries);
+       write_unlock(&misc->entries_lock);
+       simple_done_creating(dentry);
+       return 0;
+}
+
 static ssize_t bm_register_write(struct file *file, const char __user *buffer,
                               size_t count, loff_t *ppos)
 {
        Node *e;
-       struct inode *inode;
        struct super_block *sb = file_inode(file)->i_sb;
-       struct dentry *root = sb->s_root, *dentry;
-       struct binfmt_misc *misc;
        int err = 0;
        struct file *f = NULL;
 
@@ -803,39 +830,7 @@ static ssize_t bm_register_write(struct file *file, const 
char __user *buffer,
                e->interp_file = f;
        }
 
-       inode_lock(d_inode(root));
-       dentry = lookup_noperm(&QSTR(e->name), root);
-       err = PTR_ERR(dentry);
-       if (IS_ERR(dentry))
-               goto out;
-
-       err = -EEXIST;
-       if (d_really_is_positive(dentry))
-               goto out2;
-
-       inode = bm_get_inode(sb, S_IFREG | 0644);
-
-       err = -ENOMEM;
-       if (!inode)
-               goto out2;
-
-       refcount_set(&e->users, 1);
-       e->dentry = dget(dentry);
-       inode->i_private = e;
-       inode->i_fop = &bm_entry_operations;
-
-       d_instantiate(dentry, inode);
-       misc = i_binfmt_misc(inode);
-       write_lock(&misc->entries_lock);
-       list_add(&e->list, &misc->entries);
-       write_unlock(&misc->entries_lock);
-
-       err = 0;
-out2:
-       dput(dentry);
-out:
-       inode_unlock(d_inode(root));
-
+       err = add_entry(e, sb);
        if (err) {
                if (f)
                        filp_close(f, NULL);
@@ -1028,7 +1023,7 @@ static struct file_system_type bm_fs_type = {
        .name           = "binfmt_misc",
        .init_fs_context = bm_init_fs_context,
        .fs_flags       = FS_USERNS_MOUNT,
-       .kill_sb        = kill_litter_super,
+       .kill_sb        = kill_anon_super,
 };
 MODULE_ALIAS_FS("binfmt_misc");
 
-- 
2.47.3


Reply via email to