diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 29b3a94933f0..f572c53dda4f 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3072,6 +3072,11 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, | |||
3072 | 3072 | ||
3073 | bargs->flags = bctl->flags; | 3073 | bargs->flags = bctl->flags; |
3074 | 3074 | ||
3075 | if (atomic_read(&fs_info->balance_running)) | ||
3076 | bargs->state |= BTRFS_BALANCE_STATE_RUNNING; | ||
3077 | if (atomic_read(&fs_info->balance_pause_req)) | ||
3078 | bargs->state |= BTRFS_BALANCE_STATE_PAUSE_REQ; | ||
3079 | |||
3075 | memcpy(&bargs->data, &bctl->data, sizeof(bargs->data)); | 3080 | memcpy(&bargs->data, &bctl->data, sizeof(bargs->data)); |
3076 | memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta)); | 3081 | memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta)); |
3077 | memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys)); | 3082 | memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys)); |
@@ -3103,6 +3108,11 @@ static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) | |||
3103 | bargs = NULL; | 3108 | bargs = NULL; |
3104 | } | 3109 | } |
3105 | 3110 | ||
3111 | if (fs_info->balance_ctl) { | ||
3112 | ret = -EINPROGRESS; | ||
3113 | goto out_bargs; | ||
3114 | } | ||
3115 | |||
3106 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); | 3116 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); |
3107 | if (!bctl) { | 3117 | if (!bctl) { |
3108 | ret = -ENOMEM; | 3118 | ret = -ENOMEM; |
@@ -3123,7 +3133,8 @@ static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) | |||
3123 | 3133 | ||
3124 | ret = btrfs_balance(bctl, bargs); | 3134 | ret = btrfs_balance(bctl, bargs); |
3125 | /* | 3135 | /* |
3126 | * bctl is freed in __cancel_balance | 3136 | * bctl is freed in __cancel_balance or in free_fs_info if |
3137 | * restriper was paused all the way until unmount | ||
3127 | */ | 3138 | */ |
3128 | if (arg) { | 3139 | if (arg) { |
3129 | if (copy_to_user(arg, bargs, sizeof(*bargs))) | 3140 | if (copy_to_user(arg, bargs, sizeof(*bargs))) |
@@ -3138,6 +3149,19 @@ out: | |||
3138 | return ret; | 3149 | return ret; |
3139 | } | 3150 | } |
3140 | 3151 | ||
3152 | static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd) | ||
3153 | { | ||
3154 | if (!capable(CAP_SYS_ADMIN)) | ||
3155 | return -EPERM; | ||
3156 | |||
3157 | switch (cmd) { | ||
3158 | case BTRFS_BALANCE_CTL_PAUSE: | ||
3159 | return btrfs_pause_balance(root->fs_info); | ||
3160 | } | ||
3161 | |||
3162 | return -EINVAL; | ||
3163 | } | ||
3164 | |||
3141 | long btrfs_ioctl(struct file *file, unsigned int | 3165 | long btrfs_ioctl(struct file *file, unsigned int |
3142 | cmd, unsigned long arg) | 3166 | cmd, unsigned long arg) |
3143 | { | 3167 | { |
@@ -3216,6 +3240,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3216 | return btrfs_ioctl_scrub_progress(root, argp); | 3240 | return btrfs_ioctl_scrub_progress(root, argp); |
3217 | case BTRFS_IOC_BALANCE_V2: | 3241 | case BTRFS_IOC_BALANCE_V2: |
3218 | return btrfs_ioctl_balance(root, argp); | 3242 | return btrfs_ioctl_balance(root, argp); |
3243 | case BTRFS_IOC_BALANCE_CTL: | ||
3244 | return btrfs_ioctl_balance_ctl(root, arg); | ||
3219 | } | 3245 | } |
3220 | 3246 | ||
3221 | return -ENOTTY; | 3247 | return -ENOTTY; |