aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2022-03-14 18:12:32 -0700
committerDavid Sterba <dsterba@suse.com>2022-05-16 17:03:08 +0200
commita1fd0c35ffe349a7bbca27dae362932895ee8c4d (patch)
treed34501f25dd57b749816ee121a018b260f00ee58 /fs/btrfs/ioctl.c
parentbtrfs: warn when extent buffer leak test fails (diff)
downloadlinux-dev-a1fd0c35ffe349a7bbca27dae362932895ee8c4d.tar.xz
linux-dev-a1fd0c35ffe349a7bbca27dae362932895ee8c4d.zip
btrfs: allocate inode outside of btrfs_new_inode()
Instead of calling new_inode() and inode_init_owner() inside of btrfs_new_inode(), do it in the callers. This allows us to pass in just the inode instead of the mnt_userns and mode and removes the need for memalloc_nofs_{save,restores}() since we do it before starting a transaction. In create_subvol(), it also means we no longer have to look up the inode again to instantiate it. This also paves the way for some more cleanups in later patches. This also removes the comments about Smack checking i_op, which are no longer true since commit 5d6c31910bc0 ("xattr: Add __vfs_{get,set,remove}xattr helpers"). Now it checks inode->i_opflags & IOP_XATTR, which is set based on sb->s_xattr. Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 4a015579a46e..4b903517fdc3 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -587,6 +587,12 @@ static noinline int create_subvol(struct user_namespace *mnt_userns,
if (ret < 0)
goto out_root_item;
+ inode = btrfs_new_subvol_inode(mnt_userns, dir);
+ if (!inode) {
+ ret = -ENOMEM;
+ goto out_anon_dev;
+ }
+
btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
/*
* The same as the snapshot creation, please see the comment
@@ -594,13 +600,13 @@ static noinline int create_subvol(struct user_namespace *mnt_userns,
*/
ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 8, false);
if (ret)
- goto out_anon_dev;
+ goto out_inode;
trans = btrfs_start_transaction(root, 0);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
btrfs_subvolume_release_metadata(root, &block_rsv);
- goto out_anon_dev;
+ goto out_inode;
}
trans->block_rsv = &block_rsv;
trans->bytes_reserved = block_rsv.size;
@@ -683,16 +689,16 @@ static noinline int create_subvol(struct user_namespace *mnt_userns,
}
/* anon_dev is owned by new_root now. */
anon_dev = 0;
+ BTRFS_I(inode)->root = new_root;
+ /* ... and new_root is owned by inode now. */
ret = btrfs_record_root_in_trans(trans, new_root);
if (ret) {
- btrfs_put_root(new_root);
btrfs_abort_transaction(trans, ret);
goto out;
}
- ret = btrfs_create_subvol_root(trans, new_root, root, mnt_userns);
- btrfs_put_root(new_root);
+ ret = btrfs_create_subvol_root(trans, root, inode);
if (ret) {
/* We potentially lose an unused inode item here */
btrfs_abort_transaction(trans, ret);
@@ -745,11 +751,11 @@ out:
ret = btrfs_commit_transaction(trans);
if (!ret) {
- inode = btrfs_lookup_dentry(dir, dentry);
- if (IS_ERR(inode))
- return PTR_ERR(inode);
d_instantiate(dentry, inode);
+ inode = NULL;
}
+out_inode:
+ iput(inode);
out_anon_dev:
if (anon_dev)
free_anon_bdev(anon_dev);