aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c6
-rw-r--r--fs/btrfs/ioctl.c28
-rw-r--r--fs/btrfs/ioctl.h7
-rw-r--r--fs/btrfs/volumes.c51
-rw-r--r--fs/btrfs/volumes.h1
6 files changed, 94 insertions, 3 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 99eb2bcd9aa7..1afda75d5414 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1214,7 +1214,10 @@ struct btrfs_fs_info {
1214 /* restriper state */ 1214 /* restriper state */
1215 spinlock_t balance_lock; 1215 spinlock_t balance_lock;
1216 struct mutex balance_mutex; 1216 struct mutex balance_mutex;
1217 atomic_t balance_running;
1218 atomic_t balance_pause_req;
1217 struct btrfs_balance_control *balance_ctl; 1219 struct btrfs_balance_control *balance_ctl;
1220 wait_queue_head_t balance_wait_q;
1218 1221
1219 unsigned data_chunk_allocations; 1222 unsigned data_chunk_allocations;
1220 unsigned metadata_ratio; 1223 unsigned metadata_ratio;
@@ -2658,6 +2661,7 @@ static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
2658} 2661}
2659static inline void free_fs_info(struct btrfs_fs_info *fs_info) 2662static inline void free_fs_info(struct btrfs_fs_info *fs_info)
2660{ 2663{
2664 kfree(fs_info->balance_ctl);
2661 kfree(fs_info->delayed_root); 2665 kfree(fs_info->delayed_root);
2662 kfree(fs_info->extent_root); 2666 kfree(fs_info->extent_root);
2663 kfree(fs_info->tree_root); 2667 kfree(fs_info->tree_root);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index eb7a11ac5b73..8ce837407800 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2004,7 +2004,10 @@ struct btrfs_root *open_ctree(struct super_block *sb,
2004 2004
2005 spin_lock_init(&fs_info->balance_lock); 2005 spin_lock_init(&fs_info->balance_lock);
2006 mutex_init(&fs_info->balance_mutex); 2006 mutex_init(&fs_info->balance_mutex);
2007 atomic_set(&fs_info->balance_running, 0);
2008 atomic_set(&fs_info->balance_pause_req, 0);
2007 fs_info->balance_ctl = NULL; 2009 fs_info->balance_ctl = NULL;
2010 init_waitqueue_head(&fs_info->balance_wait_q);
2008 2011
2009 sb->s_blocksize = 4096; 2012 sb->s_blocksize = 4096;
2010 sb->s_blocksize_bits = blksize_bits(4096); 2013 sb->s_blocksize_bits = blksize_bits(4096);
@@ -2980,6 +2983,9 @@ int close_ctree(struct btrfs_root *root)
2980 fs_info->closing = 1; 2983 fs_info->closing = 1;
2981 smp_mb(); 2984 smp_mb();
2982 2985
2986 /* pause restriper - we want to resume on mount */
2987 btrfs_pause_balance(root->fs_info);
2988
2983 btrfs_scrub_cancel(root); 2989 btrfs_scrub_cancel(root);
2984 2990
2985 /* wait for any defraggers to finish */ 2991 /* wait for any defraggers to finish */
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;
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index c8b37d2c0d77..e972e11a8d77 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -109,6 +109,9 @@ struct btrfs_ioctl_fs_info_args {
109 __u64 reserved[124]; /* pad to 1k */ 109 __u64 reserved[124]; /* pad to 1k */
110}; 110};
111 111
112/* balance control ioctl modes */
113#define BTRFS_BALANCE_CTL_PAUSE 1
114
112/* 115/*
113 * this is packed, because it should be exactly the same as its disk 116 * this is packed, because it should be exactly the same as its disk
114 * byte order counterpart (struct btrfs_disk_balance_args) 117 * byte order counterpart (struct btrfs_disk_balance_args)
@@ -137,6 +140,9 @@ struct btrfs_balance_progress {
137 __u64 completed; /* # of chunks relocated so far */ 140 __u64 completed; /* # of chunks relocated so far */
138}; 141};
139 142
143#define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0)
144#define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1)
145
140struct btrfs_ioctl_balance_args { 146struct btrfs_ioctl_balance_args {
141 __u64 flags; /* in/out */ 147 __u64 flags; /* in/out */
142 __u64 state; /* out */ 148 __u64 state; /* out */
@@ -315,6 +321,7 @@ struct btrfs_ioctl_logical_ino_args {
315 struct btrfs_ioctl_fs_info_args) 321 struct btrfs_ioctl_fs_info_args)
316#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \ 322#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \
317 struct btrfs_ioctl_balance_args) 323 struct btrfs_ioctl_balance_args)
324#define BTRFS_IOC_BALANCE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int)
318#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \ 325#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
319 struct btrfs_ioctl_ino_path_args) 326 struct btrfs_ioctl_ino_path_args)
320#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ 327#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e0160607e6e2..d32660ce753d 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2492,6 +2492,11 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
2492 key.type = BTRFS_CHUNK_ITEM_KEY; 2492 key.type = BTRFS_CHUNK_ITEM_KEY;
2493 2493
2494 while (1) { 2494 while (1) {
2495 if (atomic_read(&fs_info->balance_pause_req)) {
2496 ret = -ECANCELED;
2497 goto error;
2498 }
2499
2495 ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); 2500 ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
2496 if (ret < 0) 2501 if (ret < 0)
2497 goto error; 2502 goto error;
@@ -2553,6 +2558,11 @@ error:
2553 return ret; 2558 return ret;
2554} 2559}
2555 2560
2561static inline int balance_need_close(struct btrfs_fs_info *fs_info)
2562{
2563 return atomic_read(&fs_info->balance_pause_req) == 0;
2564}
2565
2556static void __cancel_balance(struct btrfs_fs_info *fs_info) 2566static void __cancel_balance(struct btrfs_fs_info *fs_info)
2557{ 2567{
2558 int ret; 2568 int ret;
@@ -2575,7 +2585,8 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
2575 u64 allowed; 2585 u64 allowed;
2576 int ret; 2586 int ret;
2577 2587
2578 if (btrfs_fs_closing(fs_info)) { 2588 if (btrfs_fs_closing(fs_info) ||
2589 atomic_read(&fs_info->balance_pause_req)) {
2579 ret = -EINVAL; 2590 ret = -EINVAL;
2580 goto out; 2591 goto out;
2581 } 2592 }
@@ -2680,18 +2691,25 @@ do_balance:
2680 spin_unlock(&fs_info->balance_lock); 2691 spin_unlock(&fs_info->balance_lock);
2681 } 2692 }
2682 2693
2694 atomic_inc(&fs_info->balance_running);
2683 mutex_unlock(&fs_info->balance_mutex); 2695 mutex_unlock(&fs_info->balance_mutex);
2684 2696
2685 ret = __btrfs_balance(fs_info); 2697 ret = __btrfs_balance(fs_info);
2686 2698
2687 mutex_lock(&fs_info->balance_mutex); 2699 mutex_lock(&fs_info->balance_mutex);
2700 atomic_dec(&fs_info->balance_running);
2688 2701
2689 if (bargs) { 2702 if (bargs) {
2690 memset(bargs, 0, sizeof(*bargs)); 2703 memset(bargs, 0, sizeof(*bargs));
2691 update_ioctl_balance_args(fs_info, bargs); 2704 update_ioctl_balance_args(fs_info, bargs);
2692 } 2705 }
2693 2706
2694 __cancel_balance(fs_info); 2707 if ((ret && ret != -ECANCELED && ret != -ENOSPC) ||
2708 balance_need_close(fs_info)) {
2709 __cancel_balance(fs_info);
2710 }
2711
2712 wake_up(&fs_info->balance_wait_q);
2695 2713
2696 return ret; 2714 return ret;
2697out: 2715out:
@@ -2785,6 +2803,35 @@ out:
2785 return ret; 2803 return ret;
2786} 2804}
2787 2805
2806int btrfs_pause_balance(struct btrfs_fs_info *fs_info)
2807{
2808 int ret = 0;
2809
2810 mutex_lock(&fs_info->balance_mutex);
2811 if (!fs_info->balance_ctl) {
2812 mutex_unlock(&fs_info->balance_mutex);
2813 return -ENOTCONN;
2814 }
2815
2816 if (atomic_read(&fs_info->balance_running)) {
2817 atomic_inc(&fs_info->balance_pause_req);
2818 mutex_unlock(&fs_info->balance_mutex);
2819
2820 wait_event(fs_info->balance_wait_q,
2821 atomic_read(&fs_info->balance_running) == 0);
2822
2823 mutex_lock(&fs_info->balance_mutex);
2824 /* we are good with balance_ctl ripped off from under us */
2825 BUG_ON(atomic_read(&fs_info->balance_running));
2826 atomic_dec(&fs_info->balance_pause_req);
2827 } else {
2828 ret = -ENOTCONN;
2829 }
2830
2831 mutex_unlock(&fs_info->balance_mutex);
2832 return ret;
2833}
2834
2788/* 2835/*
2789 * shrinking a device means finding all of the device extents past 2836 * shrinking a device means finding all of the device extents past
2790 * the new size, and then following the back refs to the chunks. 2837 * the new size, and then following the back refs to the chunks.
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index cd25ea58ec35..80953afb12b9 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -273,6 +273,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *path);
273int btrfs_balance(struct btrfs_balance_control *bctl, 273int btrfs_balance(struct btrfs_balance_control *bctl,
274 struct btrfs_ioctl_balance_args *bargs); 274 struct btrfs_ioctl_balance_args *bargs);
275int btrfs_recover_balance(struct btrfs_root *tree_root); 275int btrfs_recover_balance(struct btrfs_root *tree_root);
276int btrfs_pause_balance(struct btrfs_fs_info *fs_info);
276int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); 277int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset);
277int find_free_dev_extent(struct btrfs_trans_handle *trans, 278int find_free_dev_extent(struct btrfs_trans_handle *trans,
278 struct btrfs_device *device, u64 num_bytes, 279 struct btrfs_device *device, u64 num_bytes,