* [PATCH 0/3] btrfs: minor changes related to btrfs_chunk_map
@ 2026-10-16 0:48 Qu Wenruo
2026-10-16 0:48 ` [PATCH 1/3] btrfs: rename btrfs_chunk_map::stripe_size Qu Wenruo
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Qu Wenruo @ 2026-10-16 0:48 UTC (permalink / raw)
To: linux-btrfs
The first two are renames of "stripe_size" to avoid confusion with
"stripe_len". Both names are similar but have completely different
meanings.
The last one is to enhance the chunk map reading to reject overlapping
or different chunk maps from the existing ones.
Qu Wenruo (3):
btrfs: rename btrfs_chunk_map::stripe_size
btrfs: rename stripe_size inside volumes.c
btrfs: reject existing chunks that don't match
fs/btrfs/block-group.c | 4 +-
fs/btrfs/scrub.c | 2 +-
fs/btrfs/tests/extent-map-tests.c | 2 +-
fs/btrfs/volumes.c | 138 +++++++++++++++++-------------
fs/btrfs/volumes.h | 4 +-
5 files changed, 83 insertions(+), 67 deletions(-)
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] btrfs: rename btrfs_chunk_map::stripe_size
2026-10-16 0:48 [PATCH 0/3] btrfs: minor changes related to btrfs_chunk_map Qu Wenruo
@ 2026-10-16 0:48 ` Qu Wenruo
2026-10-16 0:48 ` [PATCH 2/3] btrfs: rename stripe_size inside volumes.c Qu Wenruo
2026-10-16 0:48 ` [PATCH 3/3] btrfs: reject existing chunks that don't match Qu Wenruo
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2026-10-16 0:48 UTC (permalink / raw)
To: linux-btrfs
The member btrfs_chunk_map::stripe_size sounds very similar to
btrfs_chunk::stripe_len, but they have very different meanings.
btrfs_chunk_map::stripe_size is in fact the device extent size for the
chunk. E.g. a 2GiB RAID0 chunk with 2 stripes,
btrfs_chunk_map::stripe_size will be 1GiB (2GiB / 2).
But btrfs_chunk::stripe_len is the stripe length that striping profiles
should follow, and the value is now fixed to 64KiB.
E.g. for a 2GiB RAID0 chunk with 2 stripes, every write will be split
into 64KiB stripes, and then distributed across the 2 devices.
To avoid confusion, rename btrfs_chunk_map::stripe_size to
dev_extent_size.
And since we're here, also rename the helper btrfs_calc_stripe_length()
to btrfs_calc_dev_extent_size().
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/block-group.c | 4 ++--
fs/btrfs/scrub.c | 2 +-
fs/btrfs/tests/extent-map-tests.c | 2 +-
fs/btrfs/volumes.c | 20 ++++++++++----------
fs/btrfs/volumes.h | 4 ++--
5 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 8ff21dde9a46..1896a4ae91a6 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -2326,7 +2326,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
if (IS_ERR(map))
return -EIO;
- data_stripe_length = map->stripe_size;
+ data_stripe_length = map->dev_extent_size;
io_stripe_size = BTRFS_STRIPE_LEN;
chunk_start = map->start;
@@ -2945,7 +2945,7 @@ static int insert_dev_extents(struct btrfs_trans_handle *trans,
dev_offset = map->stripes[i].physical;
ret = insert_dev_extent(trans, device, chunk_offset, dev_offset,
- map->stripe_size);
+ map->dev_extent_size);
if (ret)
break;
}
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 479c0e037015..cb17aef81166 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2410,7 +2410,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
int ret;
int ret2;
u64 physical = map->stripes[stripe_index].physical;
- const u64 dev_stripe_len = btrfs_calc_stripe_length(map);
+ const u64 dev_stripe_len = btrfs_calc_dev_extent_size(map);
const u64 physical_end = physical + dev_stripe_len;
u64 logical;
u64 logic_end;
diff --git a/fs/btrfs/tests/extent-map-tests.c b/fs/btrfs/tests/extent-map-tests.c
index 811f36d41101..80f39c87268b 100644
--- a/fs/btrfs/tests/extent-map-tests.c
+++ b/fs/btrfs/tests/extent-map-tests.c
@@ -1029,7 +1029,7 @@ static int test_rmap_block(struct btrfs_fs_info *fs_info,
/* Start at 4GiB logical address */
map->start = SZ_4G;
map->chunk_len = test->data_stripe_size * test->num_data_stripes;
- map->stripe_size = test->data_stripe_size;
+ map->dev_extent_size = test->data_stripe_size;
map->num_stripes = test->num_stripes;
map->type = test->raid_type;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index f1305f68b1f8..2db449f7c495 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6090,7 +6090,7 @@ static void chunk_map_device_set_bits(struct btrfs_chunk_map *map, unsigned int
struct btrfs_device *device = stripe->dev;
btrfs_set_extent_bit(&device->alloc_state, stripe->physical,
- stripe->physical + map->stripe_size - 1,
+ stripe->physical + map->dev_extent_size - 1,
bits | EXTENT_NOWAIT, NULL);
}
}
@@ -6102,7 +6102,7 @@ void btrfs_chunk_map_device_clear_bits(struct btrfs_chunk_map *map, unsigned int
struct btrfs_device *device = stripe->dev;
btrfs_clear_extent_bit(&device->alloc_state, stripe->physical,
- stripe->physical + map->stripe_size - 1,
+ stripe->physical + map->dev_extent_size - 1,
bits | EXTENT_NOWAIT, NULL);
}
}
@@ -6199,7 +6199,7 @@ static struct btrfs_block_group *create_chunk(struct btrfs_trans_handle *trans,
map->start = start;
map->chunk_len = ctl->chunk_size;
- map->stripe_size = ctl->stripe_size;
+ map->dev_extent_size = ctl->stripe_size;
map->on_disk_type = type;
map->sub_stripes = ctl->sub_stripes;
map->num_stripes = ctl->num_stripes;
@@ -7650,7 +7650,7 @@ static void btrfs_report_missing_device(struct btrfs_fs_info *fs_info,
devid, uuid);
}
-u64 btrfs_calc_stripe_length(const struct btrfs_chunk_map *map)
+u64 btrfs_calc_dev_extent_size(const struct btrfs_chunk_map *map)
{
const int data_stripes = calc_data_stripes(map->type, map->num_stripes);
@@ -7778,9 +7778,9 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
set_real_chunk_type(map);
if (num_stripes > 0)
- map->stripe_size = btrfs_calc_stripe_length(map);
+ map->dev_extent_size = btrfs_calc_dev_extent_size(map);
else
- map->stripe_size = 0;
+ map->dev_extent_size = 0;
for (i = 0; i < num_stripes; i++) {
map->stripes[i].physical =
@@ -8673,7 +8673,7 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
struct btrfs_dev_lookup_args args = { .devid = devid };
struct btrfs_chunk_map *map;
struct btrfs_device *dev;
- u64 stripe_len;
+ u64 dev_extent_size;
bool found = false;
int ret = 0;
int i;
@@ -8687,12 +8687,12 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
goto out;
}
- stripe_len = btrfs_calc_stripe_length(map);
- if (unlikely(physical_len != stripe_len)) {
+ dev_extent_size = btrfs_calc_dev_extent_size(map);
+ if (unlikely(physical_len != dev_extent_size)) {
btrfs_err(fs_info,
"dev extent physical offset %llu on devid %llu length doesn't match chunk %llu, have %llu expect %llu",
physical_offset, devid, map->start, physical_len,
- stripe_len);
+ dev_extent_size);
ret = -EUCLEAN;
goto out;
}
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 6eddda239221..67464025e449 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -628,7 +628,7 @@ struct btrfs_chunk_map {
refcount_t refs;
u64 start;
u64 chunk_len;
- u64 stripe_size;
+ u64 dev_extent_size;
/*
* The real type that is utilized during logical address mapping.
*
@@ -799,7 +799,7 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev,
void btrfs_free_device(struct btrfs_device *device);
unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
u64 logical);
-u64 btrfs_calc_stripe_length(const struct btrfs_chunk_map *map);
+u64 btrfs_calc_dev_extent_size(const struct btrfs_chunk_map *map);
int btrfs_nr_parity_stripes(u64 type);
int btrfs_chunk_alloc_add_chunk_item(struct btrfs_trans_handle *trans,
struct btrfs_block_group *bg);
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] btrfs: rename stripe_size inside volumes.c
2026-10-16 0:48 [PATCH 0/3] btrfs: minor changes related to btrfs_chunk_map Qu Wenruo
2026-10-16 0:48 ` [PATCH 1/3] btrfs: rename btrfs_chunk_map::stripe_size Qu Wenruo
@ 2026-10-16 0:48 ` Qu Wenruo
2026-10-16 0:48 ` [PATCH 3/3] btrfs: reject existing chunks that don't match Qu Wenruo
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2026-10-16 0:48 UTC (permalink / raw)
To: linux-btrfs
Rename the "stripe_size" used inside volumes.c by:
- local variable in alloc_virtual_chunk()
- alloc_chunk_ctl::stripe_size
All rename to "dev_extent_size".
- alloc_chunk_ctl::max_stripe_size
Rename to "dev_extent_max" as there is already a "dev_extent_min".
- decide_stripe_size*() functions
Rename to decide_dev_extent_size*().
This further reduces the confusion between "stripe_size" and
"stripe_len".
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/volumes.c | 92 +++++++++++++++++++++++-----------------------
1 file changed, 46 insertions(+), 46 deletions(-)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 2db449f7c495..e3886c9035de 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5616,7 +5616,7 @@ static int alloc_virtual_chunk(struct btrfs_fs_info *fs_info,
const struct btrfs_raid_attr *raid_attr = &btrfs_raid_array[type];
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
struct btrfs_device *device;
- u64 stripe_size;
+ u64 dev_extent_size;
int ndevs = 0;
lockdep_assert_held(&fs_info->chunk_mutex);
@@ -5673,14 +5673,14 @@ static int alloc_virtual_chunk(struct btrfs_fs_info *fs_info,
ndevs = min(ndevs, (int)BTRFS_MAX_DEVS(fs_info));
/*
- * Stripe size will be determined by the device with the least
+ * Dev extent size will be determined by the device with the least
* unallocated space.
*/
- stripe_size = devices_info[ndevs - 1].total_avail;
+ dev_extent_size = devices_info[ndevs - 1].total_avail;
for (int i = 0; i < ndevs; i++)
- devices_info[i].dev->per_profile_allocated += stripe_size;
- *allocated = div_u64(stripe_size * (ndevs - raid_attr->nparity),
+ devices_info[i].dev->per_profile_allocated += dev_extent_size;
+ *allocated = div_u64(dev_extent_size * (ndevs - raid_attr->nparity),
raid_attr->ncopies);
return 0;
}
@@ -5795,10 +5795,10 @@ struct alloc_chunk_ctl {
int ncopies;
/* Number of stripes worth of bytes to store parity information */
int nparity;
- u64 max_stripe_size;
u64 max_chunk_size;
+ u64 dev_extent_max;
u64 dev_extent_min;
- u64 stripe_size;
+ u64 dev_extent_size;
u64 chunk_size;
int ndevs;
/* Space_info the block group is going to belong. */
@@ -5815,7 +5815,7 @@ static void init_alloc_chunk_ctl_policy_regular(
ASSERT(space_info);
ctl->max_chunk_size = READ_ONCE(space_info->chunk_size);
- ctl->max_stripe_size = min_t(u64, ctl->max_chunk_size, SZ_1G);
+ ctl->dev_extent_max = min_t(u64, ctl->max_chunk_size, SZ_1G);
if (ctl->type & BTRFS_BLOCK_GROUP_SYSTEM)
ctl->devs_max = min_t(int, ctl->devs_max, BTRFS_MAX_DEVS_SYS_CHUNK);
@@ -5837,14 +5837,14 @@ static void init_alloc_chunk_ctl_policy_zoned(
u64 min_chunk_size = min_data_stripes * zone_size;
u64 type = ctl->type;
- ctl->max_stripe_size = zone_size;
+ ctl->dev_extent_max = zone_size;
if (type & BTRFS_BLOCK_GROUP_DATA) {
ctl->max_chunk_size = round_down(BTRFS_MAX_DATA_CHUNK_SIZE,
zone_size);
} else if (type & BTRFS_BLOCK_GROUP_METADATA) {
- ctl->max_chunk_size = ctl->max_stripe_size;
+ ctl->max_chunk_size = ctl->dev_extent_max;
} else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
- ctl->max_chunk_size = 2 * ctl->max_stripe_size;
+ ctl->max_chunk_size = 2 * ctl->dev_extent_max;
ctl->devs_max = min_t(int, ctl->devs_max,
BTRFS_MAX_DEVS_SYS_CHUNK);
} else {
@@ -5895,7 +5895,7 @@ static int gather_device_info(struct btrfs_fs_devices *fs_devices,
struct btrfs_fs_info *info = fs_devices->fs_info;
struct btrfs_device *device;
u64 total_avail;
- u64 dev_extent_want = ctl->max_stripe_size * ctl->dev_stripes;
+ u64 dev_extent_want = ctl->dev_extent_max * ctl->dev_stripes;
int ret;
int ndevs = 0;
u64 max_avail;
@@ -5965,8 +5965,8 @@ static int gather_device_info(struct btrfs_fs_devices *fs_devices,
return 0;
}
-static int decide_stripe_size_regular(struct alloc_chunk_ctl *ctl,
- struct btrfs_device_info *devices_info)
+static int decide_dev_extent_size_regular(struct alloc_chunk_ctl *ctl,
+ struct btrfs_device_info *devices_info)
{
/* Number of stripes that count for block group size */
int data_stripes;
@@ -5978,8 +5978,8 @@ static int decide_stripe_size_regular(struct alloc_chunk_ctl *ctl,
* The DUP profile stores more than one stripe per device, the
* max_avail is the total size so we have to adjust.
*/
- ctl->stripe_size = div_u64(devices_info[ctl->ndevs - 1].max_avail,
- ctl->dev_stripes);
+ ctl->dev_extent_size = div_u64(devices_info[ctl->ndevs - 1].max_avail,
+ ctl->dev_stripes);
ctl->num_stripes = ctl->ndevs * ctl->dev_stripes;
/* This will have to be fixed for RAID1 and RAID10 over more drives */
@@ -5989,31 +5989,31 @@ static int decide_stripe_size_regular(struct alloc_chunk_ctl *ctl,
* Use the number of data stripes to figure out how big this chunk is
* really going to be in terms of logical address space, and compare
* that answer with the max chunk size. If it's higher, we try to
- * reduce stripe_size.
+ * reduce dev_extent_size.
*/
- if (ctl->stripe_size * data_stripes > ctl->max_chunk_size) {
+ if (ctl->dev_extent_size * data_stripes > ctl->max_chunk_size) {
/*
- * Reduce stripe_size, round it up to a 16MB boundary again and
+ * Reduce dev_extent_size, round it up to a 16MB boundary again and
* then use it, unless it ends up being even bigger than the
* previous value we had already.
*/
- ctl->stripe_size = min(round_up(div_u64(ctl->max_chunk_size,
- data_stripes), SZ_16M),
- ctl->stripe_size);
+ ctl->dev_extent_size = min(round_up(div_u64(ctl->max_chunk_size,
+ data_stripes), SZ_16M),
+ ctl->dev_extent_size);
}
- /* Stripe size should not go beyond 1G. */
- ctl->stripe_size = min_t(u64, ctl->stripe_size, SZ_1G);
+ /* Dev extent size should not go beyond 1G. */
+ ctl->dev_extent_size = min_t(u64, ctl->dev_extent_size, SZ_1G);
/* Align to BTRFS_STRIPE_LEN */
- ctl->stripe_size = round_down(ctl->stripe_size, BTRFS_STRIPE_LEN);
- ctl->chunk_size = ctl->stripe_size * data_stripes;
+ ctl->dev_extent_size = round_down(ctl->dev_extent_size, BTRFS_STRIPE_LEN);
+ ctl->chunk_size = ctl->dev_extent_size * data_stripes;
return 0;
}
-static int decide_stripe_size_zoned(struct alloc_chunk_ctl *ctl,
- struct btrfs_device_info *devices_info)
+static int decide_dev_extent_size_zoned(struct alloc_chunk_ctl *ctl,
+ struct btrfs_device_info *devices_info)
{
u64 zone_size = devices_info[0].dev->zone_info->zone_size;
/* Number of stripes that count for block group size */
@@ -6027,30 +6027,30 @@ static int decide_stripe_size_zoned(struct alloc_chunk_ctl *ctl,
"ndevs=%d max_avail=%llu dev_extent_min=%llu", ctl->ndevs,
devices_info[ctl->ndevs - 1].max_avail, ctl->dev_extent_min);
- ctl->stripe_size = zone_size;
+ ctl->dev_extent_size = zone_size;
ctl->num_stripes = ctl->ndevs * ctl->dev_stripes;
data_stripes = (ctl->num_stripes - ctl->nparity) / ctl->ncopies;
- /* stripe_size is fixed in zoned filesystem. Reduce ndevs instead. */
- if (ctl->stripe_size * data_stripes > ctl->max_chunk_size) {
+ /* dev_extent_size is fixed in zoned filesystem. Reduce ndevs instead. */
+ if (ctl->dev_extent_size * data_stripes > ctl->max_chunk_size) {
ctl->ndevs = div_u64(div_u64(ctl->max_chunk_size * ctl->ncopies,
- ctl->stripe_size) + ctl->nparity,
+ ctl->dev_extent_size) + ctl->nparity,
ctl->dev_stripes);
ctl->num_stripes = ctl->ndevs * ctl->dev_stripes;
data_stripes = (ctl->num_stripes - ctl->nparity) / ctl->ncopies;
- ASSERT(ctl->stripe_size * data_stripes <= ctl->max_chunk_size,
- "stripe_size=%llu data_stripes=%d max_chunk_size=%llu",
- ctl->stripe_size, data_stripes, ctl->max_chunk_size);
+ ASSERT(ctl->dev_extent_size * data_stripes <= ctl->max_chunk_size,
+ "dev_extent_size=%llu data_stripes=%d max_chunk_size=%llu",
+ ctl->dev_extent_size, data_stripes, ctl->max_chunk_size);
}
- ctl->chunk_size = ctl->stripe_size * data_stripes;
+ ctl->chunk_size = ctl->dev_extent_size * data_stripes;
return 0;
}
-static int decide_stripe_size(struct btrfs_fs_devices *fs_devices,
- struct alloc_chunk_ctl *ctl,
- struct btrfs_device_info *devices_info)
+static int decide_dev_extent_size(struct btrfs_fs_devices *fs_devices,
+ struct alloc_chunk_ctl *ctl,
+ struct btrfs_device_info *devices_info)
{
struct btrfs_fs_info *info = fs_devices->fs_info;
@@ -6077,9 +6077,9 @@ static int decide_stripe_size(struct btrfs_fs_devices *fs_devices,
btrfs_warn_unknown_chunk_allocation(fs_devices->chunk_alloc_policy);
fallthrough;
case BTRFS_CHUNK_ALLOC_REGULAR:
- return decide_stripe_size_regular(ctl, devices_info);
+ return decide_dev_extent_size_regular(ctl, devices_info);
case BTRFS_CHUNK_ALLOC_ZONED:
- return decide_stripe_size_zoned(ctl, devices_info);
+ return decide_dev_extent_size_zoned(ctl, devices_info);
}
}
@@ -6199,7 +6199,7 @@ static struct btrfs_block_group *create_chunk(struct btrfs_trans_handle *trans,
map->start = start;
map->chunk_len = ctl->chunk_size;
- map->dev_extent_size = ctl->stripe_size;
+ map->dev_extent_size = ctl->dev_extent_size;
map->on_disk_type = type;
map->sub_stripes = ctl->sub_stripes;
map->num_stripes = ctl->num_stripes;
@@ -6210,7 +6210,7 @@ static struct btrfs_block_group *create_chunk(struct btrfs_trans_handle *trans,
int s = i * ctl->dev_stripes + j;
map->stripes[s].dev = devices_info[i].dev;
map->stripes[s].physical = devices_info[i].dev_offset +
- j * ctl->stripe_size;
+ j * ctl->dev_extent_size;
}
}
@@ -6233,13 +6233,13 @@ static struct btrfs_block_group *create_chunk(struct btrfs_trans_handle *trans,
struct btrfs_device *dev = map->stripes[i].dev;
btrfs_device_set_bytes_used(dev,
- dev->bytes_used + ctl->stripe_size);
+ dev->bytes_used + ctl->dev_extent_size);
if (list_empty(&dev->post_commit_list))
list_add_tail(&dev->post_commit_list,
&trans->transaction->dev_update_list);
}
- atomic64_sub(ctl->stripe_size * map->num_stripes,
+ atomic64_sub(ctl->dev_extent_size * map->num_stripes,
&info->free_chunk_space);
check_raid56_incompat_flag(info, type);
@@ -6292,7 +6292,7 @@ struct btrfs_block_group *btrfs_create_chunk(struct btrfs_trans_handle *trans,
if (ret < 0)
return ERR_PTR(ret);
- ret = decide_stripe_size(fs_devices, &ctl, devices_info);
+ ret = decide_dev_extent_size(fs_devices, &ctl, devices_info);
if (ret < 0)
return ERR_PTR(ret);
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] btrfs: reject existing chunks that don't match
2026-10-16 0:48 [PATCH 0/3] btrfs: minor changes related to btrfs_chunk_map Qu Wenruo
2026-10-16 0:48 ` [PATCH 1/3] btrfs: rename btrfs_chunk_map::stripe_size Qu Wenruo
2026-10-16 0:48 ` [PATCH 2/3] btrfs: rename stripe_size inside volumes.c Qu Wenruo
@ 2026-10-16 0:48 ` Qu Wenruo
2 siblings, 0 replies; 4+ messages in thread
From: Qu Wenruo @ 2026-10-16 0:48 UTC (permalink / raw)
To: linux-btrfs
During read_one_chunk() we can hit an existing chunk map.
There are several situations that this can happen:
- System chunk maps
This is the most common case, where the system chunks are added from
super block during bootstrap.
But in that case, the system chunks in the super block should match
the one in the chunk tree, if not there is definitely something wrong.
- Overlapping chunk maps
This is rare, but potentially malicious.
Crafted images or even some bitflips in the chunk tree can lead to
this.
In that case we should reject such cases.
To detect and reject those cases:
- Introduce a new helper, is_same_chunk_map()
This checks most important members, so we can detect such problem
without fully checking the stripes.
If the helper returns false, then we output an error message and
reject the mount.
- Use the full chunk map range for btrfs_find_chunk_map()
The current search range is [@logical, @logical], which is only one
bytenr in length.
If we have the following case, btrfs_find_chunk_map() returns NULL but
we still have an overlapping chunk map:
Logical
|<--- New chunk map --->|
|<--- Existing chunk map --->|
Using the full range to do the search would return the existing chunk
map and get the new one rejected.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/volumes.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e3886c9035de..6574939e1295 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -7718,6 +7718,15 @@ static struct btrfs_device *handle_missing_device(struct btrfs_fs_info *fs_info,
return dev;
}
+static bool is_same_chunk_map(const struct btrfs_chunk_map *map, u64 logical,
+ u64 length, u64 type, u16 num_stripes)
+{
+ if (map->start != logical || map->chunk_len != length ||
+ map->on_disk_type != type || map->num_stripes != num_stripes)
+ return false;
+ return true;
+}
+
static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
struct btrfs_chunk *chunk)
{
@@ -7747,14 +7756,21 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
warn_32bit_meta_chunk(fs_info, logical, length, type);
#endif
- map = btrfs_find_chunk_map(fs_info, logical, 1);
+ map = btrfs_find_chunk_map(fs_info, logical, length);
- /* already mapped? */
- if (map && map->start <= logical && map->start + map->chunk_len > logical) {
- btrfs_free_chunk_map(map);
- return 0;
- } else if (map) {
+ /* Already mapped? Check if the existing one matches. */
+ if (map) {
+ if (unlikely(!is_same_chunk_map(map, logical, length,
+ type, num_stripes))) {
+ btrfs_err(fs_info,
+ "existing chunk %llu doesn't match the new one at %llu",
+ map->start, logical);
+ ret = -EUCLEAN;
+ } else {
+ ret = 0;
+ }
btrfs_free_chunk_map(map);
+ return ret;
}
map = btrfs_alloc_chunk_map(num_stripes, GFP_NOFS);
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-16 0:48 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 0:48 [PATCH 0/3] btrfs: minor changes related to btrfs_chunk_map Qu Wenruo
2026-10-16 0:48 ` [PATCH 1/3] btrfs: rename btrfs_chunk_map::stripe_size Qu Wenruo
2026-10-16 0:48 ` [PATCH 2/3] btrfs: rename stripe_size inside volumes.c Qu Wenruo
2026-10-16 0:48 ` [PATCH 3/3] btrfs: reject existing chunks that don't match 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.