btrfs: avoid blocking open_ctree from cleaner_kthread
[linux-2.6-block.git] / fs / btrfs / disk-io.c
index 7b5d5e8efde6965884e3eba13968a6335f56f651..789f5f2339402b77b75df4ea637106e7ae2ede96 100644 (file)
@@ -1806,6 +1806,13 @@ static int cleaner_kthread(void *arg)
                if (btrfs_need_cleaner_sleep(root))
                        goto sleep;
 
+               /*
+                * Do not do anything if we might cause open_ctree() to block
+                * before we have finished mounting the filesystem.
+                */
+               if (!root->fs_info->open)
+                       goto sleep;
+
                if (!mutex_trylock(&root->fs_info->cleaner_mutex))
                        goto sleep;
 
@@ -2520,7 +2527,6 @@ int open_ctree(struct super_block *sb,
        int num_backups_tried = 0;
        int backup_index = 0;
        int max_active;
-       bool cleaner_mutex_locked = false;
 
        tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
        chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
@@ -2999,13 +3005,6 @@ retry_root_backup:
                goto fail_sysfs;
        }
 
-       /*
-        * Hold the cleaner_mutex thread here so that we don't block
-        * for a long time on btrfs_recover_relocation.  cleaner_kthread
-        * will wait for us to finish mounting the filesystem.
-        */
-       mutex_lock(&fs_info->cleaner_mutex);
-       cleaner_mutex_locked = true;
        fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
                                               "btrfs-cleaner");
        if (IS_ERR(fs_info->cleaner_kthread))
@@ -3065,8 +3064,10 @@ retry_root_backup:
                ret = btrfs_cleanup_fs_roots(fs_info);
                if (ret)
                        goto fail_qgroup;
-               /* We locked cleaner_mutex before creating cleaner_kthread. */
+
+               mutex_lock(&fs_info->cleaner_mutex);
                ret = btrfs_recover_relocation(tree_root);
+               mutex_unlock(&fs_info->cleaner_mutex);
                if (ret < 0) {
                        btrfs_warn(fs_info, "failed to recover relocation: %d",
                                        ret);
@@ -3074,8 +3075,6 @@ retry_root_backup:
                        goto fail_qgroup;
                }
        }
-       mutex_unlock(&fs_info->cleaner_mutex);
-       cleaner_mutex_locked = false;
 
        location.objectid = BTRFS_FS_TREE_OBJECTID;
        location.type = BTRFS_ROOT_ITEM_KEY;
@@ -3189,10 +3188,6 @@ fail_cleaner:
        filemap_write_and_wait(fs_info->btree_inode->i_mapping);
 
 fail_sysfs:
-       if (cleaner_mutex_locked) {
-               mutex_unlock(&fs_info->cleaner_mutex);
-               cleaner_mutex_locked = false;
-       }
        btrfs_sysfs_remove_mounted(fs_info);
 
 fail_fsdev_sysfs: