When wen want to set the default subvolume, we must get write access, or
we will change the R/O file system.

Signed-off-by: Miao Xie <[email protected]>
---
 fs/btrfs/ioctl.c | 40 ++++++++++++++++++++++++++++------------
 1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 5102747..7d0214b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2823,12 +2823,19 @@ static long btrfs_ioctl_default_subvol(struct file 
*file, void __user *argp)
        struct btrfs_disk_key disk_key;
        u64 objectid = 0;
        u64 dir_id;
+       int ret;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (copy_from_user(&objectid, argp, sizeof(objectid)))
-               return -EFAULT;
+       ret = mnt_want_write_file(file);
+       if (ret)
+               return ret;
+
+       if (copy_from_user(&objectid, argp, sizeof(objectid))) {
+               ret = -EFAULT;
+               goto out;
+       }
 
        if (!objectid)
                objectid = root->root_key.objectid;
@@ -2838,21 +2845,28 @@ static long btrfs_ioctl_default_subvol(struct file 
*file, void __user *argp)
        location.offset = (u64)-1;
 
        new_root = btrfs_read_fs_root_no_name(root->fs_info, &location);
-       if (IS_ERR(new_root))
-               return PTR_ERR(new_root);
+       if (IS_ERR(new_root)) {
+               ret = PTR_ERR(new_root);
+               goto out;
+       }
 
-       if (btrfs_root_refs(&new_root->root_item) == 0)
-               return -ENOENT;
+       if (btrfs_root_refs(&new_root->root_item) == 0) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               ret = -ENOMEM;
+               goto out;
+       }
        path->leave_spinning = 1;
 
        trans = btrfs_start_transaction(root, 1);
        if (IS_ERR(trans)) {
                btrfs_free_path(path);
-               return PTR_ERR(trans);
+               ret = PTR_ERR(trans);
+               goto out;
        }
 
        dir_id = btrfs_super_root_dir(root->fs_info->super_copy);
@@ -2863,7 +2877,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, 
void __user *argp)
                btrfs_end_transaction(trans, root);
                printk(KERN_ERR "Umm, you don't have the default dir item, "
                       "this isn't going to work\n");
-               return -ENOENT;
+               ret = -ENOENT;
+               goto out;
        }
 
        btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key);
@@ -2873,8 +2888,9 @@ static long btrfs_ioctl_default_subvol(struct file *file, 
void __user *argp)
 
        btrfs_set_fs_incompat(root->fs_info, DEFAULT_SUBVOL);
        btrfs_end_transaction(trans, root);
-
-       return 0;
+out:
+       mnt_drop_write_file(file);
+       return ret;
 }
 
 void btrfs_get_block_group_info(struct list_head *groups_list,
-- 
1.7.11.7

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to