diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 85e546ffe3c7..1e7a9bac31ab 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3065,7 +3065,7 @@ out: | |||
3065 | return ret; | 3065 | return ret; |
3066 | } | 3066 | } |
3067 | 3067 | ||
3068 | void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, | 3068 | void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock, |
3069 | struct btrfs_ioctl_balance_args *bargs) | 3069 | struct btrfs_ioctl_balance_args *bargs) |
3070 | { | 3070 | { |
3071 | struct btrfs_balance_control *bctl = fs_info->balance_ctl; | 3071 | struct btrfs_balance_control *bctl = fs_info->balance_ctl; |
@@ -3082,6 +3082,14 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, | |||
3082 | memcpy(&bargs->data, &bctl->data, sizeof(bargs->data)); | 3082 | memcpy(&bargs->data, &bctl->data, sizeof(bargs->data)); |
3083 | memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta)); | 3083 | memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta)); |
3084 | memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys)); | 3084 | memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys)); |
3085 | |||
3086 | if (lock) { | ||
3087 | spin_lock(&fs_info->balance_lock); | ||
3088 | memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat)); | ||
3089 | spin_unlock(&fs_info->balance_lock); | ||
3090 | } else { | ||
3091 | memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat)); | ||
3092 | } | ||
3085 | } | 3093 | } |
3086 | 3094 | ||
3087 | static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) | 3095 | static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) |
@@ -3181,6 +3189,39 @@ static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd) | |||
3181 | return -EINVAL; | 3189 | return -EINVAL; |
3182 | } | 3190 | } |
3183 | 3191 | ||
3192 | static long btrfs_ioctl_balance_progress(struct btrfs_root *root, | ||
3193 | void __user *arg) | ||
3194 | { | ||
3195 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
3196 | struct btrfs_ioctl_balance_args *bargs; | ||
3197 | int ret = 0; | ||
3198 | |||
3199 | if (!capable(CAP_SYS_ADMIN)) | ||
3200 | return -EPERM; | ||
3201 | |||
3202 | mutex_lock(&fs_info->balance_mutex); | ||
3203 | if (!fs_info->balance_ctl) { | ||
3204 | ret = -ENOTCONN; | ||
3205 | goto out; | ||
3206 | } | ||
3207 | |||
3208 | bargs = kzalloc(sizeof(*bargs), GFP_NOFS); | ||
3209 | if (!bargs) { | ||
3210 | ret = -ENOMEM; | ||
3211 | goto out; | ||
3212 | } | ||
3213 | |||
3214 | update_ioctl_balance_args(fs_info, 1, bargs); | ||
3215 | |||
3216 | if (copy_to_user(arg, bargs, sizeof(*bargs))) | ||
3217 | ret = -EFAULT; | ||
3218 | |||
3219 | kfree(bargs); | ||
3220 | out: | ||
3221 | mutex_unlock(&fs_info->balance_mutex); | ||
3222 | return ret; | ||
3223 | } | ||
3224 | |||
3184 | long btrfs_ioctl(struct file *file, unsigned int | 3225 | long btrfs_ioctl(struct file *file, unsigned int |
3185 | cmd, unsigned long arg) | 3226 | cmd, unsigned long arg) |
3186 | { | 3227 | { |
@@ -3261,6 +3302,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3261 | return btrfs_ioctl_balance(root, argp); | 3302 | return btrfs_ioctl_balance(root, argp); |
3262 | case BTRFS_IOC_BALANCE_CTL: | 3303 | case BTRFS_IOC_BALANCE_CTL: |
3263 | return btrfs_ioctl_balance_ctl(root, arg); | 3304 | return btrfs_ioctl_balance_ctl(root, arg); |
3305 | case BTRFS_IOC_BALANCE_PROGRESS: | ||
3306 | return btrfs_ioctl_balance_progress(root, argp); | ||
3264 | } | 3307 | } |
3265 | 3308 | ||
3266 | return -ENOTTY; | 3309 | return -ENOTTY; |