diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 51 |
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 | ||
2561 | static inline int balance_need_close(struct btrfs_fs_info *fs_info) | ||
2562 | { | ||
2563 | return atomic_read(&fs_info->balance_pause_req) == 0; | ||
2564 | } | ||
2565 | |||
2556 | static void __cancel_balance(struct btrfs_fs_info *fs_info) | 2566 | static 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; |
2697 | out: | 2715 | out: |
@@ -2785,6 +2803,35 @@ out: | |||
2785 | return ret; | 2803 | return ret; |
2786 | } | 2804 | } |
2787 | 2805 | ||
2806 | int 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. |