Skip to content

Commit cfe8bd3

Browse files
naotakdave
authored andcommitted
btrfs: zoned: fix stripe width calculation
The stripe offset calculation in the zoned code for raid0 and raid10 wrongly uses map->stripe_size to calculate it. In fact, map->stripe_size is the size of the device extent composing the block group, which always is the zone_size on the zoned setup. Fix it by using BTRFS_STRIPE_LEN and BTRFS_STRIPE_LEN_SHIFT. Also, optimize the calculation a bit by doing the common calculation only once. Fixes: c0d90a7 ("btrfs: zoned: fix alloc_offset calculation for partly conventional block groups") CC: stable@vger.kernel.org # 6.17+ Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 140d418 commit cfe8bd3

File tree

1 file changed

+26
-30
lines changed

1 file changed

+26
-30
lines changed

fs/btrfs/zoned.c

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,35 +1523,35 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
15231523
u64 last_alloc)
15241524
{
15251525
struct btrfs_fs_info *fs_info = bg->fs_info;
1526+
u64 stripe_nr = 0, stripe_offset = 0;
1527+
u32 stripe_index = 0;
15261528

15271529
if ((map->type & BTRFS_BLOCK_GROUP_DATA) && !fs_info->stripe_root) {
15281530
btrfs_err(fs_info, "zoned: data %s needs raid-stripe-tree",
15291531
btrfs_bg_type_to_raid_name(map->type));
15301532
return -EINVAL;
15311533
}
15321534

1535+
if (last_alloc) {
1536+
u32 factor = map->num_stripes;
1537+
1538+
stripe_nr = last_alloc >> BTRFS_STRIPE_LEN_SHIFT;
1539+
stripe_offset = last_alloc & BTRFS_STRIPE_LEN_MASK;
1540+
stripe_nr = div_u64_rem(stripe_nr, factor, &stripe_index);
1541+
}
1542+
15331543
for (int i = 0; i < map->num_stripes; i++) {
15341544
if (zone_info[i].alloc_offset == WP_MISSING_DEV)
15351545
continue;
15361546

15371547
if (zone_info[i].alloc_offset == WP_CONVENTIONAL) {
1538-
u64 stripe_nr, full_stripe_nr;
1539-
u64 stripe_offset;
1540-
int stripe_index;
15411548

1542-
stripe_nr = div64_u64(last_alloc, map->stripe_size);
1543-
stripe_offset = stripe_nr * map->stripe_size;
1544-
full_stripe_nr = div_u64(stripe_nr, map->num_stripes);
1545-
div_u64_rem(stripe_nr, map->num_stripes, &stripe_index);
1546-
1547-
zone_info[i].alloc_offset =
1548-
full_stripe_nr * map->stripe_size;
1549+
zone_info[i].alloc_offset = btrfs_stripe_nr_to_offset(stripe_nr);
15491550

15501551
if (stripe_index > i)
1551-
zone_info[i].alloc_offset += map->stripe_size;
1552+
zone_info[i].alloc_offset += BTRFS_STRIPE_LEN;
15521553
else if (stripe_index == i)
1553-
zone_info[i].alloc_offset +=
1554-
(last_alloc - stripe_offset);
1554+
zone_info[i].alloc_offset += stripe_offset;
15551555
}
15561556

15571557
if (test_bit(0, active) != test_bit(i, active)) {
@@ -1575,13 +1575,23 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
15751575
u64 last_alloc)
15761576
{
15771577
struct btrfs_fs_info *fs_info = bg->fs_info;
1578+
u64 stripe_nr = 0, stripe_offset = 0;
1579+
u32 stripe_index = 0;
15781580

15791581
if ((map->type & BTRFS_BLOCK_GROUP_DATA) && !fs_info->stripe_root) {
15801582
btrfs_err(fs_info, "zoned: data %s needs raid-stripe-tree",
15811583
btrfs_bg_type_to_raid_name(map->type));
15821584
return -EINVAL;
15831585
}
15841586

1587+
if (last_alloc) {
1588+
u32 factor = map->num_stripes / map->sub_stripes;
1589+
1590+
stripe_nr = last_alloc >> BTRFS_STRIPE_LEN_SHIFT;
1591+
stripe_offset = last_alloc & BTRFS_STRIPE_LEN_MASK;
1592+
stripe_nr = div_u64_rem(stripe_nr, factor, &stripe_index);
1593+
}
1594+
15851595
for (int i = 0; i < map->num_stripes; i++) {
15861596
if (zone_info[i].alloc_offset == WP_MISSING_DEV)
15871597
continue;
@@ -1595,26 +1605,12 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
15951605
}
15961606

15971607
if (zone_info[i].alloc_offset == WP_CONVENTIONAL) {
1598-
u64 stripe_nr, full_stripe_nr;
1599-
u64 stripe_offset;
1600-
int stripe_index;
1601-
1602-
stripe_nr = div64_u64(last_alloc, map->stripe_size);
1603-
stripe_offset = stripe_nr * map->stripe_size;
1604-
full_stripe_nr = div_u64(stripe_nr,
1605-
map->num_stripes / map->sub_stripes);
1606-
div_u64_rem(stripe_nr,
1607-
(map->num_stripes / map->sub_stripes),
1608-
&stripe_index);
1609-
1610-
zone_info[i].alloc_offset =
1611-
full_stripe_nr * map->stripe_size;
1608+
zone_info[i].alloc_offset = btrfs_stripe_nr_to_offset(stripe_nr);
16121609

16131610
if (stripe_index > (i / map->sub_stripes))
1614-
zone_info[i].alloc_offset += map->stripe_size;
1611+
zone_info[i].alloc_offset += BTRFS_STRIPE_LEN;
16151612
else if (stripe_index == (i / map->sub_stripes))
1616-
zone_info[i].alloc_offset +=
1617-
(last_alloc - stripe_offset);
1613+
zone_info[i].alloc_offset += stripe_offset;
16181614
}
16191615

16201616
if ((i % map->sub_stripes) == 0) {

0 commit comments

Comments
 (0)