aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/scrub.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/scrub.c')
-rw-r--r--fs/btrfs/scrub.c23
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;
2816out: 2815out:
2817 mutex_unlock(&fs_info->scrub_lock);
2818
2819 return ret; 2816 return ret;
2820} 2817}
2821 2818
2822static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info) 2819static 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
2834int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, 2829int 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}