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:
parent
8cd2807f79
commit
3c04ce0105
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue