Btrfs: avoid unnecessary scrub workers allocation
authorWang Shilong <wangsl.fnst@cn.fujitsu.com>
Fri, 11 Oct 2013 18:11:12 +0000 (02:11 +0800)
committerChris Mason <chris.mason@fusionio.com>
Tue, 12 Nov 2013 03:12:58 +0000 (22:12 -0500)
We only allocate scrub workers if we pass all the necessary
checks, for example, there are no operation in progress.

Besides, move mutex lock protection outside of scrub_workers_get()
/scrub_workers_put().

Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
fs/btrfs/scrub.c

index 12009b4279ad1c1e3faad9e5353de1f86a0a4c9a..2544805544f0baf137c33de162c46f14b5ddf002 100644 (file)
@@ -2784,7 +2784,6 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info,
 {
        int ret = 0;
 
-       mutex_lock(&fs_info->scrub_lock);
        if (fs_info->scrub_workers_refcnt == 0) {
                if (is_dev_replace)
                        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,
        }
        ++fs_info->scrub_workers_refcnt;
 out:
-       mutex_unlock(&fs_info->scrub_lock);
-
        return ret;
 }
 
 static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info)
 {
-       mutex_lock(&fs_info->scrub_lock);
        if (--fs_info->scrub_workers_refcnt == 0) {
                btrfs_stop_workers(&fs_info->scrub_workers);
                btrfs_stop_workers(&fs_info->scrub_wr_completion_workers);
                btrfs_stop_workers(&fs_info->scrub_nocow_workers);
        }
        WARN_ON(fs_info->scrub_workers_refcnt < 0);
-       mutex_unlock(&fs_info->scrub_lock);
 }
 
 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,
                return -EINVAL;
        }
 
-       ret = scrub_workers_get(fs_info, is_dev_replace);
-       if (ret)
-               return ret;
 
        mutex_lock(&fs_info->fs_devices->device_list_mutex);
        dev = btrfs_find_device(fs_info, devid, NULL, NULL);
        if (!dev || (dev->missing && !is_dev_replace)) {
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
-               scrub_workers_put(fs_info);
                return -ENODEV;
        }
-       mutex_lock(&fs_info->scrub_lock);
 
+       mutex_lock(&fs_info->scrub_lock);
        if (!dev->in_fs_metadata || dev->is_tgtdev_for_dev_replace) {
                mutex_unlock(&fs_info->scrub_lock);
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
-               scrub_workers_put(fs_info);
                return -EIO;
        }
 
@@ -2916,10 +2906,17 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
                btrfs_dev_replace_unlock(&fs_info->dev_replace);
                mutex_unlock(&fs_info->scrub_lock);
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
-               scrub_workers_put(fs_info);
                return -EINPROGRESS;
        }
        btrfs_dev_replace_unlock(&fs_info->dev_replace);
+
+       ret = scrub_workers_get(fs_info, is_dev_replace);
+       if (ret) {
+               mutex_unlock(&fs_info->scrub_lock);
+               mutex_unlock(&fs_info->fs_devices->device_list_mutex);
+               return ret;
+       }
+
        sctx = scrub_setup_ctx(dev, is_dev_replace);
        if (IS_ERR(sctx)) {
                mutex_unlock(&fs_info->scrub_lock);
@@ -2957,10 +2954,10 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
 
        mutex_lock(&fs_info->scrub_lock);
        dev->scrub_device = NULL;
+       scrub_workers_put(fs_info);
        mutex_unlock(&fs_info->scrub_lock);
 
        scrub_free_ctx(sctx);
-       scrub_workers_put(fs_info);
 
        return ret;
 }