* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.