aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:49 -0500
committerIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:49 -0500
commit837d5b6e46d1a4af5b6cc8f2fe83cb5de79a2961 (patch)
tree4ef87d05240e90480749c345274a83094caf66f0 /fs/btrfs/ioctl.c
parent9555c6c180600b40f6e86bd4dc53bf47e06ed663 (diff)
Btrfs: allow for pausing restriper
Implement an ioctl for pausing restriper. This pauses the relocation, but balance is still considered to be "in progress": balance item is not deleted, other volume operations cannot be started, etc. If paused in the middle of profile changing operation we will continue making allocations with the target profile. Add a hook to close_ctree() to pause restriper and free its data structures on unmount. (It's safe to unmount when restriper is in "paused" state, we will resume with the same parameters on the next mount) Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c28
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
3152static 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
3141long btrfs_ioctl(struct file *file, unsigned int 3165long 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;