Skip to content

Commit 511711a

Browse files
committed
btrfs: don't run delayed references while we are creating the free space tree
This is a short term solution to make sure btrfs_run_delayed_refs() doesn't change the extent tree while we are scanning it to create the free space tree. Longer term we need to synchronize scanning the block groups one by one, similar to what happens during a balance. Signed-off-by: Chris Mason <[email protected]>
1 parent b4570aa commit 511711a

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

fs/btrfs/ctree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,8 @@ struct btrfs_fs_info {
18561856
* and will be latter freed. Protected by fs_info->chunk_mutex.
18571857
*/
18581858
struct list_head pinned_chunks;
1859+
1860+
int creating_free_space_tree;
18591861
};
18601862

18611863
struct btrfs_subvolume_writers {

fs/btrfs/disk-io.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,6 +3065,18 @@ int open_ctree(struct super_block *sb,
30653065
if (sb->s_flags & MS_RDONLY)
30663066
return 0;
30673067

3068+
if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) &&
3069+
!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
3070+
pr_info("BTRFS: creating free space tree\n");
3071+
ret = btrfs_create_free_space_tree(fs_info);
3072+
if (ret) {
3073+
pr_warn("BTRFS: failed to create free space tree %d\n",
3074+
ret);
3075+
close_ctree(tree_root);
3076+
return ret;
3077+
}
3078+
}
3079+
30683080
down_read(&fs_info->cleanup_work_sem);
30693081
if ((ret = btrfs_orphan_cleanup(fs_info->fs_root)) ||
30703082
(ret = btrfs_orphan_cleanup(fs_info->tree_root))) {
@@ -3102,18 +3114,6 @@ int open_ctree(struct super_block *sb,
31023114
}
31033115
}
31043116

3105-
if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) &&
3106-
!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
3107-
pr_info("BTRFS: creating free space tree\n");
3108-
ret = btrfs_create_free_space_tree(fs_info);
3109-
if (ret) {
3110-
pr_warn("BTRFS: failed to create free space tree %d\n",
3111-
ret);
3112-
close_ctree(tree_root);
3113-
return ret;
3114-
}
3115-
}
3116-
31173117
if (!fs_info->uuid_root) {
31183118
pr_info("BTRFS: creating UUID tree\n");
31193119
ret = btrfs_create_uuid_tree(fs_info);

fs/btrfs/extent-tree.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2926,6 +2926,9 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
29262926
if (trans->aborted)
29272927
return 0;
29282928

2929+
if (root->fs_info->creating_free_space_tree)
2930+
return 0;
2931+
29292932
if (root == root->fs_info->extent_root)
29302933
root = root->fs_info->tree_root;
29312934

fs/btrfs/free-space-tree.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,8 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
10671067
if (ret)
10681068
goto out;
10691069

1070+
mutex_lock(&block_group->free_space_lock);
1071+
10701072
/*
10711073
* Iterate through all of the extent and metadata items in this block
10721074
* group, adding the free space between them and the free space at the
@@ -1080,7 +1082,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
10801082

10811083
ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0);
10821084
if (ret < 0)
1083-
goto out;
1085+
goto out_locked;
10841086
ASSERT(ret == 0);
10851087

10861088
start = block_group->key.objectid;
@@ -1100,7 +1102,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
11001102
key.objectid -
11011103
start);
11021104
if (ret)
1103-
goto out;
1105+
goto out_locked;
11041106
}
11051107
start = key.objectid;
11061108
if (key.type == BTRFS_METADATA_ITEM_KEY)
@@ -1114,18 +1116,20 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
11141116

11151117
ret = btrfs_next_item(extent_root, path);
11161118
if (ret < 0)
1117-
goto out;
1119+
goto out_locked;
11181120
if (ret)
11191121
break;
11201122
}
11211123
if (start < end) {
11221124
ret = __add_to_free_space_tree(trans, fs_info, block_group,
11231125
path2, start, end - start);
11241126
if (ret)
1125-
goto out;
1127+
goto out_locked;
11261128
}
11271129

11281130
ret = 0;
1131+
out_locked:
1132+
mutex_unlock(&block_group->free_space_lock);
11291133
out:
11301134
btrfs_free_path(path2);
11311135
btrfs_free_path(path);
@@ -1145,6 +1149,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
11451149
if (IS_ERR(trans))
11461150
return PTR_ERR(trans);
11471151

1152+
fs_info->creating_free_space_tree = 1;
11481153
free_space_root = btrfs_create_tree(trans, fs_info,
11491154
BTRFS_FREE_SPACE_TREE_OBJECTID);
11501155
if (IS_ERR(free_space_root)) {
@@ -1164,6 +1169,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
11641169
}
11651170

11661171
btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
1172+
fs_info->creating_free_space_tree = 0;
11671173

11681174
ret = btrfs_commit_transaction(trans, tree_root);
11691175
if (ret)
@@ -1172,6 +1178,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
11721178
return 0;
11731179

11741180
abort:
1181+
fs_info->creating_free_space_tree = 0;
11751182
btrfs_abort_transaction(trans, tree_root, ret);
11761183
btrfs_end_transaction(trans, tree_root);
11771184
return ret;

0 commit comments

Comments
 (0)