aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
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.