aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index ee36009f8aa1..12b18c01b911 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3127,10 +3127,11 @@ static noinline long btrfs_ioctl_wait_sync(struct btrfs_root *root,
3127 return btrfs_wait_for_commit(root, transid); 3127 return btrfs_wait_for_commit(root, transid);
3128} 3128}
3129 3129
3130static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg) 3130static long btrfs_ioctl_scrub(struct file *file, void __user *arg)
3131{ 3131{
3132 int ret; 3132 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
3133 struct btrfs_ioctl_scrub_args *sa; 3133 struct btrfs_ioctl_scrub_args *sa;
3134 int ret;
3134 3135
3135 if (!capable(CAP_SYS_ADMIN)) 3136 if (!capable(CAP_SYS_ADMIN))
3136 return -EPERM; 3137 return -EPERM;
@@ -3139,6 +3140,12 @@ static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg)
3139 if (IS_ERR(sa)) 3140 if (IS_ERR(sa))
3140 return PTR_ERR(sa); 3141 return PTR_ERR(sa);
3141 3142
3143 if (!(sa->flags & BTRFS_SCRUB_READONLY)) {
3144 ret = mnt_want_write_file(file);
3145 if (ret)
3146 goto out;
3147 }
3148
3142 ret = btrfs_scrub_dev(root->fs_info, sa->devid, sa->start, sa->end, 3149 ret = btrfs_scrub_dev(root->fs_info, sa->devid, sa->start, sa->end,
3143 &sa->progress, sa->flags & BTRFS_SCRUB_READONLY, 3150 &sa->progress, sa->flags & BTRFS_SCRUB_READONLY,
3144 0); 3151 0);
@@ -3146,6 +3153,9 @@ static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg)
3146 if (copy_to_user(arg, sa, sizeof(*sa))) 3153 if (copy_to_user(arg, sa, sizeof(*sa)))
3147 ret = -EFAULT; 3154 ret = -EFAULT;
3148 3155
3156 if (!(sa->flags & BTRFS_SCRUB_READONLY))
3157 mnt_drop_write_file(file);
3158out:
3149 kfree(sa); 3159 kfree(sa);
3150 return ret; 3160 return ret;
3151} 3161}
@@ -3879,7 +3889,7 @@ long btrfs_ioctl(struct file *file, unsigned int
3879 case BTRFS_IOC_WAIT_SYNC: 3889 case BTRFS_IOC_WAIT_SYNC:
3880 return btrfs_ioctl_wait_sync(root, argp); 3890 return btrfs_ioctl_wait_sync(root, argp);
3881 case BTRFS_IOC_SCRUB: 3891 case BTRFS_IOC_SCRUB:
3882 return btrfs_ioctl_scrub(root, argp); 3892 return btrfs_ioctl_scrub(file, argp);
3883 case BTRFS_IOC_SCRUB_CANCEL: 3893 case BTRFS_IOC_SCRUB_CANCEL:
3884 return btrfs_ioctl_scrub_cancel(root, argp); 3894 return btrfs_ioctl_scrub_cancel(root, argp);
3885 case BTRFS_IOC_SCRUB_PROGRESS: 3895 case BTRFS_IOC_SCRUB_PROGRESS: