aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2012-11-26 03:44:50 -0500
committerChris Mason <chris.mason@fusionio.com>2012-12-16 20:46:09 -0500
commitda24927b1e1925da5c1885cb483231dabe027e15 (patch)
tree6d28cb9342d4251a8eb0116f79ee3816843c9a61 /fs
parent198605a8e2077f174c9834c97b836f535e4e56dd (diff)
Btrfs: get write access when removing a device
Steps to reproduce: # mkfs.btrfs -d single -m single <disk0> <disk1> # mount -o ro <disk0> <mnt0> # mount -o ro <disk0> <mnt1> # mount -o remount,rw <mnt0> # umount <mnt0> # btrfs device delete <disk1> <mnt1> We can remove a device from 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')
-rw-r--r--fs/btrfs/ioctl.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 2be49b4c82d6..ee36009f8aa1 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2270,20 +2270,23 @@ out:
2270 return ret; 2270 return ret;
2271} 2271}
2272 2272
2273static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) 2273static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
2274{ 2274{
2275 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
2275 struct btrfs_ioctl_vol_args *vol_args; 2276 struct btrfs_ioctl_vol_args *vol_args;
2276 int ret; 2277 int ret;
2277 2278
2278 if (!capable(CAP_SYS_ADMIN)) 2279 if (!capable(CAP_SYS_ADMIN))
2279 return -EPERM; 2280 return -EPERM;
2280 2281
2281 if (root->fs_info->sb->s_flags & MS_RDONLY) 2282 ret = mnt_want_write_file(file);
2282 return -EROFS; 2283 if (ret)
2284 return ret;
2283 2285
2284 if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, 2286 if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
2285 1)) { 2287 1)) {
2286 pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); 2288 pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
2289 mnt_drop_write_file(file);
2287 return -EINPROGRESS; 2290 return -EINPROGRESS;
2288 } 2291 }
2289 2292
@@ -2300,6 +2303,7 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)
2300 kfree(vol_args); 2303 kfree(vol_args);
2301out: 2304out:
2302 mutex_unlock(&root->fs_info->volume_mutex); 2305 mutex_unlock(&root->fs_info->volume_mutex);
2306 mnt_drop_write_file(file);
2303 atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); 2307 atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
2304 return ret; 2308 return ret;
2305} 2309}
@@ -3842,7 +3846,7 @@ long btrfs_ioctl(struct file *file, unsigned int
3842 case BTRFS_IOC_ADD_DEV: 3846 case BTRFS_IOC_ADD_DEV:
3843 return btrfs_ioctl_add_dev(root, argp); 3847 return btrfs_ioctl_add_dev(root, argp);
3844 case BTRFS_IOC_RM_DEV: 3848 case BTRFS_IOC_RM_DEV:
3845 return btrfs_ioctl_rm_dev(root, argp); 3849 return btrfs_ioctl_rm_dev(file, argp);
3846 case BTRFS_IOC_FS_INFO: 3850 case BTRFS_IOC_FS_INFO:
3847 return btrfs_ioctl_fs_info(root, argp); 3851 return btrfs_ioctl_fs_info(root, argp);
3848 case BTRFS_IOC_DEV_INFO: 3852 case BTRFS_IOC_DEV_INFO: