diff options
Diffstat (limited to 'fs/btrfs/scrub.c')
-rw-r--r-- | fs/btrfs/scrub.c | 23 |
1 files changed, 10 insertions, 13 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 12009b4279ad..2544805544f0 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -2784,7 +2784,6 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info, | |||
2784 | { | 2784 | { |
2785 | int ret = 0; | 2785 | int ret = 0; |
2786 | 2786 | ||
2787 | mutex_lock(&fs_info->scrub_lock); | ||
2788 | if (fs_info->scrub_workers_refcnt == 0) { | 2787 | if (fs_info->scrub_workers_refcnt == 0) { |
2789 | if (is_dev_replace) | 2788 | if (is_dev_replace) |
2790 | btrfs_init_workers(&fs_info->scrub_workers, "scrub", 1, | 2789 | btrfs_init_workers(&fs_info->scrub_workers, "scrub", 1, |
@@ -2814,21 +2813,17 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info, | |||
2814 | } | 2813 | } |
2815 | ++fs_info->scrub_workers_refcnt; | 2814 | ++fs_info->scrub_workers_refcnt; |
2816 | out: | 2815 | out: |
2817 | mutex_unlock(&fs_info->scrub_lock); | ||
2818 | |||
2819 | return ret; | 2816 | return ret; |
2820 | } | 2817 | } |
2821 | 2818 | ||
2822 | static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info) | 2819 | static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info) |
2823 | { | 2820 | { |
2824 | mutex_lock(&fs_info->scrub_lock); | ||
2825 | if (--fs_info->scrub_workers_refcnt == 0) { | 2821 | if (--fs_info->scrub_workers_refcnt == 0) { |
2826 | btrfs_stop_workers(&fs_info->scrub_workers); | 2822 | btrfs_stop_workers(&fs_info->scrub_workers); |
2827 | btrfs_stop_workers(&fs_info->scrub_wr_completion_workers); | 2823 | btrfs_stop_workers(&fs_info->scrub_wr_completion_workers); |
2828 | btrfs_stop_workers(&fs_info->scrub_nocow_workers); | 2824 | btrfs_stop_workers(&fs_info->scrub_nocow_workers); |
2829 | } | 2825 | } |
2830 | WARN_ON(fs_info->scrub_workers_refcnt < 0); | 2826 | WARN_ON(fs_info->scrub_workers_refcnt < 0); |
2831 | mutex_unlock(&fs_info->scrub_lock); | ||
2832 | } | 2827 | } |
2833 | 2828 | ||
2834 | int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | 2829 | int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, |
@@ -2889,23 +2884,18 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
2889 | return -EINVAL; | 2884 | return -EINVAL; |
2890 | } | 2885 | } |
2891 | 2886 | ||
2892 | ret = scrub_workers_get(fs_info, is_dev_replace); | ||
2893 | if (ret) | ||
2894 | return ret; | ||
2895 | 2887 | ||
2896 | mutex_lock(&fs_info->fs_devices->device_list_mutex); | 2888 | mutex_lock(&fs_info->fs_devices->device_list_mutex); |
2897 | dev = btrfs_find_device(fs_info, devid, NULL, NULL); | 2889 | dev = btrfs_find_device(fs_info, devid, NULL, NULL); |
2898 | if (!dev || (dev->missing && !is_dev_replace)) { | 2890 | if (!dev || (dev->missing && !is_dev_replace)) { |
2899 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 2891 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
2900 | scrub_workers_put(fs_info); | ||
2901 | return -ENODEV; | 2892 | return -ENODEV; |
2902 | } | 2893 | } |
2903 | mutex_lock(&fs_info->scrub_lock); | ||
2904 | 2894 | ||
2895 | mutex_lock(&fs_info->scrub_lock); | ||
2905 | if (!dev->in_fs_metadata || dev->is_tgtdev_for_dev_replace) { | 2896 | if (!dev->in_fs_metadata || dev->is_tgtdev_for_dev_replace) { |
2906 | mutex_unlock(&fs_info->scrub_lock); | 2897 | mutex_unlock(&fs_info->scrub_lock); |
2907 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 2898 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
2908 | scrub_workers_put(fs_info); | ||
2909 | return -EIO; | 2899 | return -EIO; |
2910 | } | 2900 | } |
2911 | 2901 | ||
@@ -2916,10 +2906,17 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
2916 | btrfs_dev_replace_unlock(&fs_info->dev_replace); | 2906 | btrfs_dev_replace_unlock(&fs_info->dev_replace); |
2917 | mutex_unlock(&fs_info->scrub_lock); | 2907 | mutex_unlock(&fs_info->scrub_lock); |
2918 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | 2908 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); |
2919 | scrub_workers_put(fs_info); | ||
2920 | return -EINPROGRESS; | 2909 | return -EINPROGRESS; |
2921 | } | 2910 | } |
2922 | btrfs_dev_replace_unlock(&fs_info->dev_replace); | 2911 | btrfs_dev_replace_unlock(&fs_info->dev_replace); |
2912 | |||
2913 | ret = scrub_workers_get(fs_info, is_dev_replace); | ||
2914 | if (ret) { | ||
2915 | mutex_unlock(&fs_info->scrub_lock); | ||
2916 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | ||
2917 | return ret; | ||
2918 | } | ||
2919 | |||
2923 | sctx = scrub_setup_ctx(dev, is_dev_replace); | 2920 | sctx = scrub_setup_ctx(dev, is_dev_replace); |
2924 | if (IS_ERR(sctx)) { | 2921 | if (IS_ERR(sctx)) { |
2925 | mutex_unlock(&fs_info->scrub_lock); | 2922 | mutex_unlock(&fs_info->scrub_lock); |
@@ -2957,10 +2954,10 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, | |||
2957 | 2954 | ||
2958 | mutex_lock(&fs_info->scrub_lock); | 2955 | mutex_lock(&fs_info->scrub_lock); |
2959 | dev->scrub_device = NULL; | 2956 | dev->scrub_device = NULL; |
2957 | scrub_workers_put(fs_info); | ||
2960 | mutex_unlock(&fs_info->scrub_lock); | 2958 | mutex_unlock(&fs_info->scrub_lock); |
2961 | 2959 | ||
2962 | scrub_free_ctx(sctx); | 2960 | scrub_free_ctx(sctx); |
2963 | scrub_workers_put(fs_info); | ||
2964 | 2961 | ||
2965 | return ret; | 2962 | return ret; |
2966 | } | 2963 | } |