aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.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/volumes.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/volumes.c')
-rw-r--r--fs/btrfs/volumes.c51
1 files changed, 49 insertions, 2 deletions
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.