btrfs: tweak extent/chunk allocation for space_info sub-space
authorNaohiro Aota <naohiro.aota@wdc.com>
Wed, 23 Apr 2025 02:43:50 +0000 (11:43 +0900)
committerDavid Sterba <dsterba@suse.com>
Thu, 15 May 2025 12:30:53 +0000 (14:30 +0200)
Make the extent allocator and the chunk allocator aware of the sub-space.
It now uses BTRFS_SUB_GROUP_DATA_RELOC sub-space for data relocation block
group, and uses BTRFS_SUB_GROUP_TREELOG for metadata tree-log block group.

And, it needs to check the space_info is the right one when a block group
candidate is given. Also, new block group should now belong to the
specified one.

Now that, block_group->space_info is always set before
btrfs_add_bg_to_space_info(), we no longer need to "find" the space_info.
So, rename the variable name to address that as well.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/block-group.c
fs/btrfs/extent-tree.c
fs/btrfs/space-info.c

index d4a5a5c98d4d607d6743c338211d8671a681b70f..af01599ef5b1c022c751225e6c132d75ddc2aa50 100644 (file)
@@ -2371,6 +2371,7 @@ static int read_one_block_group(struct btrfs_fs_info *info,
        cache->commit_used = cache->used;
        cache->flags = btrfs_stack_block_group_flags(bgi);
        cache->global_root_id = btrfs_stack_block_group_chunk_objectid(bgi);
+       cache->space_info = btrfs_find_space_info(info, cache->flags);
 
        set_free_space_tree_thresholds(cache);
 
@@ -2449,6 +2450,7 @@ static int read_one_block_group(struct btrfs_fs_info *info,
                btrfs_remove_free_space_cache(cache);
                goto error;
        }
+
        trace_btrfs_add_block_group(info, cache, 0);
        btrfs_add_bg_to_space_info(info, cache);
 
@@ -2493,6 +2495,7 @@ static int fill_dummy_bgs(struct btrfs_fs_info *fs_info)
                bg->cached = BTRFS_CACHE_FINISHED;
                bg->used = map->chunk_len;
                bg->flags = map->type;
+               bg->space_info = btrfs_find_space_info(fs_info, bg->flags);
                ret = btrfs_add_block_group_cache(bg);
                /*
                 * We may have some valid block group cache added already, in
index 32255a780d13be8df515024985616e8d4f5698ac..64e8c653ae8f3e0c01d39243142f561acff2d54b 100644 (file)
@@ -4405,8 +4405,19 @@ static noinline int find_free_extent(struct btrfs_root *root,
        trace_btrfs_find_free_extent(root, ffe_ctl);
 
        space_info = btrfs_find_space_info(fs_info, ffe_ctl->flags);
+       if (btrfs_is_zoned(fs_info) && space_info) {
+               /* Use dedicated sub-space_info for dedicated block group users. */
+               if (ffe_ctl->for_data_reloc) {
+                       space_info = space_info->sub_group[0];
+                       ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC);
+               } else if (ffe_ctl->for_treelog) {
+                       space_info = space_info->sub_group[0];
+                       ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_TREELOG);
+               }
+       }
        if (!space_info) {
-               btrfs_err(fs_info, "No space info for %llu", ffe_ctl->flags);
+               btrfs_err(fs_info, "no space info for %llu, tree-log %d, relocation %d",
+                         ffe_ctl->flags, ffe_ctl->for_treelog, ffe_ctl->for_data_reloc);
                return -ENOSPC;
        }
 
@@ -4428,6 +4439,7 @@ static noinline int find_free_extent(struct btrfs_root *root,
                 * picked out then we don't care that the block group is cached.
                 */
                if (block_group && block_group_bits(block_group, ffe_ctl->flags) &&
+                   block_group->space_info == space_info &&
                    block_group->cached != BTRFS_CACHE_NO) {
                        down_read(&space_info->groups_sem);
                        if (list_empty(&block_group->list) ||
index d858da058dcead6958ed29b3a7235c971feb7bf7..5b477960ee1f5d430405a702ef7f69520615fdfb 100644 (file)
@@ -359,31 +359,29 @@ out:
 void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info,
                                struct btrfs_block_group *block_group)
 {
-       struct btrfs_space_info *found;
+       struct btrfs_space_info *space_info = block_group->space_info;
        int factor, index;
 
        factor = btrfs_bg_type_to_factor(block_group->flags);
 
-       found = btrfs_find_space_info(info, block_group->flags);
-       ASSERT(found);
-       spin_lock(&found->lock);
-       found->total_bytes += block_group->length;
-       found->disk_total += block_group->length * factor;
-       found->bytes_used += block_group->used;
-       found->disk_used += block_group->used * factor;
-       found->bytes_readonly += block_group->bytes_super;
-       btrfs_space_info_update_bytes_zone_unusable(found, block_group->zone_unusable);
+       spin_lock(&space_info->lock);
+       space_info->total_bytes += block_group->length;
+       space_info->disk_total += block_group->length * factor;
+       space_info->bytes_used += block_group->used;
+       space_info->disk_used += block_group->used * factor;
+       space_info->bytes_readonly += block_group->bytes_super;
+       btrfs_space_info_update_bytes_zone_unusable(space_info, block_group->zone_unusable);
        if (block_group->length > 0)
-               found->full = 0;
-       btrfs_try_granting_tickets(info, found);
-       spin_unlock(&found->lock);
+               space_info->full = 0;
+       btrfs_try_granting_tickets(info, space_info);
+       spin_unlock(&space_info->lock);
 
-       block_group->space_info = found;
+       block_group->space_info = space_info;
 
        index = btrfs_bg_flags_to_raid_index(block_group->flags);
-       down_write(&found->groups_sem);
-       list_add_tail(&block_group->list, &found->block_groups[index]);
-       up_write(&found->groups_sem);
+       down_write(&space_info->groups_sem);
+       list_add_tail(&block_group->list, &space_info->block_groups[index]);
+       up_write(&space_info->groups_sem);
 }
 
 struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info,