Skip to content

Commit be10126

Browse files
adam900710kdave
authored andcommitted
btrfs-progs: optimize the block group item load for half converted fs
[PROBLEM] If there is an fs which is half converted to block group tree, then the block group item loading will still go through all the tree blocks in the old extent tree. Even if the extent tree may only contain one block group item. [CAUSE] We rely on the function find_first_block_group() to find a block group after certain bytenr. But there is no stopper on where the search should end, thus it will go the next slot until there are no more leaves. Meaning even if we have found the last block group item in the old extent tree, find_first_block_group() will still search the whole extent tree. We had a check after find_first_block_group(), but that's useless as it's already too late. [ENHANCEMENT] Add an extra parameter, @max_bytenr, that if we found a key whose objectid >= @max_bytenr, then we stop the search immediately. This will skip the time consuming full tree iteration and make resuming faster. Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 94f9a03 commit be10126

File tree

1 file changed

+8
-37
lines changed

1 file changed

+8
-37
lines changed

kernel-shared/extent-tree.c

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2643,14 +2643,14 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
26432643
}
26442644

26452645
/*
2646-
* Find a block group which starts >= @key->objectid in extent tree.
2646+
* Find a block group which starts >= @key->objectid and ends < max_bytenr.
26472647
*
26482648
* Return 0 for found
26492649
* Return >0 for not found
26502650
* Return <0 for error
26512651
*/
2652-
static int find_first_block_group(struct btrfs_root *root,
2653-
struct btrfs_path *path, struct btrfs_key *key)
2652+
static int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path,
2653+
struct btrfs_key *key, u64 max_bytenr)
26542654
{
26552655
int ret;
26562656
struct btrfs_key found_key;
@@ -2676,6 +2676,8 @@ static int find_first_block_group(struct btrfs_root *root,
26762676
if (found_key.objectid >= key->objectid &&
26772677
found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY)
26782678
return 0;
2679+
if (found_key.objectid >= max_bytenr)
2680+
break;
26792681
path->slots[0]++;
26802682
}
26812683
ret = 1;
@@ -2792,7 +2794,7 @@ static int get_last_converted_bg(struct btrfs_fs_info *fs_info)
27922794
/* Empty bg tree, all converted, then grab the first bg. */
27932795
if (btrfs_header_nritems(path.nodes[0]) == 0) {
27942796
btrfs_release_path(&path);
2795-
ret = find_first_block_group(extent_root, &path, &key);
2797+
ret = find_first_block_group(extent_root, &path, &key, (u64)-1);
27962798
/* We should have at least one bg item in extent tree. */
27972799
ASSERT(ret == 0);
27982800

@@ -2861,39 +2863,12 @@ static int read_old_block_groups_from_root(struct btrfs_fs_info *fs_info,
28612863
{
28622864
struct btrfs_path path = {0};
28632865
struct btrfs_key key = { 0 };
2864-
struct cache_extent *ce;
2865-
/* The last block group bytenr in the old root. */
2866-
u64 last_bg_in_old_root;
28672866
int ret;
28682867

2869-
if (fs_info->last_converted_bg_bytenr != (u64)-1) {
2870-
/*
2871-
* We know the last converted bg in the other tree, load the chunk
2872-
* before that last converted as our last bg in the tree.
2873-
*/
2874-
ce = search_cache_extent(&fs_info->mapping_tree.cache_tree,
2875-
fs_info->last_converted_bg_bytenr);
2876-
if (!ce || ce->start != fs_info->last_converted_bg_bytenr) {
2877-
error("no chunk found for bytenr %llu",
2878-
fs_info->last_converted_bg_bytenr);
2879-
return -ENOENT;
2880-
}
2881-
ce = prev_cache_extent(ce);
2882-
/*
2883-
* We should have previous unconverted chunk, or we have
2884-
* already finished the convert.
2885-
*/
2886-
ASSERT(ce);
2887-
2888-
last_bg_in_old_root = ce->start;
2889-
} else {
2890-
last_bg_in_old_root = (u64)-1;
2891-
}
2892-
28932868
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
28942869

28952870
while (true) {
2896-
ret = find_first_block_group(root, &path, &key);
2871+
ret = find_first_block_group(root, &path, &key, fs_info->last_converted_bg_bytenr);
28972872
if (ret > 0) {
28982873
ret = 0;
28992874
goto out;
@@ -2907,10 +2882,6 @@ static int read_old_block_groups_from_root(struct btrfs_fs_info *fs_info,
29072882
if (ret < 0 && ret != -ENOENT)
29082883
goto out;
29092884

2910-
/* We have reached last bg in the old root, no need to continue */
2911-
if (key.objectid >= last_bg_in_old_root)
2912-
break;
2913-
29142885
if (key.offset == 0)
29152886
key.objectid++;
29162887
else
@@ -2935,7 +2906,7 @@ static int read_block_groups_from_root(struct btrfs_fs_info *fs_info,
29352906
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
29362907

29372908
while (true) {
2938-
ret = find_first_block_group(root, &path, &key);
2909+
ret = find_first_block_group(root, &path, &key, (u64)-1);
29392910
if (ret > 0) {
29402911
ret = 0;
29412912
goto out;

0 commit comments

Comments
 (0)