convert binfmt_misc

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 <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2024-05-13 22:02:44 -06:00
parent b85d6b2419
commit 7beafd51c4
1 changed files with 32 additions and 37 deletions

View File

@ -765,14 +765,41 @@ static const struct file_operations bm_entry_operations = {
/* /register */ /* /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, static ssize_t bm_register_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
Node *e; Node *e;
struct inode *inode;
struct super_block *sb = file_inode(file)->i_sb; struct super_block *sb = file_inode(file)->i_sb;
struct dentry *root = sb->s_root, *dentry;
struct binfmt_misc *misc;
int err = 0; int err = 0;
struct file *f = NULL; 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; e->interp_file = f;
} }
inode_lock(d_inode(root)); err = add_entry(e, sb);
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));
if (err) { if (err) {
if (f) if (f)
filp_close(f, NULL); filp_close(f, NULL);
@ -1028,7 +1023,7 @@ static struct file_system_type bm_fs_type = {
.name = "binfmt_misc", .name = "binfmt_misc",
.init_fs_context = bm_init_fs_context, .init_fs_context = bm_init_fs_context,
.fs_flags = FS_USERNS_MOUNT, .fs_flags = FS_USERNS_MOUNT,
.kill_sb = kill_litter_super, .kill_sb = kill_anon_super,
}; };
MODULE_ALIAS_FS("binfmt_misc"); MODULE_ALIAS_FS("binfmt_misc");