Btrfs: get write access when setting the default subvolume

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 <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
This commit is contained in:
Miao Xie 2012-11-26 08:43:07 +00:00 committed by Chris Mason
parent 8cd2807f79
commit 3c04ce0105
1 changed files with 28 additions and 12 deletions

View File

@ -2843,12 +2843,19 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
struct btrfs_disk_key disk_key; struct btrfs_disk_key disk_key;
u64 objectid = 0; u64 objectid = 0;
u64 dir_id; u64 dir_id;
int ret;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (copy_from_user(&objectid, argp, sizeof(objectid))) ret = mnt_want_write_file(file);
return -EFAULT; if (ret)
return ret;
if (copy_from_user(&objectid, argp, sizeof(objectid))) {
ret = -EFAULT;
goto out;
}
if (!objectid) if (!objectid)
objectid = root->root_key.objectid; objectid = root->root_key.objectid;
@ -2858,21 +2865,28 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
location.offset = (u64)-1; location.offset = (u64)-1;
new_root = btrfs_read_fs_root_no_name(root->fs_info, &location); new_root = btrfs_read_fs_root_no_name(root->fs_info, &location);
if (IS_ERR(new_root)) if (IS_ERR(new_root)) {
return PTR_ERR(new_root); ret = PTR_ERR(new_root);
goto out;
}
if (btrfs_root_refs(&new_root->root_item) == 0) if (btrfs_root_refs(&new_root->root_item) == 0) {
return -ENOENT; ret = -ENOENT;
goto out;
}
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path) {
return -ENOMEM; ret = -ENOMEM;
goto out;
}
path->leave_spinning = 1; path->leave_spinning = 1;
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
btrfs_free_path(path); 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); dir_id = btrfs_super_root_dir(root->fs_info->super_copy);
@ -2883,7 +2897,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
printk(KERN_ERR "Umm, you don't have the default dir item, " printk(KERN_ERR "Umm, you don't have the default dir item, "
"this isn't going to work\n"); "this isn't going to work\n");
return -ENOENT; ret = -ENOENT;
goto out;
} }
btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key); btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key);
@ -2893,8 +2908,9 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
btrfs_set_fs_incompat(root->fs_info, DEFAULT_SUBVOL); btrfs_set_fs_incompat(root->fs_info, DEFAULT_SUBVOL);
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
out:
return 0; mnt_drop_write_file(file);
return ret;
} }
void btrfs_get_block_group_info(struct list_head *groups_list, void btrfs_get_block_group_info(struct list_head *groups_list,