Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [PATCH 0/9] btrfs: prepare for variable stripe_len
@ 2026-10-19  6:39 Qu Wenruo
  2026-10-19  6:39 ` [PATCH 1/9] btrfs: reduce the width of num_stripes and sub_stripes Qu Wenruo
                   ` (9 more replies)
  0 siblings, 10 replies; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:39 UTC (permalink / raw)
  To: linux-btrfs

This is a preparation patchset, to support a stripe_len that is not
64KiB.

This is for the future variable stripe length RAID56 feature, where
RAID56_VSL profile is allowed for data chunks, and the stripe_len can be
as small as sectorsize, meanwhile data IO are kept to be aligned to
data_size, which is power of 2, and larger than sector size.

Finally, RAID56_VSL will always have a number of devices that nr_data ==
data_size / sector_size.

So that's why we want a variable stripe_len.

This series does all the preparation, including supporting stripe_len <
PAGE_SIZE.

For now, tree-checker will still reject stripe_len != 64K, but that
limit will be removed when RAID56_VSL feature is introduced and can be
properly tested.

Qu Wenruo (9):
  btrfs: reduce the width of num_stripes and sub_stripes
  btrfs: load the on-disk btrfs_chunk::stripe_len
  btrfs: add btrfs_io_context::stripe_len and load it
  btrfs: change scrub to use stripe_len
  btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset()
  btrfs: convert volumes.c and block-group.c to use map->stripe_len
  btrfs: convert raid56.c to use rbio->bioc->stripe_len
  btrfs: convert zoned.c to use map->stripe_len
  btrfs: introduce extra limits on btrfs_chunk::stripe_len

 fs/btrfs/block-group.c  |   9 +--
 fs/btrfs/raid56.c       |  52 ++++++++++++------
 fs/btrfs/raid56.h       |   7 +--
 fs/btrfs/scrub.c        | 118 ++++++++++++++++++++++++++--------------
 fs/btrfs/tree-checker.c |  13 ++++-
 fs/btrfs/volumes.c      |  84 ++++++++++++++++++----------
 fs/btrfs/volumes.h      |  16 ++++--
 fs/btrfs/zoned.c        |  54 ++++++++++--------
 8 files changed, 226 insertions(+), 127 deletions(-)

-- 
2.56.0


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/9] btrfs: reduce the width of num_stripes and sub_stripes
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
@ 2026-10-19  6:39 ` Qu Wenruo
  2026-10-20  9:59   ` Johannes Thumshirn
  2026-10-19  6:39 ` [PATCH 2/9] btrfs: load the on-disk btrfs_chunk::stripe_len Qu Wenruo
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:39 UTC (permalink / raw)
  To: linux-btrfs

The on-disk btrfs_chunk structure uses u16 for both num_stripes and
sub_stripes, so there is no need to use "int" to represent them in
btrfs_chunk_map.

Follow the on-disk format to use u16 for those members, including
verified_stripes too.

And since verified_stripes is u16, it no longer completely fill the
hole between @refs and @start.
Instead use @num_stripes and @sub_stripes to fill the hole, and leave a 6
bytes hole between @verified_stripes and @stripes.

This doesn't save any space for btrfs_chunk_map, but leaves enough space
for future expansion.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/volumes.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 67464025e449..d97ca875c596 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -623,9 +623,9 @@ extern const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES];
 
 struct btrfs_chunk_map {
 	struct rb_node rb_node;
-	/* For mount time dev extent verification. */
-	int verified_stripes;
 	refcount_t refs;
+	u16 num_stripes;
+	u16 sub_stripes;
 	u64 start;
 	u64 chunk_len;
 	u64 dev_extent_size;
@@ -638,8 +638,8 @@ struct btrfs_chunk_map {
 	 */
 	u64 type;
 	u64 on_disk_type;
-	int num_stripes;
-	int sub_stripes;
+	/* For mount time dev extent verification. */
+	u16 verified_stripes;
 	struct btrfs_io_stripe stripes[];
 };
 
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/9] btrfs: load the on-disk btrfs_chunk::stripe_len
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
  2026-10-19  6:39 ` [PATCH 1/9] btrfs: reduce the width of num_stripes and sub_stripes Qu Wenruo
@ 2026-10-19  6:39 ` Qu Wenruo
  2026-10-20 10:01   ` Johannes Thumshirn
  2026-10-19  6:39 ` [PATCH 3/9] btrfs: add btrfs_io_context::stripe_len and load it Qu Wenruo
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:39 UTC (permalink / raw)
  To: linux-btrfs

Currently btrfs doesn't load btrfs_chunk::stripe_len into
btrfs_chunk_map, as tree-checker will reject any chunk whose stripe_len
is not 64K.

But for the future we will want stripe length other than 64K.

As a preparation for the variable stripe length in the future, load
btrfs_chunk::stripe_len into btrfs_chunk_map::stripe_len and
stripe_shift.

For now stripe_len is still 64K, no matter if it's loaded from the
on-disk metadata or newly allocated chunk.
As tree-checker still rejects any chunk whose stripe_len is not 64K.

The two new members fit into the existing hole of btrfs_chunk_map, so
the size of btrfs_chunk_map stay the same.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/volumes.c | 12 +++++++++++-
 fs/btrfs/volumes.h |  2 ++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 6574939e1295..a30b212ef0f1 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6166,6 +6166,12 @@ struct btrfs_chunk_map *btrfs_alloc_chunk_map(int num_stripes, gfp_t gfp)
 	refcount_set(&map->refs, 1);
 	RB_CLEAR_NODE(&map->rb_node);
 
+	/*
+	 * Initialize the default stripe len, selftests will utilize them
+	 * without an on-disk chunk item.
+	 */
+	map->stripe_len = BTRFS_STRIPE_LEN;
+	map->stripe_shift = ilog2(map->stripe_len);
 	return map;
 }
 
@@ -6203,6 +6209,8 @@ static struct btrfs_block_group *create_chunk(struct btrfs_trans_handle *trans,
 	map->on_disk_type = type;
 	map->sub_stripes = ctl->sub_stripes;
 	map->num_stripes = ctl->num_stripes;
+	map->stripe_len = BTRFS_STRIPE_LEN;
+	map->stripe_shift = ilog2(BTRFS_STRIPE_LEN);
 	set_real_chunk_type(map);
 
 	for (int i = 0; i < ctl->ndevs; i++) {
@@ -6381,7 +6389,7 @@ int btrfs_chunk_alloc_add_chunk_item(struct btrfs_trans_handle *trans,
 
 	btrfs_set_stack_chunk_length(chunk, bg->length);
 	btrfs_set_stack_chunk_owner(chunk, BTRFS_EXTENT_TREE_OBJECTID);
-	btrfs_set_stack_chunk_stripe_len(chunk, BTRFS_STRIPE_LEN);
+	btrfs_set_stack_chunk_stripe_len(chunk, map->stripe_len);
 	btrfs_set_stack_chunk_type(chunk, map->on_disk_type);
 	btrfs_set_stack_chunk_num_stripes(chunk, map->num_stripes);
 	btrfs_set_stack_chunk_io_align(chunk, BTRFS_STRIPE_LEN);
@@ -7781,6 +7789,8 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
 	map->chunk_len = length;
 	map->num_stripes = num_stripes;
 	map->on_disk_type = type;
+	map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+	map->stripe_shift = ilog2(map->stripe_len);
 	/*
 	 * We can't use the sub_stripes value, as for profiles other than
 	 * RAID10, they may have 0 as sub_stripes for filesystems created by
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index d97ca875c596..9dcc14cd61e2 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -640,6 +640,8 @@ struct btrfs_chunk_map {
 	u64 on_disk_type;
 	/* For mount time dev extent verification. */
 	u16 verified_stripes;
+	u8 stripe_shift;
+	u32 stripe_len;
 	struct btrfs_io_stripe stripes[];
 };
 
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/9] btrfs: add btrfs_io_context::stripe_len and load it
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
  2026-10-19  6:39 ` [PATCH 1/9] btrfs: reduce the width of num_stripes and sub_stripes Qu Wenruo
  2026-10-19  6:39 ` [PATCH 2/9] btrfs: load the on-disk btrfs_chunk::stripe_len Qu Wenruo
@ 2026-10-19  6:39 ` Qu Wenruo
  2026-10-20 10:05   ` Johannes Thumshirn
  2026-10-19  6:40 ` [PATCH 4/9] btrfs: change scrub to use stripe_len Qu Wenruo
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:39 UTC (permalink / raw)
  To: linux-btrfs

The new member will be utilized by various path that no direct
btrfs_chunk_map is available, but a stripe length is still required.

The new member is located inside a hole between @refs and @fs_info, so
no size increase for btrfs_io_context.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/volumes.c | 1 +
 fs/btrfs/volumes.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index a30b212ef0f1..ff7189ac1c49 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -7411,6 +7411,7 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
 		ret = -ENOMEM;
 		goto out;
 	}
+	bioc->stripe_len = map->stripe_len;
 	bioc->map_type = map->type;
 	bioc->use_rst = io_geom.use_rst;
 
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 9dcc14cd61e2..9356cec00a90 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -515,6 +515,7 @@ struct btrfs_discard_stripe {
  */
 struct btrfs_io_context {
 	refcount_t refs;
+	u32 stripe_len;
 	struct btrfs_fs_info *fs_info;
 	/* Taken from struct btrfs_chunk_map::type. */
 	u64 map_type;
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 4/9] btrfs: change scrub to use stripe_len
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
                   ` (2 preceding siblings ...)
  2026-10-19  6:39 ` [PATCH 3/9] btrfs: add btrfs_io_context::stripe_len and load it Qu Wenruo
@ 2026-10-19  6:40 ` Qu Wenruo
  2026-10-20 11:01   ` Johannes Thumshirn
  2026-10-19  6:40 ` [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset() Qu Wenruo
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:40 UTC (permalink / raw)
  To: linux-btrfs

One exception to note, we pre-initialize scrub_ctx::stripes[] at the
very beginning, so init_scrub_stripe() still uses BTRFS_STRIPE_LEN.

That's fine initially, as later we will call update_scrub_stripe_len()
before scrubing a new chunk, which updates scrub_stripe::nr_sectors and
stripe_len.

This has one hidden assumption that, every chunk's stripe_len is no
larger than BTRFS_STRIPE_LEN.
That will be kept for the future of variable stripe_len.

This also means, for the future of stripe_len < BTRFS_STRIPE_LEN cases,
stripe_len >> PAGE_SHIFT may be zero, so for alloc_scrub_bbio(), the
btrfs_bio_alloc() call needs to ensure we always allocate at least one
slot.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/scrub.c | 88 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 59 insertions(+), 29 deletions(-)

diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 7c2cb75b685c..b7ac9a417666 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -124,7 +124,7 @@ enum {
 };
 
 /*
- * Represent one contiguous range with a length of BTRFS_STRIPE_LEN.
+ * Represent one contiguous range with a length of stripe_len.
  */
 struct scrub_stripe {
 	struct scrub_ctx *sctx;
@@ -139,7 +139,7 @@ struct scrub_stripe {
 
 	u16 mirror_num;
 
-	/* Should be BTRFS_STRIPE_LEN / sectorsize. */
+	/* Should be stripe_len / sectorsize. */
 	u16 nr_sectors;
 
 	/*
@@ -150,6 +150,8 @@ struct scrub_stripe {
 	u16 nr_meta_extents;
 
 	atomic_t pending_io;
+	/* From btrfs_chunk_map::stripe_len. Should not exceed BTRFS_STRIPE_LEN. */
+	u32 stripe_len;
 	wait_queue_head_t io_wait;
 	wait_queue_head_t repair_wait;
 
@@ -348,7 +350,13 @@ static int init_scrub_stripe(struct btrfs_fs_info *fs_info,
 {
 	memset(stripe, 0, sizeof(*stripe));
 
+	/*
+	 * Use the max stripe_len for now.
+	 *
+	 * This will be updated for every chunk using its stripe_len.
+	 */
 	stripe->nr_sectors = BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits;
+	stripe->stripe_len = BTRFS_STRIPE_LEN;
 	stripe->state = 0;
 
 	init_waitqueue_head(&stripe->io_wait);
@@ -903,7 +911,7 @@ static void scrub_bio_add_sector(struct btrfs_bio *bbio, struct scrub_stripe *st
 	const u32 offset = sector_nr << fs_info->sectorsize_bits;
 	int ret;
 
-	ASSERT(offset + fs_info->sectorsize <= BTRFS_STRIPE_LEN);
+	ASSERT(offset + fs_info->sectorsize <= stripe->stripe_len);
 
 	if (is_vmalloc_addr(stripe->buffer)) {
 		ret = bio_add_vmalloc(&bbio->bio, stripe->buffer + offset, fs_info->sectorsize);
@@ -917,7 +925,7 @@ static void scrub_bio_add_sector(struct btrfs_bio *bbio, struct scrub_stripe *st
 
 static struct btrfs_bio *alloc_scrub_bbio(struct btrfs_fs_info *fs_info,
 					  blk_opf_t opf,
-					  u64 logical,
+					  u64 logical, u32 stripe_len,
 					  btrfs_bio_end_io_t end_io, void *private)
 {
 	struct btrfs_bio *bbio;
@@ -927,7 +935,7 @@ static struct btrfs_bio *alloc_scrub_bbio(struct btrfs_fs_info *fs_info,
 	 * different physical addresses, we have to ensure the bbio is large
 	 * enough to contain the full stripe.
 	 */
-	bbio = btrfs_bio_alloc(BTRFS_STRIPE_LEN >> PAGE_SHIFT, opf,
+	bbio = btrfs_bio_alloc(max(stripe_len >> PAGE_SHIFT, 1), opf,
 			       BTRFS_I(fs_info->btree_inode),
 			       logical, end_io, private);
 	bbio->is_scrub = true;
@@ -962,6 +970,7 @@ static void scrub_stripe_submit_repair_read(struct scrub_stripe *stripe,
 		if (!bbio)
 			bbio = alloc_scrub_bbio(fs_info, REQ_OP_READ,
 						stripe->logical + (i << fs_info->sectorsize_bits),
+						stripe->stripe_len,
 						scrub_repair_read_endio, stripe);
 
 		scrub_bio_add_sector(bbio, stripe, i);
@@ -1178,7 +1187,7 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
 		const unsigned long old_error_bitmap = scrub_bitmap_read_error(stripe);
 
 		scrub_stripe_submit_repair_read(stripe, mirror,
-						BTRFS_STRIPE_LEN, false);
+						stripe->stripe_len, false);
 		wait_scrub_stripe_io(stripe);
 		scrub_verify_one_stripe(stripe, old_error_bitmap);
 		if (scrub_bitmap_empty_error(stripe))
@@ -1328,7 +1337,8 @@ static void scrub_write_sectors(struct scrub_ctx *sctx, struct scrub_stripe *str
 		if (!bbio)
 			bbio = alloc_scrub_bbio(fs_info, REQ_OP_WRITE,
 					stripe->logical + (sector_nr << fs_info->sectorsize_bits),
-					scrub_write_endio, stripe);
+					stripe->stripe_len, scrub_write_endio,
+					stripe);
 		scrub_bio_add_sector(bbio, stripe, sector_nr);
 	}
 	if (bbio)
@@ -1418,7 +1428,7 @@ static int get_raid56_logic_offset(u64 physical, int num,
 
 		*offset = last_offset + btrfs_stripe_nr_to_offset(i);
 
-		stripe_nr = (u32)(*offset >> BTRFS_STRIPE_LEN_SHIFT) / data_stripes;
+		stripe_nr = (u32)(*offset >> map->stripe_shift) / data_stripes;
 
 		/* Work out the disk rotation on this stripe-set */
 		rot = stripe_nr % map->num_stripes;
@@ -1593,7 +1603,7 @@ static void fill_one_extent_info(struct btrfs_fs_info *fs_info,
 				 u64 extent_flags, u64 extent_gen)
 {
 	for (u64 cur_logical = max(stripe->logical, extent_start);
-	     cur_logical < min(stripe->logical + BTRFS_STRIPE_LEN,
+	     cur_logical < min(stripe->logical + stripe->stripe_len,
 			       extent_start + extent_len);
 	     cur_logical += fs_info->sectorsize) {
 		const int nr_sector = (cur_logical - stripe->logical) >>
@@ -1672,15 +1682,15 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
 	 * Round down to stripe boundary.
 	 *
 	 * The extra calculation against bg->start is to handle block groups
-	 * whose logical bytenr is not BTRFS_STRIPE_LEN aligned.
+	 * whose logical bytenr is not stripe_len aligned.
 	 */
-	stripe->logical = round_down(cur_logical - bg->start, BTRFS_STRIPE_LEN) +
+	stripe->logical = round_down(cur_logical - bg->start, stripe->stripe_len) +
 			  bg->start;
 	stripe->physical = physical + stripe->logical - logical_start;
 	stripe->dev = dev;
 	stripe->bg = bg;
 	stripe->mirror_num = mirror_num;
-	stripe_end = stripe->logical + BTRFS_STRIPE_LEN - 1;
+	stripe_end = stripe->logical + stripe->stripe_len - 1;
 
 	/* Fill the first extent info into stripe->sectors[] array. */
 	fill_one_extent_info(fs_info, stripe, extent_start, extent_len,
@@ -1720,7 +1730,8 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
 		 * Our csum bitmap should be large enough, as BTRFS_STRIPE_LEN
 		 * should contain at most 16 sectors.
 		 */
-		ASSERT(BITS_PER_LONG >= BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
+		ASSERT(BITS_PER_LONG >= (stripe->stripe_len >>
+					 fs_info->sectorsize_bits));
 
 		ret = btrfs_lookup_csums_bitmap(csum_root, csum_path,
 						stripe->logical, stripe_end,
@@ -1758,7 +1769,7 @@ static u32 stripe_length(const struct scrub_stripe *stripe)
 {
 	ASSERT(stripe->bg);
 
-	return min(BTRFS_STRIPE_LEN,
+	return min(stripe->stripe_len,
 		   stripe->bg->start + stripe->bg->length - stripe->logical);
 }
 
@@ -1768,7 +1779,7 @@ static void scrub_submit_extent_sector_read(struct scrub_stripe *stripe)
 	struct btrfs_bio *bbio = NULL;
 	unsigned int nr_sectors = stripe_length(stripe) >> fs_info->sectorsize_bits;
 	const unsigned long has_extent = scrub_bitmap_read_has_extent(stripe);
-	u64 stripe_len = BTRFS_STRIPE_LEN;
+	u64 stripe_len = stripe->stripe_len;
 	int mirror = stripe->mirror_num;
 	int i;
 
@@ -1822,7 +1833,8 @@ static void scrub_submit_extent_sector_read(struct scrub_stripe *stripe)
 			}
 
 			bbio = alloc_scrub_bbio(fs_info, REQ_OP_READ,
-						logical, scrub_read_endio, stripe);
+						logical, stripe->stripe_len,
+						scrub_read_endio, stripe);
 		}
 
 		scrub_bio_add_sector(bbio, stripe, i);
@@ -1859,7 +1871,8 @@ static void scrub_submit_initial_read(struct scrub_ctx *sctx,
 	}
 
 	bbio = alloc_scrub_bbio(fs_info, REQ_OP_READ,
-				stripe->logical, scrub_read_endio, stripe);
+				stripe->logical, stripe->stripe_len,
+				scrub_read_endio, stripe);
 	/* Read the whole range inside the chunk boundary. */
 	for (unsigned int cur = 0; cur < nr_sectors; cur++)
 		scrub_bio_add_sector(bbio, stripe, cur);
@@ -2104,7 +2117,7 @@ static int scrub_raid56_cached_parity(struct scrub_ctx *sctx,
 	/* For RAID56 write there must be an @bioc allocated. */
 	ASSERT(bioc);
 	rbio = raid56_parity_alloc_scrub_rbio(&bio, bioc, scrub_dev, extent_bitmap,
-				BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
+				map->stripe_len >> fs_info->sectorsize_bits);
 	btrfs_put_bioc(bioc);
 	if (!rbio) {
 		ret = -ENOMEM;
@@ -2115,7 +2128,7 @@ static int scrub_raid56_cached_parity(struct scrub_ctx *sctx,
 		struct scrub_stripe *stripe = &sctx->raid56_data_stripes[i];
 
 		raid56_parity_cache_data_folios(rbio, stripe->buffer,
-				full_stripe_start + (i << BTRFS_STRIPE_LEN_SHIFT));
+				full_stripe_start + (i << map->stripe_shift));
 	}
 	raid56_parity_submit_scrub_rbio(rbio);
 	wait_for_completion_io(&io_done);
@@ -2174,7 +2187,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
 
 		stripe = &sctx->raid56_data_stripes[i];
 		rot = div_u64(full_stripe_start - bg->start,
-			      data_stripes) >> BTRFS_STRIPE_LEN_SHIFT;
+			      data_stripes) >> map->stripe_shift;
 		stripe_index = (i + rot) % map->num_stripes;
 		physical = map->stripes[stripe_index].physical +
 			   btrfs_stripe_nr_to_offset(rot);
@@ -2184,7 +2197,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
 		ret = scrub_find_fill_first_stripe(bg, &extent_path, &csum_path,
 				map->stripes[stripe_index].dev, physical, 1,
 				full_stripe_start + btrfs_stripe_nr_to_offset(i),
-				BTRFS_STRIPE_LEN, stripe);
+				map->stripe_len, stripe);
 		if (ret < 0)
 			return ret;
 		/*
@@ -2272,6 +2285,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
 static int scrub_simple_mirror(struct scrub_ctx *sctx,
 			       struct btrfs_block_group *bg,
 			       u64 logical_start, u64 logical_length,
+			       u32 stripe_len,
 			       struct btrfs_device *device,
 			       u64 physical, int mirror_num)
 {
@@ -2319,7 +2333,7 @@ static int scrub_simple_mirror(struct scrub_ctx *sctx,
 
 		/* queue_scrub_stripe() returned 0, @found_logical must be updated. */
 		ASSERT(found_logical != U64_MAX);
-		cur_logical = found_logical + BTRFS_STRIPE_LEN;
+		cur_logical = found_logical + stripe_len;
 
 		/* Don't hold CPU for too long time */
 		cond_resched();
@@ -2374,6 +2388,7 @@ static int scrub_simple_stripe(struct scrub_ctx *sctx,
 	const u64 orig_logical = simple_stripe_get_logical(map, bg, stripe_index);
 	const u64 orig_physical = map->stripes[stripe_index].physical;
 	const u64 end = btrfs_block_group_end(bg);
+	const u32 stripe_len = map->stripe_len;
 	const int mirror_num = simple_stripe_mirror_num(map, stripe_index);
 	u64 cur_logical = orig_logical;
 	u64 cur_physical = orig_physical;
@@ -2386,18 +2401,27 @@ static int scrub_simple_stripe(struct scrub_ctx *sctx,
 		 * this stripe.
 		 */
 		ret = scrub_simple_mirror(sctx, bg, cur_logical,
-					  BTRFS_STRIPE_LEN, device, cur_physical,
+					  stripe_len, stripe_len,
+					  device, cur_physical,
 					  mirror_num);
 		if (ret)
 			return ret;
 		/* Skip to next stripe which belongs to the target device */
 		cur_logical += logical_increment;
 		/* For physical offset, we just go to next stripe */
-		cur_physical += BTRFS_STRIPE_LEN;
+		cur_physical += stripe_len;
 	}
 	return ret;
 }
 
+static void update_scrub_stripe_len(const struct btrfs_fs_info *fs_info,
+				    const struct btrfs_chunk_map *map,
+				    struct scrub_stripe *stripe)
+{
+	stripe->stripe_len = map->stripe_len;
+	stripe->nr_sectors = map->stripe_len >> fs_info->sectorsize_bits;
+}
+
 static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 					   struct btrfs_block_group *bg,
 					   struct btrfs_chunk_map *map,
@@ -2407,6 +2431,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 	struct btrfs_fs_info *fs_info = sctx->fs_info;
 	const u64 profile = map->type & BTRFS_BLOCK_GROUP_PROFILE_MASK;
 	const u64 chunk_logical = bg->start;
+	const u32 stripe_len = map->stripe_len;
 	int ret;
 	int ret2;
 	u64 physical = map->stripes[stripe_index].physical;
@@ -2449,6 +2474,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 				goto out;
 			sctx->raid56_data_stripes[i].bg = bg;
 			sctx->raid56_data_stripes[i].sctx = sctx;
+			update_scrub_stripe_len(fs_info, map, &sctx->raid56_data_stripes[i]);
 		}
 	}
 	/*
@@ -2469,7 +2495,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 		 * @stripe_index.
 		 */
 		ret = scrub_simple_mirror(sctx, bg, bg->start, bg->length,
-				scrub_dev, map->stripes[stripe_index].physical,
+				stripe_len, scrub_dev,
+				map->stripes[stripe_index].physical,
 				stripe_index + 1);
 		offset = 0;
 		goto out;
@@ -2507,7 +2534,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 			ret = scrub_raid56_parity_stripe(sctx, scrub_dev, bg,
 							 map, stripe_logical);
 			spin_lock(&sctx->stat_lock);
-			sctx->stat.last_physical = min(physical + BTRFS_STRIPE_LEN,
+			sctx->stat.last_physical = min(physical + stripe_len,
 						       physical_end);
 			spin_unlock(&sctx->stat_lock);
 			if (ret)
@@ -2523,13 +2550,13 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 		 * We can reuse scrub_simple_mirror() here, as the repair part
 		 * is still based on @mirror_num.
 		 */
-		ret = scrub_simple_mirror(sctx, bg, logical, BTRFS_STRIPE_LEN,
-					  scrub_dev, physical, 1);
+		ret = scrub_simple_mirror(sctx, bg, logical, stripe_len,
+					  stripe_len, scrub_dev, physical, 1);
 		if (ret < 0)
 			goto out;
 next:
 		logical += increment;
-		physical += BTRFS_STRIPE_LEN;
+		physical += stripe_len;
 		spin_lock(&sctx->stat_lock);
 		sctx->stat.last_physical = physical;
 		spin_unlock(&sctx->stat_lock);
@@ -2589,6 +2616,9 @@ static noinline_for_stack int scrub_chunk(struct scrub_ctx *sctx,
 	if (map->chunk_len < dev_extent_len)
 		goto out;
 
+	for (i = 0; i < SCRUB_TOTAL_STRIPES; i++)
+		update_scrub_stripe_len(fs_info, map, &sctx->stripes[i]);
+
 	for (i = 0; i < map->num_stripes; ++i) {
 		if (map->stripes[i].dev->bdev == scrub_dev->bdev &&
 		    map->stripes[i].physical == dev_offset) {
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset()
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
                   ` (3 preceding siblings ...)
  2026-10-19  6:40 ` [PATCH 4/9] btrfs: change scrub to use stripe_len Qu Wenruo
@ 2026-10-19  6:40 ` Qu Wenruo
  2026-10-19 21:52   ` kernel test robot
  2026-10-19  6:40 ` [PATCH 6/9] btrfs: convert volumes.c and block-group.c to use map->stripe_len Qu Wenruo
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:40 UTC (permalink / raw)
  To: linux-btrfs

That helper is currently using a fixed BTRFS_STRIPE_LEN, change it to
accept a 'u32 stripe_len'.

Also add an ASSERT() to make sure the @stripe_len passed in is power of
2, and no larger than BTRFS_STRIPE_LEN.

There is a special case where we still pass BTRFS_STRIPE_LEN into
btrfs_stripe_nr_to_offset(), that's for chunk allocation to determine
the minimal device extent size.

In that case, since our future planned map->stripe_len is always power
of 2 and no larger than BTRFS_STRIPE_LEN, we are totally fine to use the
old BTRFS_STRIPE_LEN.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/block-group.c |  3 ++-
 fs/btrfs/scrub.c       | 32 +++++++++++++++++++-------------
 fs/btrfs/volumes.c     | 40 +++++++++++++++++++++++++++-------------
 fs/btrfs/volumes.h     |  5 +++--
 fs/btrfs/zoned.c       |  7 +++++--
 5 files changed, 56 insertions(+), 31 deletions(-)

diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index f2b55ffbdaef..c0d735cee4a8 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -2302,7 +2302,8 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
 
 	/* For RAID5/6 adjust to a full IO stripe length */
 	if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
-		io_stripe_size = btrfs_stripe_nr_to_offset(nr_data_stripes(map));
+		io_stripe_size = btrfs_stripe_nr_to_offset(nr_data_stripes(map),
+							   map->stripe_len);
 
 	buf = kzalloc_objs(u64, map->num_stripes, GFP_NOFS);
 	if (!buf) {
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index b7ac9a417666..da3dc5904c18 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -1426,7 +1426,8 @@ static int get_raid56_logic_offset(u64 physical, int num,
 		u32 stripe_index;
 		u32 rot;
 
-		*offset = last_offset + btrfs_stripe_nr_to_offset(i);
+		*offset = last_offset + btrfs_stripe_nr_to_offset(i,
+							map->stripe_len);
 
 		stripe_nr = (u32)(*offset >> map->stripe_shift) / data_stripes;
 
@@ -1440,7 +1441,7 @@ static int get_raid56_logic_offset(u64 physical, int num,
 		if (stripe_index < num)
 			j++;
 	}
-	*offset = last_offset + btrfs_stripe_nr_to_offset(j);
+	*offset = last_offset + btrfs_stripe_nr_to_offset(j, map->stripe_len);
 	return 1;
 }
 
@@ -1923,7 +1924,8 @@ static void submit_initial_group_read(struct scrub_ctx *sctx,
 	ASSERT(first_slot + nr_stripes <= SCRUB_TOTAL_STRIPES);
 
 	scrub_throttle_dev_io(sctx, sctx->stripes[0].dev,
-			      btrfs_stripe_nr_to_offset(nr_stripes));
+			      btrfs_stripe_nr_to_offset(nr_stripes,
+						sctx->stripes[0].stripe_len));
 	blk_start_plug(&plug);
 	for (int i = 0; i < nr_stripes; i++) {
 		struct scrub_stripe *stripe = &sctx->stripes[first_slot + i];
@@ -2101,7 +2103,7 @@ static int scrub_raid56_cached_parity(struct scrub_ctx *sctx,
 	struct btrfs_raid_bio *rbio;
 	struct bio bio;
 	const int data_stripes = nr_data_stripes(map);
-	u64 length = btrfs_stripe_nr_to_offset(data_stripes);
+	u64 length = btrfs_stripe_nr_to_offset(data_stripes, map->stripe_len);
 	int ret;
 
 	bio_init(&bio, NULL, NULL, 0, REQ_OP_READ);
@@ -2150,6 +2152,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
 	BTRFS_PATH_AUTO_RELEASE(csum_path);
 	struct scrub_stripe *stripe;
 	bool all_empty = true;
+	const u32 stripe_len = map->stripe_len;
 	const int data_stripes = nr_data_stripes(map);
 	unsigned long extent_bitmap = 0;
 	int ret;
@@ -2190,14 +2193,15 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
 			      data_stripes) >> map->stripe_shift;
 		stripe_index = (i + rot) % map->num_stripes;
 		physical = map->stripes[stripe_index].physical +
-			   btrfs_stripe_nr_to_offset(rot);
+			   btrfs_stripe_nr_to_offset(rot, stripe_len);
 
 		scrub_reset_stripe(stripe);
 		set_bit(SCRUB_STRIPE_FLAG_NO_REPORT, &stripe->state);
 		ret = scrub_find_fill_first_stripe(bg, &extent_path, &csum_path,
 				map->stripes[stripe_index].dev, physical, 1,
-				full_stripe_start + btrfs_stripe_nr_to_offset(i),
-				map->stripe_len, stripe);
+				full_stripe_start +
+				btrfs_stripe_nr_to_offset(i, stripe_len),
+				stripe_len, stripe);
 		if (ret < 0)
 			return ret;
 		/*
@@ -2206,7 +2210,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
 		 */
 		if (ret > 0) {
 			stripe->logical = full_stripe_start +
-					  btrfs_stripe_nr_to_offset(i);
+					  btrfs_stripe_nr_to_offset(i, stripe_len);
 			stripe->dev = map->stripes[stripe_index].dev;
 			stripe->mirror_num = 1;
 			set_bit(SCRUB_STRIPE_FLAG_INITIALIZED, &stripe->state);
@@ -2347,7 +2351,8 @@ static u64 simple_stripe_full_stripe_len(const struct btrfs_chunk_map *map)
 	ASSERT(map->type & (BTRFS_BLOCK_GROUP_RAID0 |
 			    BTRFS_BLOCK_GROUP_RAID10));
 
-	return btrfs_stripe_nr_to_offset(map->num_stripes / map->sub_stripes);
+	return btrfs_stripe_nr_to_offset(map->num_stripes / map->sub_stripes,
+					 map->stripe_len);
 }
 
 /* Get the logical bytenr for the stripe */
@@ -2363,8 +2368,8 @@ static u64 simple_stripe_get_logical(struct btrfs_chunk_map *map,
 	 * (stripe_index / sub_stripes) gives how many data stripes we need to
 	 * skip.
 	 */
-	return btrfs_stripe_nr_to_offset(stripe_index / map->sub_stripes) +
-	       bg->start;
+	return btrfs_stripe_nr_to_offset(stripe_index / map->sub_stripes,
+					 map->stripe_len) + bg->start;
 }
 
 /* Get the mirror number for the stripe */
@@ -2503,7 +2508,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 	}
 	if (profile & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) {
 		ret = scrub_simple_stripe(sctx, bg, map, scrub_dev, stripe_index);
-		offset = btrfs_stripe_nr_to_offset(stripe_index / map->sub_stripes);
+		offset = btrfs_stripe_nr_to_offset(stripe_index / map->sub_stripes,
+						   stripe_len);
 		goto out;
 	}
 
@@ -2518,7 +2524,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 
 	/* Initialize @offset in case we need to go to out: label */
 	get_raid56_logic_offset(physical, stripe_index, map, &offset, NULL);
-	increment = btrfs_stripe_nr_to_offset(nr_data_stripes(map));
+	increment = btrfs_stripe_nr_to_offset(nr_data_stripes(map), stripe_len);
 
 	/*
 	 * Due to the rotation, for RAID56 it's better to iterate each stripe
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index ff7189ac1c49..6a3ae8a081fe 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5823,7 +5823,8 @@ static void init_alloc_chunk_ctl_policy_regular(
 	/* We don't want a chunk larger than 10% of writable space */
 	ctl->max_chunk_size = min(mult_perc(fs_devices->total_rw_bytes, 10),
 				  ctl->max_chunk_size);
-	ctl->dev_extent_min = btrfs_stripe_nr_to_offset(ctl->dev_stripes);
+	ctl->dev_extent_min = btrfs_stripe_nr_to_offset(ctl->dev_stripes,
+							BTRFS_STRIPE_LEN);
 }
 
 static void init_alloc_chunk_ctl_policy_zoned(
@@ -6587,7 +6588,8 @@ unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
 
 	if (!WARN_ON(IS_ERR(map))) {
 		if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
-			len = btrfs_stripe_nr_to_offset(nr_data_stripes(map));
+			len = btrfs_stripe_nr_to_offset(nr_data_stripes(map),
+							map->stripe_len);
 		btrfs_free_chunk_map(map);
 	}
 	return len;
@@ -6784,6 +6786,7 @@ struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
 	u64 stripe_end_offset;
 	u64 stripe_offset;
 	u32 stripe_index;
+	u32 stripe_len;
 	u32 factor = 0;
 	u32 sub_stripes = 0;
 	u32 stripes_per_dev = 0;
@@ -6820,6 +6823,7 @@ struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
 		goto out_free_map;
 	}
 
+	stripe_len = map->stripe_len;
 	offset = logical - map->start;
 	length = min_t(u64, map->start + map->chunk_len - logical, length);
 	*length_ret = length;
@@ -6831,12 +6835,13 @@ struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
 	stripe_nr = offset >> BTRFS_STRIPE_LEN_SHIFT;
 
 	/* stripe_offset is the offset of this block in its stripe */
-	stripe_offset = offset - btrfs_stripe_nr_to_offset(stripe_nr);
+	stripe_offset = offset - btrfs_stripe_nr_to_offset(stripe_nr,
+							   stripe_len);
 
 	stripe_nr_end = round_up(offset + length, BTRFS_STRIPE_LEN) >>
 			BTRFS_STRIPE_LEN_SHIFT;
 	stripe_cnt = stripe_nr_end - stripe_nr;
-	stripe_end_offset = btrfs_stripe_nr_to_offset(stripe_nr_end) -
+	stripe_end_offset = btrfs_stripe_nr_to_offset(stripe_nr_end, stripe_len) -
 			    (offset + length);
 	/*
 	 * after this, stripe_nr is the number of stripes on this
@@ -6879,12 +6884,14 @@ struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
 	for (i = 0; i < *num_stripes; i++) {
 		stripes[i].physical =
 			map->stripes[stripe_index].physical +
-			stripe_offset + btrfs_stripe_nr_to_offset(stripe_nr);
+			stripe_offset + btrfs_stripe_nr_to_offset(stripe_nr,
+								  stripe_len);
 		stripes[i].dev = map->stripes[stripe_index].dev;
 
 		if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
 				 BTRFS_BLOCK_GROUP_RAID10)) {
-			stripes[i].length = btrfs_stripe_nr_to_offset(stripes_per_dev);
+			stripes[i].length = btrfs_stripe_nr_to_offset(stripes_per_dev,
+								      stripe_len);
 
 			if (i / sub_stripes < remaining_stripes)
 				stripes[i].length += BTRFS_STRIPE_LEN;
@@ -7022,6 +7029,8 @@ static void handle_ops_on_dev_replace(struct btrfs_io_context *bioc,
 static u64 btrfs_max_io_len(struct btrfs_chunk_map *map, u64 offset,
 			    struct btrfs_io_geometry *io_geom)
 {
+	const u32 stripe_len = map->stripe_len;
+
 	/*
 	 * Stripe_nr is the stripe where this block falls.  stripe_offset is
 	 * the offset of this block in its stripe.
@@ -7033,7 +7042,8 @@ static u64 btrfs_max_io_len(struct btrfs_chunk_map *map, u64 offset,
 
 	if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
 		unsigned long full_stripe_len =
-			btrfs_stripe_nr_to_offset(nr_data_stripes(map));
+			btrfs_stripe_nr_to_offset(nr_data_stripes(map),
+						  stripe_len);
 
 		/*
 		 * For full stripe start, we use previously calculated
@@ -7045,7 +7055,8 @@ static u64 btrfs_max_io_len(struct btrfs_chunk_map *map, u64 offset,
 		 * not ensured to be power of 2.
 		 */
 		io_geom->raid56_full_stripe_start = btrfs_stripe_nr_to_offset(
-			rounddown(io_geom->stripe_nr, nr_data_stripes(map)));
+			rounddown(io_geom->stripe_nr, nr_data_stripes(map)),
+			stripe_len);
 
 		ASSERT(io_geom->raid56_full_stripe_start + full_stripe_len > offset,
 		       "raid56_full_stripe_start=%llu full_stripe_len=%lu offset=%llu",
@@ -7084,7 +7095,8 @@ static int set_io_stripe(struct btrfs_fs_info *fs_info, u64 logical,
 
 	dst->physical = map->stripes[io_geom->stripe_index].physical +
 			io_geom->stripe_offset +
-			btrfs_stripe_nr_to_offset(io_geom->stripe_nr);
+			btrfs_stripe_nr_to_offset(io_geom->stripe_nr,
+						  map->stripe_len);
 	return 0;
 }
 
@@ -7207,7 +7219,7 @@ static void map_blocks_raid56_write(struct btrfs_chunk_map *map,
 	/* Return the length to the full stripe end. */
 	*length = min(logical + *length,
 		      io_geom->raid56_full_stripe_start + map->start +
-		      btrfs_stripe_nr_to_offset(data_stripes)) -
+		      btrfs_stripe_nr_to_offset(data_stripes, map->stripe_len)) -
 		logical;
 	io_geom->stripe_index = 0;
 	io_geom->stripe_offset = 0;
@@ -7434,7 +7446,8 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
 		 */
 		bioc->full_stripe_logical = map->start +
 			btrfs_stripe_nr_to_offset(io_geom.stripe_nr *
-						  nr_data_stripes(map));
+						  nr_data_stripes(map),
+						  map->stripe_len);
 		for (int i = 0; i < io_geom.num_stripes; i++) {
 			struct btrfs_io_stripe *dst = &bioc->stripes[i];
 			u32 stripe_index;
@@ -7444,7 +7457,8 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
 			dst->physical =
 				map->stripes[stripe_index].physical +
 				io_geom.stripe_offset +
-				btrfs_stripe_nr_to_offset(io_geom.stripe_nr);
+				btrfs_stripe_nr_to_offset(io_geom.stripe_nr,
+							  map->stripe_len);
 		}
 	} else {
 		/*
@@ -9070,7 +9084,7 @@ static void map_raid56_repair_block(struct btrfs_io_context *bioc,
 
 	for (i = 0; i < data_stripes; i++) {
 		u64 stripe_start = bioc->full_stripe_logical +
-				   btrfs_stripe_nr_to_offset(i);
+				   btrfs_stripe_nr_to_offset(i, bioc->stripe_len);
 
 		if (logical >= stripe_start &&
 		    logical < stripe_start + BTRFS_STRIPE_LEN)
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 9356cec00a90..75b1179776c8 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -722,9 +722,10 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
  * @stripe_nr is u32, with left shift it can overflow u32 for chunks larger
  * than 4G.  This does the proper type cast to avoid overflow.
  */
-static inline u64 btrfs_stripe_nr_to_offset(u32 stripe_nr)
+static inline u64 btrfs_stripe_nr_to_offset(u32 stripe_nr, u32 stripe_len)
 {
-	return (u64)stripe_nr << BTRFS_STRIPE_LEN_SHIFT;
+	ASSERT(is_power_of_2(stripe_len) && stripe_len <= BTRFS_STRIPE_LEN);
+	return (u64)stripe_nr << ilog2(stripe_len);
 }
 
 void btrfs_get_bioc(struct btrfs_io_context *bioc);
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 1cda88332284..37084c8d8d75 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -1630,7 +1630,9 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
 
 		if (zone_info[i].alloc_offset == WP_CONVENTIONAL) {
 			has_conventional = true;
-			zone_info[i].alloc_offset = btrfs_stripe_nr_to_offset(stripe_nr);
+			zone_info[i].alloc_offset =
+				btrfs_stripe_nr_to_offset(stripe_nr,
+							  map->stripe_len);
 
 			if (stripe_index > i)
 				zone_info[i].alloc_offset += BTRFS_STRIPE_LEN;
@@ -1772,7 +1774,8 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
 
 		if (raid0_allocs[idx] == WP_CONVENTIONAL) {
 			has_conventional = true;
-			raid0_allocs[idx] = btrfs_stripe_nr_to_offset(stripe_nr);
+			raid0_allocs[idx] = btrfs_stripe_nr_to_offset(stripe_nr,
+								map->stripe_len);
 
 			if (stripe_index > idx)
 				raid0_allocs[idx] += BTRFS_STRIPE_LEN;
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 6/9] btrfs: convert volumes.c and block-group.c to use map->stripe_len
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
                   ` (4 preceding siblings ...)
  2026-10-19  6:40 ` [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset() Qu Wenruo
@ 2026-10-19  6:40 ` Qu Wenruo
  2026-10-20 11:03   ` Johannes Thumshirn
  2026-10-19  6:40 ` [PATCH 7/9] btrfs: convert raid56.c to use rbio->bioc->stripe_len Qu Wenruo
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:40 UTC (permalink / raw)
  To: linux-btrfs

There are still some BTRFS_STRIPE_LEN usage remaining, but they are all
for chunk allocation.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/block-group.c |  6 +++---
 fs/btrfs/volumes.c     | 41 ++++++++++++++++++++++-------------------
 2 files changed, 25 insertions(+), 22 deletions(-)

diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index c0d735cee4a8..092cdbedf39f 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -2297,7 +2297,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
 		return -EIO;
 
 	data_stripe_length = map->dev_extent_size;
-	io_stripe_size = BTRFS_STRIPE_LEN;
+	io_stripe_size = map->stripe_len;
 	chunk_start = map->start;
 
 	/* For RAID5/6 adjust to a full IO stripe length */
@@ -2322,9 +2322,9 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
 			continue;
 
 		stripe_nr = (physical - map->stripes[i].physical) >>
-			    BTRFS_STRIPE_LEN_SHIFT;
+			    map->stripe_shift;
 		offset = (physical - map->stripes[i].physical) &
-			 BTRFS_STRIPE_LEN_MASK;
+			 (map->stripe_len - 1);
 
 		if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
 				 BTRFS_BLOCK_GROUP_RAID10))
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 6a3ae8a081fe..c1e2ba046609 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6168,8 +6168,8 @@ struct btrfs_chunk_map *btrfs_alloc_chunk_map(int num_stripes, gfp_t gfp)
 	RB_CLEAR_NODE(&map->rb_node);
 
 	/*
-	 * Initialize the default stripe len, selftests will utilize them
-	 * without an on-disk chunk item.
+	 * Initialize the default stripe len, selftests and some other call
+	 * sites relies on the sane default value.
 	 */
 	map->stripe_len = BTRFS_STRIPE_LEN;
 	map->stripe_shift = ilog2(map->stripe_len);
@@ -6210,8 +6210,6 @@ static struct btrfs_block_group *create_chunk(struct btrfs_trans_handle *trans,
 	map->on_disk_type = type;
 	map->sub_stripes = ctl->sub_stripes;
 	map->num_stripes = ctl->num_stripes;
-	map->stripe_len = BTRFS_STRIPE_LEN;
-	map->stripe_shift = ilog2(BTRFS_STRIPE_LEN);
 	set_real_chunk_type(map);
 
 	for (int i = 0; i < ctl->ndevs; i++) {
@@ -6393,8 +6391,8 @@ int btrfs_chunk_alloc_add_chunk_item(struct btrfs_trans_handle *trans,
 	btrfs_set_stack_chunk_stripe_len(chunk, map->stripe_len);
 	btrfs_set_stack_chunk_type(chunk, map->on_disk_type);
 	btrfs_set_stack_chunk_num_stripes(chunk, map->num_stripes);
-	btrfs_set_stack_chunk_io_align(chunk, BTRFS_STRIPE_LEN);
-	btrfs_set_stack_chunk_io_width(chunk, BTRFS_STRIPE_LEN);
+	btrfs_set_stack_chunk_io_align(chunk, map->stripe_len);
+	btrfs_set_stack_chunk_io_width(chunk, map->stripe_len);
 	btrfs_set_stack_chunk_sector_size(chunk, fs_info->sectorsize);
 	btrfs_set_stack_chunk_sub_stripes(chunk, map->sub_stripes);
 
@@ -6832,14 +6830,14 @@ struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
 	 * stripe_nr counts the total number of stripes we have to stride
 	 * to get to this block
 	 */
-	stripe_nr = offset >> BTRFS_STRIPE_LEN_SHIFT;
+	stripe_nr = offset >> map->stripe_shift;
 
 	/* stripe_offset is the offset of this block in its stripe */
 	stripe_offset = offset - btrfs_stripe_nr_to_offset(stripe_nr,
 							   stripe_len);
 
-	stripe_nr_end = round_up(offset + length, BTRFS_STRIPE_LEN) >>
-			BTRFS_STRIPE_LEN_SHIFT;
+	stripe_nr_end = round_up(offset + length, stripe_len) >>
+			map->stripe_shift;
 	stripe_cnt = stripe_nr_end - stripe_nr;
 	stripe_end_offset = btrfs_stripe_nr_to_offset(stripe_nr_end, stripe_len) -
 			    (offset + length);
@@ -6894,7 +6892,7 @@ struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
 								      stripe_len);
 
 			if (i / sub_stripes < remaining_stripes)
-				stripes[i].length += BTRFS_STRIPE_LEN;
+				stripes[i].length += stripe_len;
 
 			/*
 			 * Special for the first stripe and
@@ -7035,8 +7033,8 @@ static u64 btrfs_max_io_len(struct btrfs_chunk_map *map, u64 offset,
 	 * Stripe_nr is the stripe where this block falls.  stripe_offset is
 	 * the offset of this block in its stripe.
 	 */
-	io_geom->stripe_offset = offset & BTRFS_STRIPE_LEN_MASK;
-	io_geom->stripe_nr = offset >> BTRFS_STRIPE_LEN_SHIFT;
+	io_geom->stripe_offset = offset & (stripe_len - 1);
+	io_geom->stripe_nr = offset >> map->stripe_shift;
 	ASSERT(io_geom->stripe_offset < U32_MAX,
 	       "stripe_offset=%llu", io_geom->stripe_offset);
 
@@ -7077,7 +7075,7 @@ static u64 btrfs_max_io_len(struct btrfs_chunk_map *map, u64 offset,
 	 * a single disk).
 	 */
 	if (map->type & BTRFS_BLOCK_GROUP_STRIPE_MASK)
-		return BTRFS_STRIPE_LEN - io_geom->stripe_offset;
+		return stripe_len - io_geom->stripe_offset;
 	return U64_MAX;
 }
 
@@ -7742,10 +7740,12 @@ static struct btrfs_device *handle_missing_device(struct btrfs_fs_info *fs_info,
 }
 
 static bool is_same_chunk_map(const struct btrfs_chunk_map *map, u64 logical,
-			      u64 length, u64 type, u16 num_stripes)
+			      u64 length, u64 type, u32 stripe_len,
+			      u16 num_stripes)
 {
 	if (map->start != logical || map->chunk_len != length ||
-	    map->on_disk_type != type || map->num_stripes != num_stripes)
+	    map->on_disk_type != type || map->stripe_len != stripe_len ||
+	    map->num_stripes != num_stripes)
 		return false;
 	return true;
 }
@@ -7760,6 +7760,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
 	u64 length;
 	u64 devid;
 	u64 type;
+	u32 stripe_len;
 	u8 uuid[BTRFS_UUID_SIZE];
 	int index;
 	int num_stripes;
@@ -7770,6 +7771,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
 	length = btrfs_chunk_length(leaf, chunk);
 	type = btrfs_chunk_type(leaf, chunk);
 	index = btrfs_bg_flags_to_raid_index(type);
+	stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
 	num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
 
 #if BITS_PER_LONG == 32
@@ -7784,7 +7786,8 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
 	/* Already mapped? Check if the existing one matches. */
 	if (map) {
 		if (unlikely(!is_same_chunk_map(map, logical, length,
-						type, num_stripes))) {
+						type, stripe_len,
+						num_stripes))) {
 			btrfs_err(fs_info,
 		"existing chunk %llu doesn't match the new one at %llu",
 				  map->start, logical);
@@ -7804,7 +7807,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
 	map->chunk_len = length;
 	map->num_stripes = num_stripes;
 	map->on_disk_type = type;
-	map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+	map->stripe_len = stripe_len;
 	map->stripe_shift = ilog2(map->stripe_len);
 	/*
 	 * We can't use the sub_stripes value, as for profiles other than
@@ -9087,14 +9090,14 @@ static void map_raid56_repair_block(struct btrfs_io_context *bioc,
 				   btrfs_stripe_nr_to_offset(i, bioc->stripe_len);
 
 		if (logical >= stripe_start &&
-		    logical < stripe_start + BTRFS_STRIPE_LEN)
+		    logical < stripe_start + bioc->stripe_len)
 			break;
 	}
 	ASSERT(i < data_stripes, "i=%d data_stripes=%d", i, data_stripes);
 	smap->dev = bioc->stripes[i].dev;
 	smap->physical = bioc->stripes[i].physical +
 			((logical - bioc->full_stripe_logical) &
-			 BTRFS_STRIPE_LEN_MASK);
+			 (bioc->stripe_len - 1));
 }
 
 /*
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 7/9] btrfs: convert raid56.c to use rbio->bioc->stripe_len
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
                   ` (5 preceding siblings ...)
  2026-10-19  6:40 ` [PATCH 6/9] btrfs: convert volumes.c and block-group.c to use map->stripe_len Qu Wenruo
@ 2026-10-19  6:40 ` Qu Wenruo
  2026-10-19  6:40 ` [PATCH 8/9] btrfs: convert zoned.c to use map->stripe_len Qu Wenruo
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:40 UTC (permalink / raw)
  To: linux-btrfs

So that raid56 can support stripe length other than BTRFS_STRIPE_LEN.

There are several extra things to note:

- btrfs_raid_bio::stripe_npages is removed
  With stripe_len < BTRFS_STRIPE_LEN, there is no guarantee that a page
  won't cross multiple stripes.

  E.g. with 4K stripe_len and sectorsize, 2 data stripes, with 64K page
  size, one page will cover the full stripe.

  So stripe_npages no longer makes sense, just remove it.

- alloc_rbio_data_pages()/alloc_rbio_parity_pages() fallback
  For the same above reason, a page can contain both data and parity
  blocks.
  In that case we can no longer only allocate pages for data/parity.

  Add a fallback that if stripe_len is smaller than page size, always
  allocate all the pages.

  This is not the best solution, but should be good enough for now until
  the variable stripe_len is properly tested.

- steal_rbio() fallback
  If stripe_len is smaller than PAGE_SIZE, it's hard to only steal the
  data pages.

  Again skip the stealing if stripe_len is smaller than PAGE_SIZE.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/raid56.c | 52 +++++++++++++++++++++++++++++++----------------
 fs/btrfs/raid56.h |  7 +------
 2 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 5ec31299f1c3..ed415a247117 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -417,6 +417,9 @@ static void steal_rbio(struct btrfs_raid_bio *src, struct btrfs_raid_bio *dest)
 
 	if (!test_bit(RBIO_CACHE_READY_BIT, &src->flags))
 		return;
+	/* Data and P/Q can be mixed into a page, skip stealing. */
+	if (src->bioc->stripe_len < PAGE_SIZE)
+		return;
 
 	for (i = 0; i < dest->nr_pages; i++) {
 		struct page *p = src->stripe_pages[i];
@@ -624,12 +627,13 @@ static void cache_rbio(struct btrfs_raid_bio *rbio)
 static int rbio_is_full(struct btrfs_raid_bio *rbio)
 {
 	unsigned long size = rbio->bio_list_bytes;
+	const u32 stripe_len = rbio->bioc->stripe_len;
 	int ret = 1;
 
 	spin_lock(&rbio->bio_list_lock);
-	if (size != rbio->nr_data * BTRFS_STRIPE_LEN)
+	if (size != rbio->nr_data * stripe_len)
 		ret = 0;
-	BUG_ON(size > rbio->nr_data * BTRFS_STRIPE_LEN);
+	BUG_ON(size > rbio->nr_data * stripe_len);
 	spin_unlock(&rbio->bio_list_lock);
 
 	return ret;
@@ -1041,11 +1045,12 @@ static phys_addr_t sector_paddr_in_rbio(struct btrfs_raid_bio *rbio,
 static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
 					 struct btrfs_io_context *bioc)
 {
+	const u32 stripe_len = bioc->stripe_len;
 	const unsigned int real_stripes = bioc->num_stripes - bioc->replace_nr_stripes;
-	const unsigned int stripe_npages = BTRFS_STRIPE_LEN >> PAGE_SHIFT;
-	const unsigned int num_pages = stripe_npages * real_stripes;
+	const unsigned int num_pages = round_up(stripe_len * real_stripes, PAGE_SIZE) >>
+				       PAGE_SHIFT;
 	const unsigned int stripe_nsectors =
-		BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits;
+		stripe_len >> fs_info->sectorsize_bits;
 	const unsigned int num_sectors = stripe_nsectors * real_stripes;
 	const unsigned int step = min(fs_info->sectorsize, PAGE_SIZE);
 	const unsigned int sector_nsteps = fs_info->sectorsize / step;
@@ -1105,7 +1110,6 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
 	rbio->nr_pages = num_pages;
 	rbio->nr_sectors = num_sectors;
 	rbio->real_stripes = real_stripes;
-	rbio->stripe_npages = stripe_npages;
 	rbio->stripe_nsectors = stripe_nsectors;
 	rbio->sector_nsteps = sector_nsteps;
 	refcount_set(&rbio->refs, 1);
@@ -1134,9 +1138,17 @@ static int alloc_rbio_pages(struct btrfs_raid_bio *rbio)
 /* only allocate pages for p/q stripes */
 static int alloc_rbio_parity_pages(struct btrfs_raid_bio *rbio)
 {
-	const int data_pages = rbio->nr_data * rbio->stripe_npages;
+	int data_pages;
 	int ret;
 
+	/*
+	 * Page size larger than stripe size, we can not only allocate
+	 * pages for P/Q stripes.
+	 */
+	if (rbio->bioc->stripe_len < PAGE_SIZE)
+		return alloc_rbio_pages(rbio);
+
+	data_pages = rbio->nr_data * (rbio->bioc->stripe_len >> PAGE_SHIFT);
 	ret = btrfs_alloc_page_array(rbio->nr_pages - data_pages,
 				     rbio->stripe_pages + data_pages, GFP_NOFS);
 	if (ret < 0)
@@ -1274,7 +1286,7 @@ static int rbio_add_io_paddrs(struct btrfs_raid_bio *rbio, struct bio_list *bio_
 
 	/* put a new bio on the list */
 	bio = bio_alloc(stripe->dev->bdev,
-			max(BTRFS_STRIPE_LEN >> PAGE_SHIFT, 1),
+			max(rbio->bioc->stripe_len >> PAGE_SHIFT, 1),
 			op, GFP_NOFS);
 	bio->bi_iter.bi_sector = disk_start >> SECTOR_SHIFT;
 	bio->bi_private = rbio;
@@ -1715,9 +1727,13 @@ static void submit_read_wait_bio_list(struct btrfs_raid_bio *rbio,
 
 static int alloc_rbio_data_pages(struct btrfs_raid_bio *rbio)
 {
-	const int data_pages = rbio->nr_data * rbio->stripe_npages;
+	int data_pages;
 	int ret;
 
+	if (rbio->bioc->stripe_len < PAGE_SIZE)
+		return alloc_rbio_pages(rbio);
+
+	data_pages = rbio->nr_data * (rbio->bioc->stripe_len >> PAGE_SHIFT);
 	ret = btrfs_alloc_page_array(data_pages, rbio->stripe_pages, GFP_NOFS);
 	if (ret < 0)
 		return ret;
@@ -1804,7 +1820,7 @@ static void rbio_add_bio(struct btrfs_raid_bio *rbio, struct bio *orig_bio)
 
 	ASSERT_RBIO_LOGICAL(orig_logical >= full_stripe_start &&
 			    orig_logical + orig_len <= full_stripe_start +
-			    rbio->nr_data * BTRFS_STRIPE_LEN,
+			    rbio->nr_data * rbio->bioc->stripe_len,
 			    rbio, orig_logical);
 
 	bio_list_add(&rbio->bio_list, orig_bio);
@@ -3012,6 +3028,7 @@ void raid56_parity_cache_data_folios(struct btrfs_raid_bio *rbio,
 	struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
 	const u64 offset_in_full_stripe = data_logical -
 					  rbio->bioc->full_stripe_logical;
+	const u32 stripe_len = rbio->bioc->stripe_len;
 	int ret;
 
 	/*
@@ -3027,19 +3044,20 @@ void raid56_parity_cache_data_folios(struct btrfs_raid_bio *rbio,
 		return;
 
 	/* data_logical must be at stripe boundary and inside the full stripe. */
-	ASSERT(IS_ALIGNED(offset_in_full_stripe, BTRFS_STRIPE_LEN));
-	ASSERT(offset_in_full_stripe < (rbio->nr_data << BTRFS_STRIPE_LEN_SHIFT));
+	ASSERT(IS_ALIGNED(offset_in_full_stripe, stripe_len));
+	ASSERT(offset_in_full_stripe < (rbio->nr_data << ilog2(stripe_len)));
 
 	for (unsigned int cur_off = offset_in_full_stripe;
-	     cur_off < offset_in_full_stripe + BTRFS_STRIPE_LEN;
+	     cur_off < offset_in_full_stripe + stripe_len;
 	     cur_off += PAGE_SIZE) {
 		const unsigned int pindex = cur_off >> PAGE_SHIFT;
+		const u32 cur_len = min(stripe_len, PAGE_SIZE);
 
-		ASSERT(cur_off - offset_in_full_stripe + PAGE_SIZE <= BTRFS_STRIPE_LEN);
-		memcpy_to_page(rbio->stripe_pages[pindex], 0,
-			       vaddr + cur_off - offset_in_full_stripe, PAGE_SIZE);
+		ASSERT(cur_off - offset_in_full_stripe + cur_len <= stripe_len);
+		memcpy_to_page(rbio->stripe_pages[pindex], offset_in_page(cur_off),
+			       vaddr + cur_off - offset_in_full_stripe, cur_len);
 	}
 	bitmap_set(rbio->stripe_uptodate_bitmap,
 		   offset_in_full_stripe >> fs_info->sectorsize_bits,
-		   BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
+		   stripe_len >> fs_info->sectorsize_bits);
 }
diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
index 8542648199f1..8700910b8dc9 100644
--- a/fs/btrfs/raid56.h
+++ b/fs/btrfs/raid56.h
@@ -60,8 +60,6 @@ enum btrfs_rbio_ops {
  * stripe_pages[] array stores all the pages covering the full stripe, including
  * data and P/Q pages.
  * stripe_pages[0] is the first page of the first data stripe.
- * stripe_pages[BTRFS_STRIPE_LEN / PAGE_SIZE] is the first page of the second
- * data stripe.
  *
  * Some pointers inside stripe_pages[] can be NULL, e.g. for a full stripe write
  * (the bio covers all data stripes) there is no need to allocate pages for
@@ -81,7 +79,7 @@ enum btrfs_rbio_ops {
  *
  * - sector_nr
  *   Starts from 0 (representing the first sector of the stripe), ends
- *   at BTRFS_STRIPE_LEN / sectorsize - 1.
+ *   at stripe_len / sectorsize - 1.
  *
  * - step_nr
  *   A step is min(sector_size, PAGE_SIZE).
@@ -153,9 +151,6 @@ struct btrfs_raid_bio {
 	/* Number of all stripes (including P/Q) */
 	u8 real_stripes;
 
-	/* How many pages there are for each stripe */
-	u8 stripe_npages;
-
 	/* How many sectors there are for each stripe */
 	u8 stripe_nsectors;
 
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 8/9] btrfs: convert zoned.c to use map->stripe_len
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
                   ` (6 preceding siblings ...)
  2026-10-19  6:40 ` [PATCH 7/9] btrfs: convert raid56.c to use rbio->bioc->stripe_len Qu Wenruo
@ 2026-10-19  6:40 ` Qu Wenruo
  2026-10-20 11:07   ` Johannes Thumshirn
  2026-10-19  6:40 ` [PATCH 9/9] btrfs: introduce extra limits on btrfs_chunk::stripe_len Qu Wenruo
  2026-10-19  7:45 ` [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
  9 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:40 UTC (permalink / raw)
  To: linux-btrfs

There are still several call sites using BTRFS_STRIPE_LEN, but that's
when doing the basic zoned checks.

For other call sites with a btrfs_chunk_map, use map->stripe_len instead
of the hardcoded BTRFS_STRIPE_LEN.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/zoned.c | 53 +++++++++++++++++++++++++-----------------------
 1 file changed, 28 insertions(+), 25 deletions(-)

diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 37084c8d8d75..263f8a5475e8 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -1576,6 +1576,8 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
 					u64 last_alloc)
 {
 	struct btrfs_fs_info *fs_info = bg->fs_info;
+	const u32 stripe_len = map->stripe_len;
+	const u8 stripe_shift = map->stripe_shift;
 	u64 stripe_nr = 0, stripe_offset = 0;
 	u64 prev_offset = 0;
 	u32 stripe_index = 0;
@@ -1599,18 +1601,18 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
 		    zone_info[i].alloc_offset == WP_CONVENTIONAL)
 			continue;
 
-		stripe_nr = zone_info[i].alloc_offset >> BTRFS_STRIPE_LEN_SHIFT;
-		stripe_offset = zone_info[i].alloc_offset & BTRFS_STRIPE_LEN_MASK;
+		stripe_nr = zone_info[i].alloc_offset >> stripe_shift;
+		stripe_offset = zone_info[i].alloc_offset & (stripe_len - 1);
 		if (stripe_offset == 0 && stripe_nr > 0) {
 			stripe_nr--;
-			stripe_offset = BTRFS_STRIPE_LEN;
+			stripe_offset = stripe_len;
 		}
-		alloc = ((stripe_nr * map->num_stripes + i) << BTRFS_STRIPE_LEN_SHIFT) +
+		alloc = ((stripe_nr * map->num_stripes + i) << stripe_shift) +
 			stripe_offset;
 		last_alloc = max(last_alloc, alloc);
 
 		/* Partially written stripe found. It should be last. */
-		if (zone_info[i].alloc_offset & BTRFS_STRIPE_LEN_MASK)
+		if (zone_info[i].alloc_offset & (stripe_len - 1))
 			break;
 	}
 	stripe_nr = 0;
@@ -1619,8 +1621,8 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
 	if (last_alloc) {
 		u32 factor = map->num_stripes;
 
-		stripe_nr = last_alloc >> BTRFS_STRIPE_LEN_SHIFT;
-		stripe_offset = last_alloc & BTRFS_STRIPE_LEN_MASK;
+		stripe_nr = last_alloc >> stripe_shift;
+		stripe_offset = last_alloc & (stripe_len - 1);
 		stripe_nr = div_u64_rem(stripe_nr, factor, &stripe_index);
 	}
 
@@ -1631,11 +1633,10 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
 		if (zone_info[i].alloc_offset == WP_CONVENTIONAL) {
 			has_conventional = true;
 			zone_info[i].alloc_offset =
-				btrfs_stripe_nr_to_offset(stripe_nr,
-							  map->stripe_len);
+				btrfs_stripe_nr_to_offset(stripe_nr, stripe_len);
 
 			if (stripe_index > i)
-				zone_info[i].alloc_offset += BTRFS_STRIPE_LEN;
+				zone_info[i].alloc_offset += stripe_len;
 			else if (stripe_index == i)
 				zone_info[i].alloc_offset += stripe_offset;
 		}
@@ -1650,7 +1651,7 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
 			}
 
 			if (unlikely(has_partial &&
-				     (zone_info[i].alloc_offset & BTRFS_STRIPE_LEN_MASK))) {
+				     (zone_info[i].alloc_offset & (stripe_len - 1)))) {
 				btrfs_err(fs_info,
 				"zoned: multiple partial written stripe found in block group %llu",
 					  bg->start);
@@ -1659,7 +1660,7 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
 		}
 		prev_offset = zone_info[i].alloc_offset;
 
-		if ((zone_info[i].alloc_offset & BTRFS_STRIPE_LEN_MASK) != 0)
+		if ((zone_info[i].alloc_offset & (stripe_len - 1)) != 0)
 			has_partial = true;
 
 		if (test_bit(0, active) != test_bit(i, active)) {
@@ -1675,7 +1676,7 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
 
 	/* Check if all devices stay in the same stripe row. */
 	if (unlikely(zone_info[0].alloc_offset -
-		     zone_info[map->num_stripes - 1].alloc_offset > BTRFS_STRIPE_LEN)) {
+		     zone_info[map->num_stripes - 1].alloc_offset > stripe_len)) {
 		btrfs_err(fs_info, "zoned: stripe gap too large in block group %llu", bg->start);
 		return -EIO;
 	}
@@ -1699,6 +1700,8 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
 	u64 AUTO_KFREE(raid0_allocs);
 	u64 stripe_nr = 0, stripe_offset = 0;
 	u32 stripe_index = 0;
+	const u32 stripe_len = map->stripe_len;
+	const u8 stripe_shift = map->stripe_shift;
 	bool has_partial = false, has_conventional = false;
 	u64 prev_offset = 0;
 
@@ -1746,16 +1749,16 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
 			return -EIO;
 		}
 
-		stripe_nr = alloc >> BTRFS_STRIPE_LEN_SHIFT;
-		stripe_offset = alloc & BTRFS_STRIPE_LEN_MASK;
+		stripe_nr = alloc >> stripe_shift;
+		stripe_offset = alloc & (stripe_len - 1);
 		if (stripe_offset == 0 && stripe_nr > 0) {
 			stripe_nr--;
-			stripe_offset = BTRFS_STRIPE_LEN;
+			stripe_offset = stripe_len;
 		}
 
 		alloc = ((stripe_nr * (map->num_stripes / map->sub_stripes) +
-			  (i / map->sub_stripes)) <<
-			 BTRFS_STRIPE_LEN_SHIFT) + stripe_offset;
+			  (i / map->sub_stripes)) << stripe_shift) +
+			stripe_offset;
 		last_alloc = max(last_alloc, alloc);
 	}
 	stripe_nr = 0;
@@ -1764,8 +1767,8 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
 	if (last_alloc) {
 		u32 factor = map->num_stripes / map->sub_stripes;
 
-		stripe_nr = last_alloc >> BTRFS_STRIPE_LEN_SHIFT;
-		stripe_offset = last_alloc & BTRFS_STRIPE_LEN_MASK;
+		stripe_nr = last_alloc >> stripe_shift;
+		stripe_offset = last_alloc & (stripe_len - 1);
 		stripe_nr = div_u64_rem(stripe_nr, factor, &stripe_index);
 	}
 
@@ -1775,10 +1778,10 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
 		if (raid0_allocs[idx] == WP_CONVENTIONAL) {
 			has_conventional = true;
 			raid0_allocs[idx] = btrfs_stripe_nr_to_offset(stripe_nr,
-								map->stripe_len);
+								      stripe_len);
 
 			if (stripe_index > idx)
-				raid0_allocs[idx] += BTRFS_STRIPE_LEN;
+				raid0_allocs[idx] += stripe_len;
 			else if (stripe_index == idx)
 				raid0_allocs[idx] += stripe_offset;
 		}
@@ -1794,7 +1797,7 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
 				}
 
 				if (unlikely(has_partial &&
-					     (raid0_allocs[idx] & BTRFS_STRIPE_LEN_MASK))) {
+					     (raid0_allocs[idx] & (stripe_len - 1)))) {
 					btrfs_err(fs_info,
 					"zoned: multiple partial written stripe found in block group %llu",
 						  bg->start);
@@ -1803,7 +1806,7 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
 			}
 			prev_offset = raid0_allocs[idx];
 
-			if ((raid0_allocs[idx] & BTRFS_STRIPE_LEN_MASK) != 0)
+			if ((raid0_allocs[idx] & (stripe_len - 1)) != 0)
 				has_partial = true;
 		}
 
@@ -1826,7 +1829,7 @@ static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg,
 
 	/* Check if all devices stay in the same stripe row. */
 	if (unlikely(zone_info[0].alloc_offset -
-		     zone_info[map->num_stripes - 1].alloc_offset > BTRFS_STRIPE_LEN)) {
+		     zone_info[map->num_stripes - 1].alloc_offset > stripe_len)) {
 		btrfs_err(fs_info, "zoned: stripe gap too large in block group %llu",
 			  bg->start);
 		return -EIO;
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 9/9] btrfs: introduce extra limits on btrfs_chunk::stripe_len
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
                   ` (7 preceding siblings ...)
  2026-10-19  6:40 ` [PATCH 8/9] btrfs: convert zoned.c to use map->stripe_len Qu Wenruo
@ 2026-10-19  6:40 ` Qu Wenruo
  2026-10-20 11:23   ` Johannes Thumshirn
  2026-10-19  7:45 ` [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
  9 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  6:40 UTC (permalink / raw)
  To: linux-btrfs

The new limits are:

- Stripe_len must be no smaller than sectorsize
  As sectorsize is still the minimal unit.

- Stripe_len must be no larger than BTRFS_STRIPE_LEN
  We still have a lot of things requiring on BTRFS_STRIPE_LEN alignment,
  e.g. dev extent and chunk allocation.
  A stripe_len larger than BTRFS_STRIPE_LEN will cause problems for the
  existing chunk allocator.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/tree-checker.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 503b6be90dda..61ea8f42c9f2 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -1044,7 +1044,18 @@ int btrfs_check_chunk_valid(const struct btrfs_fs_info *fs_info,
 			  logical, length);
 		return -EUCLEAN;
 	}
-	if (unlikely(!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN)) {
+
+	/*
+	 * For now the "stripe_len != BTRFS_STRIPE_LEN" will cover all cases,
+	 * but the power_of_2 and stripe_len >= sectorsize and
+	 * stripe_len <= BTRFS_STRIPE_LEN are the requirements for future
+	 * stripe_len support.
+	 *
+	 * In the future, "stripe_len != BTRFS_STRIPE_LEN" will be removed.
+	 */
+	if (unlikely(stripe_len != BTRFS_STRIPE_LEN ||
+		     !is_power_of_2(stripe_len) || stripe_len < sectorsize ||
+		     stripe_len > BTRFS_STRIPE_LEN)) {
 		chunk_err(fs_info, leaf, chunk, logical,
 			  "invalid chunk stripe length: %llu",
 			  stripe_len);
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 0/9] btrfs: prepare for variable stripe_len
  2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
                   ` (8 preceding siblings ...)
  2026-10-19  6:40 ` [PATCH 9/9] btrfs: introduce extra limits on btrfs_chunk::stripe_len Qu Wenruo
@ 2026-10-19  7:45 ` Qu Wenruo
  9 siblings, 0 replies; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19  7:45 UTC (permalink / raw)
  To: linux-btrfs



在 2026/10/19 17:09, Qu Wenruo 写道:
> This is a preparation patchset, to support a stripe_len that is not
> 64KiB.
> 
> This is for the future variable stripe length RAID56 feature, where
> RAID56_VSL profile is allowed for data chunks, and the stripe_len can be
> as small as sectorsize, meanwhile data IO are kept to be aligned to
> data_size, which is power of 2, and larger than sector size.
> 
> Finally, RAID56_VSL will always have a number of devices that nr_data ==
> data_size / sector_size.
> 
> So that's why we want a variable stripe_len.
> 
> This series does all the preparation, including supporting stripe_len <
> PAGE_SIZE.
> 
> For now, tree-checker will still reject stripe_len != 64K, but that
> limit will be removed when RAID56_VSL feature is introduced and can be
> properly tested.

Forget to mention that, this series relies on this patch which is 
already sent to the list but not yet merged:

https://lore.kernel.org/linux-btrfs/bd4a247e970e35e3adc140c5417da14bfab2f4f8.1792296994.git.wqu@suse.com/

That's why Sashiko is mentioning two minor problems.

> 
> Qu Wenruo (9):
>    btrfs: reduce the width of num_stripes and sub_stripes
>    btrfs: load the on-disk btrfs_chunk::stripe_len
>    btrfs: add btrfs_io_context::stripe_len and load it
>    btrfs: change scrub to use stripe_len
>    btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset()
>    btrfs: convert volumes.c and block-group.c to use map->stripe_len
>    btrfs: convert raid56.c to use rbio->bioc->stripe_len
>    btrfs: convert zoned.c to use map->stripe_len
>    btrfs: introduce extra limits on btrfs_chunk::stripe_len
> 
>   fs/btrfs/block-group.c  |   9 +--
>   fs/btrfs/raid56.c       |  52 ++++++++++++------
>   fs/btrfs/raid56.h       |   7 +--
>   fs/btrfs/scrub.c        | 118 ++++++++++++++++++++++++++--------------
>   fs/btrfs/tree-checker.c |  13 ++++-
>   fs/btrfs/volumes.c      |  84 ++++++++++++++++++----------
>   fs/btrfs/volumes.h      |  16 ++++--
>   fs/btrfs/zoned.c        |  54 ++++++++++--------
>   8 files changed, 226 insertions(+), 127 deletions(-)
> 


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset()
  2026-10-19  6:40 ` [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset() Qu Wenruo
@ 2026-10-19 21:52   ` kernel test robot
  2026-10-19 22:05     ` Qu Wenruo
  0 siblings, 1 reply; 20+ messages in thread
From: kernel test robot @ 2026-10-19 21:52 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs; +Cc: oe-kbuild-all

Hi Qu,

kernel test robot noticed the following build errors:

[auto build test ERROR on btrfs/for-next]
[also build test ERROR on linus/master v7.3 next-20261016]
[cannot apply to kdave/for-next]
[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/Qu-Wenruo/btrfs-reduce-the-width-of-num_stripes-and-sub_stripes/20261019-170957
base:   https://github.com/btrfs/linux.git for-next
patch link:    https://lore.kernel.org/r/48b407f8488edc890710cdf8ebfefe413e7721c2.1792391732.git.wqu%40suse.com
patch subject: [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset()
config: m68k-defconfig (https://download.01.org/0day-ci/archive/20261020/202610200549.0ma4is7Y-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261020/202610200549.0ma4is7Y-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/202610200549.0ma4is7Y-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/error-injection.h:5,
                    from fs/btrfs/tree-checker.c:20:
   fs/btrfs/tree-checker.c: In function 'btrfs_check_chunk_valid':
>> fs/btrfs/tree-checker.c:1061:32: error: too few arguments to function 'btrfs_stripe_nr_to_offset'; expected 2, have 1
    1061 |         if (unlikely(length >= btrfs_stripe_nr_to_offset(U32_MAX))) {
         |                                ^~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:77:45: note: in definition of macro 'unlikely'
      77 | # define unlikely(x)    __builtin_expect(!!(x), 0)
         |                                             ^
   In file included from fs/btrfs/tree-checker.c:25:
   fs/btrfs/volumes.h:725:19: note: declared here
     725 | static inline u64 btrfs_stripe_nr_to_offset(u32 stripe_nr, u32 stripe_len)
         |                   ^~~~~~~~~~~~~~~~~~~~~~~~~
   fs/btrfs/tree-checker.c:1064:35: error: too few arguments to function 'btrfs_stripe_nr_to_offset'; expected 2, have 1
    1064 |                           length, btrfs_stripe_nr_to_offset(U32_MAX));
         |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~
   fs/btrfs/volumes.h:725:19: note: declared here
     725 | static inline u64 btrfs_stripe_nr_to_offset(u32 stripe_nr, u32 stripe_len)
         |                   ^~~~~~~~~~~~~~~~~~~~~~~~~


vim +/btrfs_stripe_nr_to_offset +1061 fs/btrfs/tree-checker.c

c3d6dda60c9da79 Mark Harmstone 2026-01-07   958  
82fc28fbedbb596 Qu Wenruo      2019-03-20   959  /*
82fc28fbedbb596 Qu Wenruo      2019-03-20   960   * The common chunk check which could also work on super block sys chunk array.
82fc28fbedbb596 Qu Wenruo      2019-03-20   961   *
2a9bb78cfd367fd Qu Wenruo      2024-12-21   962   * If @leaf is NULL, then @chunk must be an on-stack chunk item.
2a9bb78cfd367fd Qu Wenruo      2024-12-21   963   * (For superblock sys_chunk array, and fs_info->sectorsize is unreliable)
2a9bb78cfd367fd Qu Wenruo      2024-12-21   964   *
bf871c3b43b1dcc Qu Wenruo      2019-03-20   965   * Return -EUCLEAN if anything is corrupted.
82fc28fbedbb596 Qu Wenruo      2019-03-20   966   * Return 0 if everything is OK.
82fc28fbedbb596 Qu Wenruo      2019-03-20   967   */
2a9bb78cfd367fd Qu Wenruo      2024-12-21   968  int btrfs_check_chunk_valid(const struct btrfs_fs_info *fs_info,
2a9bb78cfd367fd Qu Wenruo      2024-12-21   969  			    const struct extent_buffer *leaf,
2a9bb78cfd367fd Qu Wenruo      2024-12-21   970  			    const struct btrfs_chunk *chunk, u64 logical,
2a9bb78cfd367fd Qu Wenruo      2024-12-21   971  			    u32 sectorsize)
82fc28fbedbb596 Qu Wenruo      2019-03-20   972  {
82fc28fbedbb596 Qu Wenruo      2019-03-20   973  	u64 length;
347fb0cfc9bab51 Su Yue         2021-01-03   974  	u64 chunk_end;
82fc28fbedbb596 Qu Wenruo      2019-03-20   975  	u64 stripe_len;
82fc28fbedbb596 Qu Wenruo      2019-03-20   976  	u16 num_stripes;
82fc28fbedbb596 Qu Wenruo      2019-03-20   977  	u16 sub_stripes;
82fc28fbedbb596 Qu Wenruo      2019-03-20   978  	u64 type;
82fc28fbedbb596 Qu Wenruo      2019-03-20   979  	u64 features;
2a9bb78cfd367fd Qu Wenruo      2024-12-21   980  	u32 chunk_sector_size;
82fc28fbedbb596 Qu Wenruo      2019-03-20   981  	bool mixed = false;
c3d6dda60c9da79 Mark Harmstone 2026-01-07   982  	bool remapped;
85d07fbe09efd1c Daniel Xu      2020-10-08   983  	int raid_index;
85d07fbe09efd1c Daniel Xu      2020-10-08   984  	int nparity;
85d07fbe09efd1c Daniel Xu      2020-10-08   985  	int ncopies;
82fc28fbedbb596 Qu Wenruo      2019-03-20   986  
2a9bb78cfd367fd Qu Wenruo      2024-12-21   987  	if (leaf) {
82fc28fbedbb596 Qu Wenruo      2019-03-20   988  		length = btrfs_chunk_length(leaf, chunk);
82fc28fbedbb596 Qu Wenruo      2019-03-20   989  		stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
82fc28fbedbb596 Qu Wenruo      2019-03-20   990  		num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
82fc28fbedbb596 Qu Wenruo      2019-03-20   991  		sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
82fc28fbedbb596 Qu Wenruo      2019-03-20   992  		type = btrfs_chunk_type(leaf, chunk);
2a9bb78cfd367fd Qu Wenruo      2024-12-21   993  		chunk_sector_size = btrfs_chunk_sector_size(leaf, chunk);
2a9bb78cfd367fd Qu Wenruo      2024-12-21   994  	} else {
2a9bb78cfd367fd Qu Wenruo      2024-12-21   995  		length = btrfs_stack_chunk_length(chunk);
2a9bb78cfd367fd Qu Wenruo      2024-12-21   996  		stripe_len = btrfs_stack_chunk_stripe_len(chunk);
2a9bb78cfd367fd Qu Wenruo      2024-12-21   997  		num_stripes = btrfs_stack_chunk_num_stripes(chunk);
2a9bb78cfd367fd Qu Wenruo      2024-12-21   998  		sub_stripes = btrfs_stack_chunk_sub_stripes(chunk);
2a9bb78cfd367fd Qu Wenruo      2024-12-21   999  		type = btrfs_stack_chunk_type(chunk);
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1000  		chunk_sector_size = btrfs_stack_chunk_sector_size(chunk);
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1001  	}
85d07fbe09efd1c Daniel Xu      2020-10-08  1002  	raid_index = btrfs_bg_flags_to_raid_index(type);
85d07fbe09efd1c Daniel Xu      2020-10-08  1003  	ncopies = btrfs_raid_array[raid_index].ncopies;
85d07fbe09efd1c Daniel Xu      2020-10-08  1004  	nparity = btrfs_raid_array[raid_index].nparity;
c3d6dda60c9da79 Mark Harmstone 2026-01-07  1005  	remapped = (type & BTRFS_BLOCK_GROUP_REMAPPED);
82fc28fbedbb596 Qu Wenruo      2019-03-20  1006  
c3d6dda60c9da79 Mark Harmstone 2026-01-07  1007  	if (unlikely(!remapped && !num_stripes)) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1008  		chunk_err(fs_info, leaf, chunk, logical,
f114024376bceb1 Qu Wenruo      2019-03-20  1009  			  "invalid chunk num_stripes, have %u", num_stripes);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1010  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1011  	}
c3d6dda60c9da79 Mark Harmstone 2026-01-07  1012  	if (unlikely(num_stripes != 0 && num_stripes < ncopies)) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1013  		chunk_err(fs_info, leaf, chunk, logical,
85d07fbe09efd1c Daniel Xu      2020-10-08  1014  			  "invalid chunk num_stripes < ncopies, have %u < %d",
85d07fbe09efd1c Daniel Xu      2020-10-08  1015  			  num_stripes, ncopies);
85d07fbe09efd1c Daniel Xu      2020-10-08  1016  		return -EUCLEAN;
85d07fbe09efd1c Daniel Xu      2020-10-08  1017  	}
c7c01a4a2524b3f David Sterba   2020-11-04  1018  	if (unlikely(nparity && num_stripes == nparity)) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1019  		chunk_err(fs_info, leaf, chunk, logical,
85d07fbe09efd1c Daniel Xu      2020-10-08  1020  			  "invalid chunk num_stripes == nparity, have %u == %d",
85d07fbe09efd1c Daniel Xu      2020-10-08  1021  			  num_stripes, nparity);
85d07fbe09efd1c Daniel Xu      2020-10-08  1022  		return -EUCLEAN;
85d07fbe09efd1c Daniel Xu      2020-10-08  1023  	}
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1024  	if (unlikely(!IS_ALIGNED(logical, sectorsize))) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1025  		chunk_err(fs_info, leaf, chunk, logical,
f114024376bceb1 Qu Wenruo      2019-03-20  1026  		"invalid chunk logical, have %llu should aligned to %u",
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1027  			  logical, sectorsize);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1028  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1029  	}
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1030  	if (unlikely(chunk_sector_size != sectorsize)) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1031  		chunk_err(fs_info, leaf, chunk, logical,
f114024376bceb1 Qu Wenruo      2019-03-20  1032  			  "invalid chunk sectorsize, have %u expect %u",
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1033  			  chunk_sector_size, sectorsize);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1034  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1035  	}
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1036  	if (unlikely(!length || !IS_ALIGNED(length, sectorsize))) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1037  		chunk_err(fs_info, leaf, chunk, logical,
f114024376bceb1 Qu Wenruo      2019-03-20  1038  			  "invalid chunk length, have %llu", length);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1039  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1040  	}
347fb0cfc9bab51 Su Yue         2021-01-03  1041  	if (unlikely(check_add_overflow(logical, length, &chunk_end))) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1042  		chunk_err(fs_info, leaf, chunk, logical,
347fb0cfc9bab51 Su Yue         2021-01-03  1043  "invalid chunk logical start and length, have logical start %llu length %llu",
347fb0cfc9bab51 Su Yue         2021-01-03  1044  			  logical, length);
347fb0cfc9bab51 Su Yue         2021-01-03  1045  		return -EUCLEAN;
347fb0cfc9bab51 Su Yue         2021-01-03  1046  	}
c7c01a4a2524b3f David Sterba   2020-11-04  1047  	if (unlikely(!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN)) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1048  		chunk_err(fs_info, leaf, chunk, logical,
f114024376bceb1 Qu Wenruo      2019-03-20  1049  			  "invalid chunk stripe length: %llu",
82fc28fbedbb596 Qu Wenruo      2019-03-20  1050  			  stripe_len);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1051  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1052  	}
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1053  	/*
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1054  	 * We artificially limit the chunk size, so that the number of stripes
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1055  	 * inside a chunk can be fit into a U32.  The current limit (256G) is
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1056  	 * way too large for real world usage anyway, and it's also much larger
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1057  	 * than our existing limit (10G).
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1058  	 *
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1059  	 * Thus it should be a good way to catch obvious bitflips.
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1060  	 */
cb091225a538005 Qu Wenruo      2023-06-22 @1061  	if (unlikely(length >= btrfs_stripe_nr_to_offset(U32_MAX))) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1062  		chunk_err(fs_info, leaf, chunk, logical,
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1063  			  "chunk length too large: have %llu limit %llu",
cb091225a538005 Qu Wenruo      2023-06-22  1064  			  length, btrfs_stripe_nr_to_offset(U32_MAX));
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1065  		return -EUCLEAN;
6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1066  	}
ef6a31d035a1000 Mark Harmstone 2026-01-07  1067  	if (unlikely(type & ~BTRFS_BLOCK_GROUP_VALID)) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1068  		chunk_err(fs_info, leaf, chunk, logical,
f114024376bceb1 Qu Wenruo      2019-03-20  1069  			  "unrecognized chunk type: 0x%llx",
ef6a31d035a1000 Mark Harmstone 2026-01-07  1070  			  type & ~BTRFS_BLOCK_GROUP_VALID);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1071  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1072  	}
82fc28fbedbb596 Qu Wenruo      2019-03-20  1073  
c7c01a4a2524b3f David Sterba   2020-11-04  1074  	if (unlikely(!has_single_bit_set(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) &&
c7c01a4a2524b3f David Sterba   2020-11-04  1075  		     (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) != 0)) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1076  		chunk_err(fs_info, leaf, chunk, logical,
80e46cf22ba0bcb Qu Wenruo      2019-03-13  1077  		"invalid chunk profile flag: 0x%llx, expect 0 or 1 bit set",
80e46cf22ba0bcb Qu Wenruo      2019-03-13  1078  			  type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
80e46cf22ba0bcb Qu Wenruo      2019-03-13  1079  		return -EUCLEAN;
80e46cf22ba0bcb Qu Wenruo      2019-03-13  1080  	}
c7c01a4a2524b3f David Sterba   2020-11-04  1081  	if (unlikely((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0)) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1082  		chunk_err(fs_info, leaf, chunk, logical,
f114024376bceb1 Qu Wenruo      2019-03-20  1083  	"missing chunk type flag, have 0x%llx one bit must be set in 0x%llx",
f114024376bceb1 Qu Wenruo      2019-03-20  1084  			  type, BTRFS_BLOCK_GROUP_TYPE_MASK);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1085  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1086  	}
82fc28fbedbb596 Qu Wenruo      2019-03-20  1087  
c7c01a4a2524b3f David Sterba   2020-11-04  1088  	if (unlikely((type & BTRFS_BLOCK_GROUP_SYSTEM) &&
c7c01a4a2524b3f David Sterba   2020-11-04  1089  		     (type & (BTRFS_BLOCK_GROUP_METADATA |
c7c01a4a2524b3f David Sterba   2020-11-04  1090  			      BTRFS_BLOCK_GROUP_DATA)))) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1091  		chunk_err(fs_info, leaf, chunk, logical,
f114024376bceb1 Qu Wenruo      2019-03-20  1092  			  "system chunk with data or metadata type: 0x%llx",
f114024376bceb1 Qu Wenruo      2019-03-20  1093  			  type);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1094  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1095  	}
82fc28fbedbb596 Qu Wenruo      2019-03-20  1096  
82fc28fbedbb596 Qu Wenruo      2019-03-20  1097  	features = btrfs_super_incompat_flags(fs_info->super_copy);
82fc28fbedbb596 Qu Wenruo      2019-03-20  1098  	if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
82fc28fbedbb596 Qu Wenruo      2019-03-20  1099  		mixed = true;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1100  
82fc28fbedbb596 Qu Wenruo      2019-03-20  1101  	if (!mixed) {
c7c01a4a2524b3f David Sterba   2020-11-04  1102  		if (unlikely((type & BTRFS_BLOCK_GROUP_METADATA) &&
c7c01a4a2524b3f David Sterba   2020-11-04  1103  			     (type & BTRFS_BLOCK_GROUP_DATA))) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1104  			chunk_err(fs_info, leaf, chunk, logical,
82fc28fbedbb596 Qu Wenruo      2019-03-20  1105  			"mixed chunk type in non-mixed mode: 0x%llx", type);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1106  			return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1107  		}
82fc28fbedbb596 Qu Wenruo      2019-03-20  1108  	}
82fc28fbedbb596 Qu Wenruo      2019-03-20  1109  
18addf9ec82f857 Mark Harmstone 2026-03-04  1110  	if (unlikely((type & BTRFS_BLOCK_GROUP_METADATA_REMAP) &&
18addf9ec82f857 Mark Harmstone 2026-03-04  1111  		     !(features & BTRFS_FEATURE_INCOMPAT_REMAP_TREE))) {
18addf9ec82f857 Mark Harmstone 2026-03-04  1112  		chunk_err(fs_info, leaf, chunk, logical,
18addf9ec82f857 Mark Harmstone 2026-03-04  1113  		"METADATA_REMAP chunk type without REMAP_TREE incompat bit");
18addf9ec82f857 Mark Harmstone 2026-03-04  1114  		return -EUCLEAN;
18addf9ec82f857 Mark Harmstone 2026-03-04  1115  	}
18addf9ec82f857 Mark Harmstone 2026-03-04  1116  
18addf9ec82f857 Mark Harmstone 2026-03-04  1117  	if (unlikely(remapped &&
18addf9ec82f857 Mark Harmstone 2026-03-04  1118  		     !(features & BTRFS_FEATURE_INCOMPAT_REMAP_TREE))) {
18addf9ec82f857 Mark Harmstone 2026-03-04  1119  		chunk_err(fs_info, leaf, chunk, logical,
18addf9ec82f857 Mark Harmstone 2026-03-04  1120  		"REMAPPED chunk flag without REMAP_TREE incompat bit");
18addf9ec82f857 Mark Harmstone 2026-03-04  1121  		return -EUCLEAN;
18addf9ec82f857 Mark Harmstone 2026-03-04  1122  	}
18addf9ec82f857 Mark Harmstone 2026-03-04  1123  
a6e5521ecc5e712 Filipe Manana  2026-09-16  1124  	if (unlikely(!remapped &&
c3d6dda60c9da79 Mark Harmstone 2026-01-07  1125  		     !valid_stripe_count(type & BTRFS_BLOCK_GROUP_PROFILE_MASK,
a6e5521ecc5e712 Filipe Manana  2026-09-16  1126  					 num_stripes, sub_stripes))) {
2a9bb78cfd367fd Qu Wenruo      2024-12-21  1127  		chunk_err(fs_info, leaf, chunk, logical,
82fc28fbedbb596 Qu Wenruo      2019-03-20  1128  			"invalid num_stripes:sub_stripes %u:%u for profile %llu",
82fc28fbedbb596 Qu Wenruo      2019-03-20  1129  			num_stripes, sub_stripes,
82fc28fbedbb596 Qu Wenruo      2019-03-20  1130  			type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
bf871c3b43b1dcc Qu Wenruo      2019-03-20  1131  		return -EUCLEAN;
82fc28fbedbb596 Qu Wenruo      2019-03-20  1132  	}
82fc28fbedbb596 Qu Wenruo      2019-03-20  1133  
82fc28fbedbb596 Qu Wenruo      2019-03-20  1134  	return 0;
fce466eab7ac6ba Qu Wenruo      2018-07-03  1135  }
fce466eab7ac6ba Qu Wenruo      2018-07-03  1136  

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset()
  2026-10-19 21:52   ` kernel test robot
@ 2026-10-19 22:05     ` Qu Wenruo
  0 siblings, 0 replies; 20+ messages in thread
From: Qu Wenruo @ 2026-10-19 22:05 UTC (permalink / raw)
  To: kernel test robot, linux-btrfs; +Cc: oe-kbuild-all



在 2026/10/20 08:22, kernel test robot 写道:
> Hi Qu,
> 
> kernel test robot noticed the following build errors:
> 
> [auto build test ERROR on btrfs/for-next]

This patchset has one extra dependency, which was just merged hours ago.

Please retry the latest btrfs/for-next branch.

> [also build test ERROR on linus/master v7.3 next-20261016]
> [cannot apply to kdave/for-next]
> [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/Qu-Wenruo/btrfs-reduce-the-width-of-num_stripes-and-sub_stripes/20261019-170957
> base:   https://github.com/btrfs/linux.git for-next
> patch link:    https://lore.kernel.org/r/48b407f8488edc890710cdf8ebfefe413e7721c2.1792391732.git.wqu%40suse.com
> patch subject: [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset()
> config: m68k-defconfig (https://download.01.org/0day-ci/archive/20261020/202610200549.0ma4is7Y-lkp@intel.com/config)
> compiler: m68k-linux-gcc (GCC) 16.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261020/202610200549.0ma4is7Y-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/202610200549.0ma4is7Y-lkp@intel.com/
> 
> All errors (new ones prefixed by >>):
> 
>     In file included from include/linux/error-injection.h:5,
>                      from fs/btrfs/tree-checker.c:20:
>     fs/btrfs/tree-checker.c: In function 'btrfs_check_chunk_valid':
>>> fs/btrfs/tree-checker.c:1061:32: error: too few arguments to function 'btrfs_stripe_nr_to_offset'; expected 2, have 1
>      1061 |         if (unlikely(length >= btrfs_stripe_nr_to_offset(U32_MAX))) {
>           |                                ^~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/compiler.h:77:45: note: in definition of macro 'unlikely'
>        77 | # define unlikely(x)    __builtin_expect(!!(x), 0)
>           |                                             ^
>     In file included from fs/btrfs/tree-checker.c:25:
>     fs/btrfs/volumes.h:725:19: note: declared here
>       725 | static inline u64 btrfs_stripe_nr_to_offset(u32 stripe_nr, u32 stripe_len)
>           |                   ^~~~~~~~~~~~~~~~~~~~~~~~~
>     fs/btrfs/tree-checker.c:1064:35: error: too few arguments to function 'btrfs_stripe_nr_to_offset'; expected 2, have 1
>      1064 |                           length, btrfs_stripe_nr_to_offset(U32_MAX));
>           |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~
>     fs/btrfs/volumes.h:725:19: note: declared here
>       725 | static inline u64 btrfs_stripe_nr_to_offset(u32 stripe_nr, u32 stripe_len)
>           |                   ^~~~~~~~~~~~~~~~~~~~~~~~~
> 
> 
> vim +/btrfs_stripe_nr_to_offset +1061 fs/btrfs/tree-checker.c
> 
> c3d6dda60c9da79 Mark Harmstone 2026-01-07   958
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   959  /*
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   960   * The common chunk check which could also work on super block sys chunk array.
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   961   *
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   962   * If @leaf is NULL, then @chunk must be an on-stack chunk item.
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   963   * (For superblock sys_chunk array, and fs_info->sectorsize is unreliable)
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   964   *
> bf871c3b43b1dcc Qu Wenruo      2019-03-20   965   * Return -EUCLEAN if anything is corrupted.
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   966   * Return 0 if everything is OK.
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   967   */
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   968  int btrfs_check_chunk_valid(const struct btrfs_fs_info *fs_info,
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   969  			    const struct extent_buffer *leaf,
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   970  			    const struct btrfs_chunk *chunk, u64 logical,
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   971  			    u32 sectorsize)
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   972  {
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   973  	u64 length;
> 347fb0cfc9bab51 Su Yue         2021-01-03   974  	u64 chunk_end;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   975  	u64 stripe_len;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   976  	u16 num_stripes;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   977  	u16 sub_stripes;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   978  	u64 type;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   979  	u64 features;
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   980  	u32 chunk_sector_size;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   981  	bool mixed = false;
> c3d6dda60c9da79 Mark Harmstone 2026-01-07   982  	bool remapped;
> 85d07fbe09efd1c Daniel Xu      2020-10-08   983  	int raid_index;
> 85d07fbe09efd1c Daniel Xu      2020-10-08   984  	int nparity;
> 85d07fbe09efd1c Daniel Xu      2020-10-08   985  	int ncopies;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   986
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   987  	if (leaf) {
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   988  		length = btrfs_chunk_length(leaf, chunk);
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   989  		stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   990  		num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   991  		sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
> 82fc28fbedbb596 Qu Wenruo      2019-03-20   992  		type = btrfs_chunk_type(leaf, chunk);
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   993  		chunk_sector_size = btrfs_chunk_sector_size(leaf, chunk);
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   994  	} else {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   995  		length = btrfs_stack_chunk_length(chunk);
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   996  		stripe_len = btrfs_stack_chunk_stripe_len(chunk);
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   997  		num_stripes = btrfs_stack_chunk_num_stripes(chunk);
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   998  		sub_stripes = btrfs_stack_chunk_sub_stripes(chunk);
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21   999  		type = btrfs_stack_chunk_type(chunk);
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1000  		chunk_sector_size = btrfs_stack_chunk_sector_size(chunk);
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1001  	}
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1002  	raid_index = btrfs_bg_flags_to_raid_index(type);
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1003  	ncopies = btrfs_raid_array[raid_index].ncopies;
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1004  	nparity = btrfs_raid_array[raid_index].nparity;
> c3d6dda60c9da79 Mark Harmstone 2026-01-07  1005  	remapped = (type & BTRFS_BLOCK_GROUP_REMAPPED);
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1006
> c3d6dda60c9da79 Mark Harmstone 2026-01-07  1007  	if (unlikely(!remapped && !num_stripes)) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1008  		chunk_err(fs_info, leaf, chunk, logical,
> f114024376bceb1 Qu Wenruo      2019-03-20  1009  			  "invalid chunk num_stripes, have %u", num_stripes);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1010  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1011  	}
> c3d6dda60c9da79 Mark Harmstone 2026-01-07  1012  	if (unlikely(num_stripes != 0 && num_stripes < ncopies)) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1013  		chunk_err(fs_info, leaf, chunk, logical,
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1014  			  "invalid chunk num_stripes < ncopies, have %u < %d",
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1015  			  num_stripes, ncopies);
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1016  		return -EUCLEAN;
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1017  	}
> c7c01a4a2524b3f David Sterba   2020-11-04  1018  	if (unlikely(nparity && num_stripes == nparity)) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1019  		chunk_err(fs_info, leaf, chunk, logical,
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1020  			  "invalid chunk num_stripes == nparity, have %u == %d",
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1021  			  num_stripes, nparity);
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1022  		return -EUCLEAN;
> 85d07fbe09efd1c Daniel Xu      2020-10-08  1023  	}
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1024  	if (unlikely(!IS_ALIGNED(logical, sectorsize))) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1025  		chunk_err(fs_info, leaf, chunk, logical,
> f114024376bceb1 Qu Wenruo      2019-03-20  1026  		"invalid chunk logical, have %llu should aligned to %u",
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1027  			  logical, sectorsize);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1028  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1029  	}
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1030  	if (unlikely(chunk_sector_size != sectorsize)) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1031  		chunk_err(fs_info, leaf, chunk, logical,
> f114024376bceb1 Qu Wenruo      2019-03-20  1032  			  "invalid chunk sectorsize, have %u expect %u",
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1033  			  chunk_sector_size, sectorsize);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1034  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1035  	}
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1036  	if (unlikely(!length || !IS_ALIGNED(length, sectorsize))) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1037  		chunk_err(fs_info, leaf, chunk, logical,
> f114024376bceb1 Qu Wenruo      2019-03-20  1038  			  "invalid chunk length, have %llu", length);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1039  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1040  	}
> 347fb0cfc9bab51 Su Yue         2021-01-03  1041  	if (unlikely(check_add_overflow(logical, length, &chunk_end))) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1042  		chunk_err(fs_info, leaf, chunk, logical,
> 347fb0cfc9bab51 Su Yue         2021-01-03  1043  "invalid chunk logical start and length, have logical start %llu length %llu",
> 347fb0cfc9bab51 Su Yue         2021-01-03  1044  			  logical, length);
> 347fb0cfc9bab51 Su Yue         2021-01-03  1045  		return -EUCLEAN;
> 347fb0cfc9bab51 Su Yue         2021-01-03  1046  	}
> c7c01a4a2524b3f David Sterba   2020-11-04  1047  	if (unlikely(!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN)) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1048  		chunk_err(fs_info, leaf, chunk, logical,
> f114024376bceb1 Qu Wenruo      2019-03-20  1049  			  "invalid chunk stripe length: %llu",
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1050  			  stripe_len);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1051  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1052  	}
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1053  	/*
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1054  	 * We artificially limit the chunk size, so that the number of stripes
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1055  	 * inside a chunk can be fit into a U32.  The current limit (256G) is
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1056  	 * way too large for real world usage anyway, and it's also much larger
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1057  	 * than our existing limit (10G).
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1058  	 *
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1059  	 * Thus it should be a good way to catch obvious bitflips.
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1060  	 */
> cb091225a538005 Qu Wenruo      2023-06-22 @1061  	if (unlikely(length >= btrfs_stripe_nr_to_offset(U32_MAX))) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1062  		chunk_err(fs_info, leaf, chunk, logical,
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1063  			  "chunk length too large: have %llu limit %llu",
> cb091225a538005 Qu Wenruo      2023-06-22  1064  			  length, btrfs_stripe_nr_to_offset(U32_MAX));
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1065  		return -EUCLEAN;
> 6ded22c1bfe6a8a Qu Wenruo      2023-02-17  1066  	}
> ef6a31d035a1000 Mark Harmstone 2026-01-07  1067  	if (unlikely(type & ~BTRFS_BLOCK_GROUP_VALID)) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1068  		chunk_err(fs_info, leaf, chunk, logical,
> f114024376bceb1 Qu Wenruo      2019-03-20  1069  			  "unrecognized chunk type: 0x%llx",
> ef6a31d035a1000 Mark Harmstone 2026-01-07  1070  			  type & ~BTRFS_BLOCK_GROUP_VALID);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1071  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1072  	}
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1073
> c7c01a4a2524b3f David Sterba   2020-11-04  1074  	if (unlikely(!has_single_bit_set(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) &&
> c7c01a4a2524b3f David Sterba   2020-11-04  1075  		     (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) != 0)) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1076  		chunk_err(fs_info, leaf, chunk, logical,
> 80e46cf22ba0bcb Qu Wenruo      2019-03-13  1077  		"invalid chunk profile flag: 0x%llx, expect 0 or 1 bit set",
> 80e46cf22ba0bcb Qu Wenruo      2019-03-13  1078  			  type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
> 80e46cf22ba0bcb Qu Wenruo      2019-03-13  1079  		return -EUCLEAN;
> 80e46cf22ba0bcb Qu Wenruo      2019-03-13  1080  	}
> c7c01a4a2524b3f David Sterba   2020-11-04  1081  	if (unlikely((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0)) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1082  		chunk_err(fs_info, leaf, chunk, logical,
> f114024376bceb1 Qu Wenruo      2019-03-20  1083  	"missing chunk type flag, have 0x%llx one bit must be set in 0x%llx",
> f114024376bceb1 Qu Wenruo      2019-03-20  1084  			  type, BTRFS_BLOCK_GROUP_TYPE_MASK);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1085  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1086  	}
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1087
> c7c01a4a2524b3f David Sterba   2020-11-04  1088  	if (unlikely((type & BTRFS_BLOCK_GROUP_SYSTEM) &&
> c7c01a4a2524b3f David Sterba   2020-11-04  1089  		     (type & (BTRFS_BLOCK_GROUP_METADATA |
> c7c01a4a2524b3f David Sterba   2020-11-04  1090  			      BTRFS_BLOCK_GROUP_DATA)))) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1091  		chunk_err(fs_info, leaf, chunk, logical,
> f114024376bceb1 Qu Wenruo      2019-03-20  1092  			  "system chunk with data or metadata type: 0x%llx",
> f114024376bceb1 Qu Wenruo      2019-03-20  1093  			  type);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1094  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1095  	}
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1096
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1097  	features = btrfs_super_incompat_flags(fs_info->super_copy);
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1098  	if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1099  		mixed = true;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1100
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1101  	if (!mixed) {
> c7c01a4a2524b3f David Sterba   2020-11-04  1102  		if (unlikely((type & BTRFS_BLOCK_GROUP_METADATA) &&
> c7c01a4a2524b3f David Sterba   2020-11-04  1103  			     (type & BTRFS_BLOCK_GROUP_DATA))) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1104  			chunk_err(fs_info, leaf, chunk, logical,
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1105  			"mixed chunk type in non-mixed mode: 0x%llx", type);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1106  			return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1107  		}
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1108  	}
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1109
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1110  	if (unlikely((type & BTRFS_BLOCK_GROUP_METADATA_REMAP) &&
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1111  		     !(features & BTRFS_FEATURE_INCOMPAT_REMAP_TREE))) {
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1112  		chunk_err(fs_info, leaf, chunk, logical,
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1113  		"METADATA_REMAP chunk type without REMAP_TREE incompat bit");
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1114  		return -EUCLEAN;
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1115  	}
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1116
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1117  	if (unlikely(remapped &&
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1118  		     !(features & BTRFS_FEATURE_INCOMPAT_REMAP_TREE))) {
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1119  		chunk_err(fs_info, leaf, chunk, logical,
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1120  		"REMAPPED chunk flag without REMAP_TREE incompat bit");
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1121  		return -EUCLEAN;
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1122  	}
> 18addf9ec82f857 Mark Harmstone 2026-03-04  1123
> a6e5521ecc5e712 Filipe Manana  2026-09-16  1124  	if (unlikely(!remapped &&
> c3d6dda60c9da79 Mark Harmstone 2026-01-07  1125  		     !valid_stripe_count(type & BTRFS_BLOCK_GROUP_PROFILE_MASK,
> a6e5521ecc5e712 Filipe Manana  2026-09-16  1126  					 num_stripes, sub_stripes))) {
> 2a9bb78cfd367fd Qu Wenruo      2024-12-21  1127  		chunk_err(fs_info, leaf, chunk, logical,
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1128  			"invalid num_stripes:sub_stripes %u:%u for profile %llu",
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1129  			num_stripes, sub_stripes,
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1130  			type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
> bf871c3b43b1dcc Qu Wenruo      2019-03-20  1131  		return -EUCLEAN;
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1132  	}
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1133
> 82fc28fbedbb596 Qu Wenruo      2019-03-20  1134  	return 0;
> fce466eab7ac6ba Qu Wenruo      2018-07-03  1135  }
> fce466eab7ac6ba Qu Wenruo      2018-07-03  1136
> 
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/9] btrfs: reduce the width of num_stripes and sub_stripes
  2026-10-19  6:39 ` [PATCH 1/9] btrfs: reduce the width of num_stripes and sub_stripes Qu Wenruo
@ 2026-10-20  9:59   ` Johannes Thumshirn
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Thumshirn @ 2026-10-20  9:59 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/9] btrfs: load the on-disk btrfs_chunk::stripe_len
  2026-10-19  6:39 ` [PATCH 2/9] btrfs: load the on-disk btrfs_chunk::stripe_len Qu Wenruo
@ 2026-10-20 10:01   ` Johannes Thumshirn
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Thumshirn @ 2026-10-20 10:01 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/9] btrfs: add btrfs_io_context::stripe_len and load it
  2026-10-19  6:39 ` [PATCH 3/9] btrfs: add btrfs_io_context::stripe_len and load it Qu Wenruo
@ 2026-10-20 10:05   ` Johannes Thumshirn
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Thumshirn @ 2026-10-20 10:05 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs

Oh that one's handy for RST as well,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/9] btrfs: change scrub to use stripe_len
  2026-10-19  6:40 ` [PATCH 4/9] btrfs: change scrub to use stripe_len Qu Wenruo
@ 2026-10-20 11:01   ` Johannes Thumshirn
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Thumshirn @ 2026-10-20 11:01 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs

On 19.10.26 08:40, Qu Wenruo wrote:
>   
>   static struct btrfs_bio *alloc_scrub_bbio(struct btrfs_fs_info *fs_info,
>   					  blk_opf_t opf,
> -					  u64 logical,
> +					  u64 logical, u32 stripe_len,
>   					  btrfs_bio_end_io_t end_io, void *private)
>   {
All callers of alloc_scrub_bbio() pass a scrub_stripe as 'private'. Why 
not change 'void *private' to 'struct scrub_stripe *stripe' and access 
'stripe_len' from there?


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 6/9] btrfs: convert volumes.c and block-group.c to use map->stripe_len
  2026-10-19  6:40 ` [PATCH 6/9] btrfs: convert volumes.c and block-group.c to use map->stripe_len Qu Wenruo
@ 2026-10-20 11:03   ` Johannes Thumshirn
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Thumshirn @ 2026-10-20 11:03 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs

On 19.10.26 08:40, Qu Wenruo wrote:
>   static bool is_same_chunk_map(const struct btrfs_chunk_map *map, u64 logical,
> -			      u64 length, u64 type, u16 num_stripes)
> +			      u64 length, u64 type, u32 stripe_len,
> +			      u16 num_stripes)
>   {
>   	if (map->start != logical || map->chunk_len != length ||
> -	    map->on_disk_type != type || map->num_stripes != num_stripes)
> +	    map->on_disk_type != type || map->stripe_len != stripe_len ||
> +	    map->num_stripes != num_stripes)
>   		return false;
>   	return true;
>   }

While you're at it, can you untangle that if? It's barely readable.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 8/9] btrfs: convert zoned.c to use map->stripe_len
  2026-10-19  6:40 ` [PATCH 8/9] btrfs: convert zoned.c to use map->stripe_len Qu Wenruo
@ 2026-10-20 11:07   ` Johannes Thumshirn
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Thumshirn @ 2026-10-20 11:07 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs

On 19.10.26 08:40, Qu Wenruo wrote:
> -		if (zone_info[i].alloc_offset & BTRFS_STRIPE_LEN_MASK)
> +		if (zone_info[i].alloc_offset & (stripe_len - 1))
>   			break;

I think this would be a good opportunity for using IS_ALIGNED() here.

>   	}
>   	stripe_nr = 0;
> @@ -1619,8 +1621,8 @@ static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg,
>   	if (last_alloc) {
>   		u32 factor = map->num_stripes;
>   
> -		stripe_nr = last_alloc >> BTRFS_STRIPE_LEN_SHIFT;
> -		stripe_offset = last_alloc & BTRFS_STRIPE_LEN_MASK;
> +		stripe_nr = last_alloc >> stripe_shift;
> +		stripe_offset = last_alloc & (stripe_len - 1);
>
And ALIGN()?

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 9/9] btrfs: introduce extra limits on btrfs_chunk::stripe_len
  2026-10-19  6:40 ` [PATCH 9/9] btrfs: introduce extra limits on btrfs_chunk::stripe_len Qu Wenruo
@ 2026-10-20 11:23   ` Johannes Thumshirn
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Thumshirn @ 2026-10-20 11:23 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2026-10-20 11:23 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19  6:39 [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo
2026-10-19  6:39 ` [PATCH 1/9] btrfs: reduce the width of num_stripes and sub_stripes Qu Wenruo
2026-10-20  9:59   ` Johannes Thumshirn
2026-10-19  6:39 ` [PATCH 2/9] btrfs: load the on-disk btrfs_chunk::stripe_len Qu Wenruo
2026-10-20 10:01   ` Johannes Thumshirn
2026-10-19  6:39 ` [PATCH 3/9] btrfs: add btrfs_io_context::stripe_len and load it Qu Wenruo
2026-10-20 10:05   ` Johannes Thumshirn
2026-10-19  6:40 ` [PATCH 4/9] btrfs: change scrub to use stripe_len Qu Wenruo
2026-10-20 11:01   ` Johannes Thumshirn
2026-10-19  6:40 ` [PATCH 5/9] btrfs: add a new 'stripe_len' parameter to btrfs_stripe_nr_to_offset() Qu Wenruo
2026-10-19 21:52   ` kernel test robot
2026-10-19 22:05     ` Qu Wenruo
2026-10-19  6:40 ` [PATCH 6/9] btrfs: convert volumes.c and block-group.c to use map->stripe_len Qu Wenruo
2026-10-20 11:03   ` Johannes Thumshirn
2026-10-19  6:40 ` [PATCH 7/9] btrfs: convert raid56.c to use rbio->bioc->stripe_len Qu Wenruo
2026-10-19  6:40 ` [PATCH 8/9] btrfs: convert zoned.c to use map->stripe_len Qu Wenruo
2026-10-20 11:07   ` Johannes Thumshirn
2026-10-19  6:40 ` [PATCH 9/9] btrfs: introduce extra limits on btrfs_chunk::stripe_len Qu Wenruo
2026-10-20 11:23   ` Johannes Thumshirn
2026-10-19  7:45 ` [PATCH 0/9] btrfs: prepare for variable stripe_len Qu Wenruo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox