diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2012-11-26 03:43:45 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-12-16 20:46:09 -0500 |
commit | 198605a8e2077f174c9834c97b836f535e4e56dd (patch) | |
tree | 1dae7f3529ead027b13ae4737f5b5cedb267d3a0 /fs/btrfs/ioctl.c | |
parent | 3c04ce01053413007b9df88313b8b8e17272b57b (diff) |
Btrfs: get write access when doing resize fs
Steps to reproduce:
# mkfs.btrfs <partition>
# mount -o ro <partition> <mnt0>
# mount -o ro <partition> <mnt1>
# mount -o remount,rw <mnt0>
# umount <mnt0>
# btrfs fi resize 10g <mnt1>
We re-sized a R/O filesystem. The reason is that we just check the R/O flag
of the super block object. It is not enough, because the kernel may set the
R/O flag only for the mount point. We need invoke mnt_want_write_file() to
do a full check.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 10bc65ed736c..2be49b4c82d6 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -1298,12 +1298,13 @@ out_ra: | |||
1298 | return ret; | 1298 | return ret; |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | 1301 | static noinline int btrfs_ioctl_resize(struct file *file, |
1302 | void __user *arg) | 1302 | void __user *arg) |
1303 | { | 1303 | { |
1304 | u64 new_size; | 1304 | u64 new_size; |
1305 | u64 old_size; | 1305 | u64 old_size; |
1306 | u64 devid = 1; | 1306 | u64 devid = 1; |
1307 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
1307 | struct btrfs_ioctl_vol_args *vol_args; | 1308 | struct btrfs_ioctl_vol_args *vol_args; |
1308 | struct btrfs_trans_handle *trans; | 1309 | struct btrfs_trans_handle *trans; |
1309 | struct btrfs_device *device = NULL; | 1310 | struct btrfs_device *device = NULL; |
@@ -1318,6 +1319,10 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
1318 | if (!capable(CAP_SYS_ADMIN)) | 1319 | if (!capable(CAP_SYS_ADMIN)) |
1319 | return -EPERM; | 1320 | return -EPERM; |
1320 | 1321 | ||
1322 | ret = mnt_want_write_file(file); | ||
1323 | if (ret) | ||
1324 | return ret; | ||
1325 | |||
1321 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | 1326 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
1322 | 1)) { | 1327 | 1)) { |
1323 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | 1328 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
@@ -1425,6 +1430,7 @@ out_free: | |||
1425 | kfree(vol_args); | 1430 | kfree(vol_args); |
1426 | out: | 1431 | out: |
1427 | mutex_unlock(&root->fs_info->volume_mutex); | 1432 | mutex_unlock(&root->fs_info->volume_mutex); |
1433 | mnt_drop_write_file(file); | ||
1428 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | 1434 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); |
1429 | return ret; | 1435 | return ret; |
1430 | } | 1436 | } |
@@ -3832,7 +3838,7 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3832 | case BTRFS_IOC_DEFRAG_RANGE: | 3838 | case BTRFS_IOC_DEFRAG_RANGE: |
3833 | return btrfs_ioctl_defrag(file, argp); | 3839 | return btrfs_ioctl_defrag(file, argp); |
3834 | case BTRFS_IOC_RESIZE: | 3840 | case BTRFS_IOC_RESIZE: |
3835 | return btrfs_ioctl_resize(root, argp); | 3841 | return btrfs_ioctl_resize(file, argp); |
3836 | case BTRFS_IOC_ADD_DEV: | 3842 | case BTRFS_IOC_ADD_DEV: |
3837 | return btrfs_ioctl_add_dev(root, argp); | 3843 | return btrfs_ioctl_add_dev(root, argp); |
3838 | case BTRFS_IOC_RM_DEV: | 3844 | case BTRFS_IOC_RM_DEV: |