diff options
author | Josef Bacik <josef@toxicpanda.com> | 2020-01-24 09:32:37 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2020-03-23 17:01:29 +0100 |
commit | 2a2b5d62026633d6fc515b1c0fe3a5e58cae7891 (patch) | |
tree | 2cb741f40a0f39b1fda7da4b659a9bd422ae4353 /fs/btrfs/ioctl.c | |
parent | 04734e844894ccdfcb907d10eec1433e19d4918a (diff) | |
download | linux-2a2b5d62026633d6fc515b1c0fe3a5e58cae7891.tar.bz2 |
btrfs: hold ref on root in btrfs_ioctl_default_subvol
We look up an arbitrary fs root here, we need to hold a ref on the root
for the duration.
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0aa47bc3e172..5fde22db1727 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3986,7 +3986,7 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) struct btrfs_root *new_root; struct btrfs_dir_item *di; struct btrfs_trans_handle *trans; - struct btrfs_path *path; + struct btrfs_path *path = NULL; struct btrfs_key location; struct btrfs_disk_key disk_key; u64 objectid = 0; @@ -4017,44 +4017,50 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) ret = PTR_ERR(new_root); goto out; } - if (!is_fstree(new_root->root_key.objectid)) { + if (!btrfs_grab_fs_root(new_root)) { ret = -ENOENT; goto out; } + if (!is_fstree(new_root->root_key.objectid)) { + ret = -ENOENT; + goto out_free; + } path = btrfs_alloc_path(); if (!path) { ret = -ENOMEM; - goto out; + goto out_free; } path->leave_spinning = 1; trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) { - btrfs_free_path(path); ret = PTR_ERR(trans); - goto out; + goto out_free; } dir_id = btrfs_super_root_dir(fs_info->super_copy); di = btrfs_lookup_dir_item(trans, fs_info->tree_root, path, dir_id, "default", 7, 1); if (IS_ERR_OR_NULL(di)) { - btrfs_free_path(path); + btrfs_release_path(path); btrfs_end_transaction(trans); btrfs_err(fs_info, "Umm, you don't have the default diritem, this isn't going to work"); ret = -ENOENT; - goto out; + goto out_free; } btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key); btrfs_set_dir_item_key(path->nodes[0], di, &disk_key); btrfs_mark_buffer_dirty(path->nodes[0]); - btrfs_free_path(path); + btrfs_release_path(path); btrfs_set_fs_incompat(fs_info, DEFAULT_SUBVOL); btrfs_end_transaction(trans); +out_free: + btrfs_put_fs_root(new_root); + btrfs_free_path(path); out: mnt_drop_write_file(file); return ret; |