* [PATCH v2] btrfs: zoned: fix alloc_offset calculation for partly conventional block groups
@ 2025-06-05 9:18 Johannes Thumshirn
2025-06-06 0:06 ` kernel test robot
0 siblings, 1 reply; 2+ messages in thread
From: Johannes Thumshirn @ 2025-06-05 9:18 UTC (permalink / raw)
To: linux-btrfs
Cc: Naohiro Aota, Damien Le Moal, David Sterba, Josef Bacik,
Johannes Thumshirn
From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
When one of two zones composing a DUP block group is a conventional zone,
we have the zone_info[i]->alloc_offset = WP_CONVENTIONAL. That will, of
course, not match the write pointer of the other zone, and fails that
block group.
This commit solves that issue by properly recovering the emulated write
pointer from the last allocated extent. The offset for the SINGLE, DUP,
and RAID1 are straight-forward: it is same as the end of last allocated
extent. The RAID0 and RAID10 are a bit tricky that we need to do the math
of striping.
This is the kernel equivalent of Naohiro's user-space commit:
1e85aa96e107 ("btrfs-progs: zoned: fix alloc_offset calculation for partly conventional block groups")
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
---
Changes to v1:
- Fix kbuild error on 32bit due to divisions
---
fs/btrfs/zoned.c | 85 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 71 insertions(+), 14 deletions(-)
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 4e122d6c19c0..63d72bd63823 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -1404,7 +1404,8 @@ static int btrfs_load_block_group_single(struct btrfs_block_group *bg,
static int btrfs_load_block_group_dup(struct btrfs_block_group *bg,
struct btrfs_chunk_map *map,
struct zone_info *zone_info,
- unsigned long *active)
+ unsigned long *active,
+ u64 last_alloc)
{
struct btrfs_fs_info *fs_info = bg->fs_info;
@@ -1427,6 +1428,13 @@ static int btrfs_load_block_group_dup(struct btrfs_block_group *bg,
zone_info[1].physical);
return -EIO;
}
+
+ if (zone_info[0].alloc_offset == WP_CONVENTIONAL)
+ zone_info[0].alloc_offset = last_alloc;
+
+ if (zone_info[1].alloc_offset == WP_CONVENTIONAL)
+ zone_info[1].alloc_offset = last_alloc;
+
if (zone_info[0].alloc_offset != zone_info[1].alloc_offset) {
btrfs_err(bg->fs_info,
"zoned: write pointer offset mismatch of zones in DUP profile");
@@ -1447,7 +1455,8 @@ static int btrfs_load_block_group_dup(struct btrfs_block_group *bg,
static int btrfs_load_block_group_raid1(struct btrfs_block_group *bg,
struct btrfs_chunk_map *map,
struct zone_info *zone_info,
- unsigned long *active)
+ unsigned long *active,
+ u64 last_alloc)
{
struct btrfs_fs_info *fs_info = bg->fs_info;
int i;
@@ -1462,10 +1471,12 @@ static int btrfs_load_block_group_raid1(struct btrfs_block_group *bg,
bg->zone_capacity = min_not_zero(zone_info[0].capacity, zone_info[1].capacity);
for (i = 0; i < map->num_stripes; i++) {
- if (zone_info[i].alloc_offset == WP_MISSING_DEV ||
- zone_info[i].alloc_offset == WP_CONVENTIONAL)
+ if (zone_info[i].alloc_offset == WP_MISSING_DEV)
continue;
+ if (zone_info[i].alloc_offset == WP_CONVENTIONAL)
+ zone_info[i].alloc_offset = last_alloc;
+
if ((zone_info[0].alloc_offset != zone_info[i].alloc_offset) &&
!btrfs_test_opt(fs_info, DEGRADED)) {
btrfs_err(fs_info,
@@ -1495,7 +1506,8 @@ static int btrfs_load_block_group_raid1(struct btrfs_block_group *bg,
static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
struct btrfs_chunk_map *map,
struct zone_info *zone_info,
- unsigned long *active)
+ unsigned long *active,
+ u64 last_alloc)
{
struct btrfs_fs_info *fs_info = bg->fs_info;
@@ -1506,10 +1518,29 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
}
for (int i = 0; i < map->num_stripes; i++) {
- if (zone_info[i].alloc_offset == WP_MISSING_DEV ||
- zone_info[i].alloc_offset == WP_CONVENTIONAL)
+ if (zone_info[i].alloc_offset == WP_MISSING_DEV)
continue;
+ if (zone_info[i].alloc_offset == WP_CONVENTIONAL) {
+ u64 stripe_nr, full_stripe_nr;
+ u64 stripe_offset;
+ int stripe_index;
+
+ stripe_nr = div64_u64(last_alloc, map->stripe_size);
+ stripe_offset = stripe_nr * map->stripe_size;
+ full_stripe_nr = div_u64(stripe_nr, map->num_stripes);
+ stripe_index = stripe_nr % map->num_stripes;
+
+ zone_info[i].alloc_offset =
+ full_stripe_nr * map->stripe_size;
+
+ if (stripe_index > i)
+ zone_info[i].alloc_offset += map->stripe_size;
+ else if (stripe_index == i)
+ zone_info[i].alloc_offset +=
+ (last_alloc - stripe_offset);
+ }
+
if (test_bit(0, active) != test_bit(i, active)) {
if (!btrfs_zone_activate(bg))
return -EIO;
@@ -1527,7 +1558,8 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
struct btrfs_chunk_map *map,
struct zone_info *zone_info,
- unsigned long *active)
+ unsigned long *active,
+ u64 last_alloc)
{
struct btrfs_fs_info *fs_info = bg->fs_info;
@@ -1538,8 +1570,7 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
}
for (int i = 0; i < map->num_stripes; i++) {
- if (zone_info[i].alloc_offset == WP_MISSING_DEV ||
- zone_info[i].alloc_offset == WP_CONVENTIONAL)
+ if (zone_info[i].alloc_offset == WP_MISSING_DEV)
continue;
if (test_bit(0, active) != test_bit(i, active)) {
@@ -1550,6 +1581,28 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
set_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &bg->runtime_flags);
}
+ if (zone_info[i].alloc_offset == WP_CONVENTIONAL) {
+ u64 stripe_nr, full_stripe_nr;
+ u64 stripe_offset;
+ int stripe_index;
+
+ stripe_nr = div64_u64(last_alloc, map->stripe_size);
+ stripe_offset = stripe_nr * map->stripe_size;
+ full_stripe_nr = div_u64(stripe_nr,
+ map->num_stripes / map->sub_stripes);
+ stripe_index = stripe_nr %
+ (map->num_stripes / map->sub_stripes);
+
+ zone_info[i].alloc_offset =
+ full_stripe_nr * map->stripe_size;
+
+ if (stripe_index > (i / map->sub_stripes))
+ zone_info[i].alloc_offset += map->stripe_size;
+ else if (stripe_index == (i / map->sub_stripes))
+ zone_info[i].alloc_offset +=
+ (last_alloc - stripe_offset);
+ }
+
if ((i % map->sub_stripes) == 0) {
bg->zone_capacity += zone_info[i].capacity;
bg->alloc_offset += zone_info[i].alloc_offset;
@@ -1638,18 +1691,22 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
ret = btrfs_load_block_group_single(cache, &zone_info[0], active);
break;
case BTRFS_BLOCK_GROUP_DUP:
- ret = btrfs_load_block_group_dup(cache, map, zone_info, active);
+ ret = btrfs_load_block_group_dup(cache, map, zone_info, active,
+ last_alloc);
break;
case BTRFS_BLOCK_GROUP_RAID1:
case BTRFS_BLOCK_GROUP_RAID1C3:
case BTRFS_BLOCK_GROUP_RAID1C4:
- ret = btrfs_load_block_group_raid1(cache, map, zone_info, active);
+ ret = btrfs_load_block_group_raid1(cache, map, zone_info,
+ active, last_alloc);
break;
case BTRFS_BLOCK_GROUP_RAID0:
- ret = btrfs_load_block_group_raid0(cache, map, zone_info, active);
+ ret = btrfs_load_block_group_raid0(cache, map, zone_info,
+ active, last_alloc);
break;
case BTRFS_BLOCK_GROUP_RAID10:
- ret = btrfs_load_block_group_raid10(cache, map, zone_info, active);
+ ret = btrfs_load_block_group_raid10(cache, map, zone_info,
+ active, last_alloc);
break;
case BTRFS_BLOCK_GROUP_RAID5:
case BTRFS_BLOCK_GROUP_RAID6:
--
2.49.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH v2] btrfs: zoned: fix alloc_offset calculation for partly conventional block groups
2025-06-05 9:18 [PATCH v2] btrfs: zoned: fix alloc_offset calculation for partly conventional block groups Johannes Thumshirn
@ 2025-06-06 0:06 ` kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2025-06-06 0:06 UTC (permalink / raw)
To: Johannes Thumshirn, linux-btrfs
Cc: oe-kbuild-all, Naohiro Aota, Damien Le Moal, David Sterba,
Josef Bacik, Johannes Thumshirn
Hi Johannes,
kernel test robot noticed the following build errors:
[auto build test ERROR on kdave/for-next]
[also build test ERROR on linus/master v6.15 next-20250605]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Johannes-Thumshirn/btrfs-zoned-fix-alloc_offset-calculation-for-partly-conventional-block-groups/20250605-171925
base: https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next
patch link: https://lore.kernel.org/r/20250605091811.386815-1-jth%40kernel.org
patch subject: [PATCH v2] btrfs: zoned: fix alloc_offset calculation for partly conventional block groups
config: i386-buildonly-randconfig-002-20250606 (https://download.01.org/0day-ci/archive/20250606/202506060751.KRci5LHx-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250606/202506060751.KRci5LHx-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506060751.KRci5LHx-lkp@intel.com/
All errors (new ones prefixed by >>):
ld: fs/btrfs/zoned.o: in function `btrfs_load_block_group_raid0':
>> fs/btrfs/zoned.c:1531: undefined reference to `__umoddi3'
ld: fs/btrfs/zoned.o: in function `btrfs_load_block_group_raid10':
fs/btrfs/zoned.c:1592: undefined reference to `__umoddi3'
vim +1531 fs/btrfs/zoned.c
1504
1505 static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
1506 struct btrfs_chunk_map *map,
1507 struct zone_info *zone_info,
1508 unsigned long *active,
1509 u64 last_alloc)
1510 {
1511 struct btrfs_fs_info *fs_info = bg->fs_info;
1512
1513 if ((map->type & BTRFS_BLOCK_GROUP_DATA) && !fs_info->stripe_root) {
1514 btrfs_err(fs_info, "zoned: data %s needs raid-stripe-tree",
1515 btrfs_bg_type_to_raid_name(map->type));
1516 return -EINVAL;
1517 }
1518
1519 for (int i = 0; i < map->num_stripes; i++) {
1520 if (zone_info[i].alloc_offset == WP_MISSING_DEV)
1521 continue;
1522
1523 if (zone_info[i].alloc_offset == WP_CONVENTIONAL) {
1524 u64 stripe_nr, full_stripe_nr;
1525 u64 stripe_offset;
1526 int stripe_index;
1527
1528 stripe_nr = div64_u64(last_alloc, map->stripe_size);
1529 stripe_offset = stripe_nr * map->stripe_size;
1530 full_stripe_nr = div_u64(stripe_nr, map->num_stripes);
> 1531 stripe_index = stripe_nr % map->num_stripes;
1532
1533 zone_info[i].alloc_offset =
1534 full_stripe_nr * map->stripe_size;
1535
1536 if (stripe_index > i)
1537 zone_info[i].alloc_offset += map->stripe_size;
1538 else if (stripe_index == i)
1539 zone_info[i].alloc_offset +=
1540 (last_alloc - stripe_offset);
1541 }
1542
1543 if (test_bit(0, active) != test_bit(i, active)) {
1544 if (!btrfs_zone_activate(bg))
1545 return -EIO;
1546 } else {
1547 if (test_bit(0, active))
1548 set_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &bg->runtime_flags);
1549 }
1550 bg->zone_capacity += zone_info[i].capacity;
1551 bg->alloc_offset += zone_info[i].alloc_offset;
1552 }
1553
1554 return 0;
1555 }
1556
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-06-06 0:06 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-05 9:18 [PATCH v2] btrfs: zoned: fix alloc_offset calculation for partly conventional block groups Johannes Thumshirn
2025-06-06 0:06 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox