Skip to content

Commit 580dc52

Browse files
naotagregkh
authored andcommitted
btrfs: zoned: fix data relocation block group reservation
[ Upstream commit daa0fde ] btrfs_zoned_reserve_data_reloc_bg() is called on mount and at that point, all data block groups belong to the primary data space_info. So, we don't find anything in the data relocation space_info. Also, the condition "bg->used > 0" can select a block group with full of zone_unusable bytes for the candidate. As we cannot allocate from the block group, it is useless to reserve it as the data relocation block group. Furthermore, because of the space_info separation, we need to migrate the selected block group to the data relocation space_info. If not, the extent allocator cannot use the block group to do the allocation. This commit fixes these three issues. Fixes: e606ff985ec7 ("btrfs: zoned: reserve data_reloc block group on mount") Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent f5e395a commit 580dc52

File tree

1 file changed

+47
-8
lines changed

1 file changed

+47
-8
lines changed

fs/btrfs/zoned.c

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "accessors.h"
1919
#include "bio.h"
2020
#include "transaction.h"
21+
#include "sysfs.h"
2122

2223
/* Maximum number of zones to report per blkdev_report_zones() call */
2324
#define BTRFS_REPORT_NR_ZONES 4096
@@ -2510,12 +2511,12 @@ void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg)
25102511
void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info)
25112512
{
25122513
struct btrfs_space_info *data_sinfo = fs_info->data_sinfo;
2513-
struct btrfs_space_info *space_info = data_sinfo->sub_group[0];
2514+
struct btrfs_space_info *space_info = data_sinfo;
25142515
struct btrfs_trans_handle *trans;
25152516
struct btrfs_block_group *bg;
25162517
struct list_head *bg_list;
25172518
u64 alloc_flags;
2518-
bool initial = false;
2519+
bool first = true;
25192520
bool did_chunk_alloc = false;
25202521
int index;
25212522
int ret;
@@ -2529,21 +2530,52 @@ void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info)
25292530
if (sb_rdonly(fs_info->sb))
25302531
return;
25312532

2532-
ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC);
25332533
alloc_flags = btrfs_get_alloc_profile(fs_info, space_info->flags);
25342534
index = btrfs_bg_flags_to_raid_index(alloc_flags);
25352535

2536-
bg_list = &data_sinfo->block_groups[index];
2536+
/* Scan the data space_info to find empty block groups. Take the second one. */
25372537
again:
2538+
bg_list = &space_info->block_groups[index];
25382539
list_for_each_entry(bg, bg_list, list) {
2539-
if (bg->used > 0)
2540+
if (bg->alloc_offset != 0)
25402541
continue;
25412542

2542-
if (!initial) {
2543-
initial = true;
2543+
if (first) {
2544+
first = false;
25442545
continue;
25452546
}
25462547

2548+
if (space_info == data_sinfo) {
2549+
/* Migrate the block group to the data relocation space_info. */
2550+
struct btrfs_space_info *reloc_sinfo = data_sinfo->sub_group[0];
2551+
int factor;
2552+
2553+
ASSERT(reloc_sinfo->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC);
2554+
factor = btrfs_bg_type_to_factor(bg->flags);
2555+
2556+
down_write(&space_info->groups_sem);
2557+
list_del_init(&bg->list);
2558+
/* We can assume this as we choose the second empty one. */
2559+
ASSERT(!list_empty(&space_info->block_groups[index]));
2560+
up_write(&space_info->groups_sem);
2561+
2562+
spin_lock(&space_info->lock);
2563+
space_info->total_bytes -= bg->length;
2564+
space_info->disk_total -= bg->length * factor;
2565+
/* There is no allocation ever happened. */
2566+
ASSERT(bg->used == 0);
2567+
ASSERT(bg->zone_unusable == 0);
2568+
/* No super block in a block group on the zoned setup. */
2569+
ASSERT(bg->bytes_super == 0);
2570+
spin_unlock(&space_info->lock);
2571+
2572+
bg->space_info = reloc_sinfo;
2573+
if (reloc_sinfo->block_group_kobjs[index] == NULL)
2574+
btrfs_sysfs_add_block_group_type(bg);
2575+
2576+
btrfs_add_bg_to_space_info(fs_info, bg);
2577+
}
2578+
25472579
fs_info->data_reloc_bg = bg->start;
25482580
set_bit(BLOCK_GROUP_FLAG_ZONED_DATA_RELOC, &bg->runtime_flags);
25492581
btrfs_zone_activate(bg);
@@ -2558,11 +2590,18 @@ void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info)
25582590
if (IS_ERR(trans))
25592591
return;
25602592

2593+
/* Allocate new BG in the data relocation space_info. */
2594+
space_info = data_sinfo->sub_group[0];
2595+
ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC);
25612596
ret = btrfs_chunk_alloc(trans, space_info, alloc_flags, CHUNK_ALLOC_FORCE);
25622597
btrfs_end_transaction(trans);
25632598
if (ret == 1) {
2599+
/*
2600+
* We allocated a new block group in the data relocation space_info. We
2601+
* can take that one.
2602+
*/
2603+
first = false;
25642604
did_chunk_alloc = true;
2565-
bg_list = &space_info->block_groups[index];
25662605
goto again;
25672606
}
25682607
}

0 commit comments

Comments
 (0)