|
@@ -2517,6 +2517,7 @@ 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);
|
|
@@ -2997,6 +2998,13 @@ 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))
|
|
@@ -3056,10 +3064,8 @@ retry_root_backup:
|
|
|
ret = btrfs_cleanup_fs_roots(fs_info);
|
|
|
if (ret)
|
|
|
goto fail_qgroup;
|
|
|
-
|
|
|
- mutex_lock(&fs_info->cleaner_mutex);
|
|
|
+ /* We locked cleaner_mutex before creating cleaner_kthread. */
|
|
|
ret = btrfs_recover_relocation(tree_root);
|
|
|
- mutex_unlock(&fs_info->cleaner_mutex);
|
|
|
if (ret < 0) {
|
|
|
printk(KERN_WARNING
|
|
|
"BTRFS: failed to recover relocation\n");
|
|
@@ -3067,6 +3073,8 @@ 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;
|
|
@@ -3180,6 +3188,10 @@ 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:
|