* [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path
@ 2026-04-13 6:52 robbieko
2026-04-13 6:52 ` [PATCH 1/6] btrfs: copy devid in btrfs_partially_delete_raid_extent() robbieko
` (8 more replies)
0 siblings, 9 replies; 18+ messages in thread
From: robbieko @ 2026-04-13 6:52 UTC (permalink / raw)
To: linux-btrfs; +Cc: robbieko
This series fixes six bugs in fs/btrfs/raid-stripe-tree.c, all within the
stripe extent deletion and partial deletion code paths.
Patch 1 fixes btrfs_partially_delete_raid_extent() failing to copy the
devid when rebuilding a truncated stripe extent, resulting in zeroed-out
devids and corrupted stripe mappings.
Patch 2 fixes btrfs_delete_raid_extent() using offset=0 for the search
key, which can miss entries when the target is the first item on a leaf.
Changed to offset=(u64)-1 with proper boundary handling.
Patch 3 fixes btrfs_previous_item() being called with min_objectid=start,
which prevents finding the preceding stripe extent whose objectid is less
than start.
Patch 4 replaces an ASSERT(found_start <= start) with proper error
handling that returns -ENOENT, avoiding kernel panics on unexpected
B-tree states.
Patch 5 handles -EAGAIN from btrfs_duplicate_item() in the punch-a-hole
case and refreshes the stale leaf pointer after a potential leaf split.
Patch 6 adds return value checking for all three call sites of
btrfs_partially_delete_raid_extent() to avoid silently losing errors.
robbieko (6):
btrfs: copy devid in btrfs_partially_delete_raid_extent()
btrfs: fix raid stripe search missing entries at leaf boundaries
btrfs: fix wrong min_objectid in btrfs_previous_item() call
btrfs: replace ASSERT with proper error handling in stripe lookup
fallback
btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf
pointer
btrfs: check return value of btrfs_partially_delete_raid_extent()
fs/btrfs/raid-stripe-tree.c | 57 +++++++++++++++++++++++++++++--------
1 file changed, 45 insertions(+), 12 deletions(-)
--
2.43.0
Disclaimer: The contents of this e-mail message and any attachments are confidential and are intended solely for addressee. The information may also be legally privileged. This transmission is sent in trust, for the sole purpose of delivery to the intended recipient. If you have received this transmission in error, any use, reproduction or dissemination of this transmission is strictly prohibited. If you are not the intended recipient, please immediately notify the sender by reply e-mail or phone and delete this message and its attachments, if any.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/6] btrfs: copy devid in btrfs_partially_delete_raid_extent()
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
@ 2026-04-13 6:52 ` robbieko
2026-04-13 9:14 ` Johannes Thumshirn
2026-04-13 6:52 ` [PATCH 2/6] btrfs: fix raid stripe search missing entries at leaf boundaries robbieko
` (7 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: robbieko @ 2026-04-13 6:52 UTC (permalink / raw)
To: linux-btrfs; +Cc: robbieko
When btrfs_partially_delete_raid_extent() rebuilds a truncated/shifted
stripe extent into newitem, the loop copies the physical address for
each stride but forgets to copy the devid. The resulting item written
back to the stripe tree has zeroed-out devids, corrupting the stripe
mapping.
Fix this by reading the devid with btrfs_raid_stride_devid() and
writing it into the new item with btrfs_set_stack_raid_stride_devid()
before copying the physical address.
Signed-off-by: robbieko <robbieko@synology.com>
---
fs/btrfs/raid-stripe-tree.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
index 2987cb7c686e..5c519e161331 100644
--- a/fs/btrfs/raid-stripe-tree.c
+++ b/fs/btrfs/raid-stripe-tree.c
@@ -45,8 +45,11 @@ static int btrfs_partially_delete_raid_extent(struct btrfs_trans_handle *trans,
for (int i = 0; i < btrfs_num_raid_stripes(item_size); i++) {
struct btrfs_raid_stride *stride = &extent->strides[i];
+ u64 devid;
u64 phys;
+ devid = btrfs_raid_stride_devid(leaf, stride);
+ btrfs_set_stack_raid_stride_devid(&newitem->strides[i], devid);
phys = btrfs_raid_stride_physical(leaf, stride) + frontpad;
btrfs_set_stack_raid_stride_physical(&newitem->strides[i], phys);
}
--
2.43.0
Disclaimer: The contents of this e-mail message and any attachments are confidential and are intended solely for addressee. The information may also be legally privileged. This transmission is sent in trust, for the sole purpose of delivery to the intended recipient. If you have received this transmission in error, any use, reproduction or dissemination of this transmission is strictly prohibited. If you are not the intended recipient, please immediately notify the sender by reply e-mail or phone and delete this message and its attachments, if any.
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 2/6] btrfs: fix raid stripe search missing entries at leaf boundaries
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
2026-04-13 6:52 ` [PATCH 1/6] btrfs: copy devid in btrfs_partially_delete_raid_extent() robbieko
@ 2026-04-13 6:52 ` robbieko
2026-04-13 10:02 ` Johannes Thumshirn
2026-04-13 19:09 ` David Sterba
2026-04-13 6:52 ` [PATCH 3/6] btrfs: fix wrong min_objectid in btrfs_previous_item() call robbieko
` (6 subsequent siblings)
8 siblings, 2 replies; 18+ messages in thread
From: robbieko @ 2026-04-13 6:52 UTC (permalink / raw)
To: linux-btrfs; +Cc: robbieko
In btrfs_delete_raid_extent(), the search key uses offset=0. When the
target stripe entry is the first item on a leaf, btrfs_search_slot()
may land on the previous leaf and decrementing the slot from nritems
still points to the wrong entry, causing the stripe extent to be
silently missed.
Fix this by searching with offset=(u64)-1 instead. Since no real stripe
entry has this offset, btrfs_search_slot() always returns 1 with the
slot pointing past the last matching objectid entry. Then unconditionally
decrement the slot with a proper slots[0]==0 early-exit check to handle
the case where no matching entry exists.
Signed-off-by: robbieko <robbieko@synology.com>
---
fs/btrfs/raid-stripe-tree.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
index 5c519e161331..d35efe74aa1b 100644
--- a/fs/btrfs/raid-stripe-tree.c
+++ b/fs/btrfs/raid-stripe-tree.c
@@ -98,14 +98,26 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
while (1) {
key.objectid = start;
key.type = BTRFS_RAID_STRIPE_KEY;
- key.offset = 0;
+ key.offset = (u64)-1;
ret = btrfs_search_slot(trans, stripe_root, &key, path, -1, 1);
if (ret < 0)
break;
- if (path->slots[0] == btrfs_header_nritems(path->nodes[0]))
- path->slots[0]--;
+ /*
+ * Search with offset=(u64)-1 ensures we land on the correct
+ * leaf even when the target entry is the first item on a leaf.
+ * Since no real entry has offset=(u64)-1, ret is always 1 and
+ * slot points past the last entry with objectid==start (or
+ * past the end of the leaf if that entry is the last item).
+ * Back up one slot to find the actual entry.
+ */
+ if (path->slots[0] == 0) {
+ /* No entry with objectid <= start exists. */
+ ret = 0;
+ break;
+ }
+ path->slots[0]--;
leaf = path->nodes[0];
slot = path->slots[0];
--
2.43.0
Disclaimer: The contents of this e-mail message and any attachments are confidential and are intended solely for addressee. The information may also be legally privileged. This transmission is sent in trust, for the sole purpose of delivery to the intended recipient. If you have received this transmission in error, any use, reproduction or dissemination of this transmission is strictly prohibited. If you are not the intended recipient, please immediately notify the sender by reply e-mail or phone and delete this message and its attachments, if any.
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 3/6] btrfs: fix wrong min_objectid in btrfs_previous_item() call
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
2026-04-13 6:52 ` [PATCH 1/6] btrfs: copy devid in btrfs_partially_delete_raid_extent() robbieko
2026-04-13 6:52 ` [PATCH 2/6] btrfs: fix raid stripe search missing entries at leaf boundaries robbieko
@ 2026-04-13 6:52 ` robbieko
2026-04-13 9:43 ` Johannes Thumshirn
2026-04-13 6:52 ` [PATCH 4/6] btrfs: replace ASSERT with proper error handling in stripe lookup fallback robbieko
` (5 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: robbieko @ 2026-04-13 6:52 UTC (permalink / raw)
To: linux-btrfs; +Cc: robbieko
When found_start > start and slot == 0, btrfs_previous_item() is called
with min_objectid=start to find the previous stripe extent. However, the
previous stripe extent we are looking for has objectid < start (it starts
before our deletion range), so passing start as min_objectid prevents
finding it.
Fix by passing 0 as min_objectid to allow finding any preceding stripe
extent regardless of its objectid.
Signed-off-by: robbieko <robbieko@synology.com>
---
fs/btrfs/raid-stripe-tree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
index d35efe74aa1b..2f41cec637d4 100644
--- a/fs/btrfs/raid-stripe-tree.c
+++ b/fs/btrfs/raid-stripe-tree.c
@@ -138,7 +138,7 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
*/
if (found_start > start) {
if (slot == 0) {
- ret = btrfs_previous_item(stripe_root, path, start,
+ ret = btrfs_previous_item(stripe_root, path, 0,
BTRFS_RAID_STRIPE_KEY);
if (ret) {
if (ret > 0)
--
2.43.0
Disclaimer: The contents of this e-mail message and any attachments are confidential and are intended solely for addressee. The information may also be legally privileged. This transmission is sent in trust, for the sole purpose of delivery to the intended recipient. If you have received this transmission in error, any use, reproduction or dissemination of this transmission is strictly prohibited. If you are not the intended recipient, please immediately notify the sender by reply e-mail or phone and delete this message and its attachments, if any.
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 4/6] btrfs: replace ASSERT with proper error handling in stripe lookup fallback
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
` (2 preceding siblings ...)
2026-04-13 6:52 ` [PATCH 3/6] btrfs: fix wrong min_objectid in btrfs_previous_item() call robbieko
@ 2026-04-13 6:52 ` robbieko
2026-04-13 9:49 ` Johannes Thumshirn
2026-04-13 6:52 ` [PATCH 5/6] btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf pointer robbieko
` (4 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: robbieko @ 2026-04-13 6:52 UTC (permalink / raw)
To: linux-btrfs; +Cc: robbieko
After falling back to the previous item in btrfs_delete_raid_extent(),
the code uses ASSERT(found_start <= start) to verify the found extent
actually precedes our target range. If the B-tree state is unexpected
(e.g. no overlapping extent exists), this triggers a kernel BUG/panic
in debug builds, or silently continues with wrong data otherwise.
Replace the ASSERT with a proper bounds check that returns -ENOENT if
the found extent does not actually overlap with the start position.
Signed-off-by: robbieko <robbieko@synology.com>
---
fs/btrfs/raid-stripe-tree.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
index 2f41cec637d4..5909ad35a1b0 100644
--- a/fs/btrfs/raid-stripe-tree.c
+++ b/fs/btrfs/raid-stripe-tree.c
@@ -154,7 +154,10 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
btrfs_item_key_to_cpu(leaf, &key, slot);
found_start = key.objectid;
found_end = found_start + key.offset;
- ASSERT(found_start <= start);
+ if (found_start > start || found_end <= start) {
+ ret = -ENOENT;
+ break;
+ }
}
if (key.type != BTRFS_RAID_STRIPE_KEY)
--
2.43.0
Disclaimer: The contents of this e-mail message and any attachments are confidential and are intended solely for addressee. The information may also be legally privileged. This transmission is sent in trust, for the sole purpose of delivery to the intended recipient. If you have received this transmission in error, any use, reproduction or dissemination of this transmission is strictly prohibited. If you are not the intended recipient, please immediately notify the sender by reply e-mail or phone and delete this message and its attachments, if any.
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 5/6] btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf pointer
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
` (3 preceding siblings ...)
2026-04-13 6:52 ` [PATCH 4/6] btrfs: replace ASSERT with proper error handling in stripe lookup fallback robbieko
@ 2026-04-13 6:52 ` robbieko
2026-04-13 9:54 ` Johannes Thumshirn
2026-04-13 6:52 ` [PATCH 6/6] btrfs: check return value of btrfs_partially_delete_raid_extent() robbieko
` (3 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: robbieko @ 2026-04-13 6:52 UTC (permalink / raw)
To: linux-btrfs; +Cc: robbieko
In the 'punch a hole' case of btrfs_delete_raid_extent(),
btrfs_duplicate_item() can return -EAGAIN when the leaf needs to be
split and the path becomes invalid. The old code treats any error as
fatal and breaks out of the loop.
Additionally, btrfs_duplicate_item() may trigger setup_leaf_for_split()
which can reallocate the leaf node. The code continues using the old
leaf pointer, leading to use-after-free or stale data access.
Fix both issues by:
- Handling -EAGAIN specifically: release the path and retry the loop.
- Refreshing leaf = path->nodes[0] after successful duplication.
Signed-off-by: robbieko <robbieko@synology.com>
---
fs/btrfs/raid-stripe-tree.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
index 5909ad35a1b0..1e8392a6c5a4 100644
--- a/fs/btrfs/raid-stripe-tree.c
+++ b/fs/btrfs/raid-stripe-tree.c
@@ -194,9 +194,19 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
/* The "right" item. */
ret = btrfs_duplicate_item(trans, stripe_root, path, &newkey);
+ if (ret == -EAGAIN) {
+ btrfs_release_path(path);
+ continue;
+ }
if (ret)
break;
+ /*
+ * btrfs_duplicate_item() may have triggered a leaf
+ * split via setup_leaf_for_split(), so we must refresh
+ * our leaf pointer from the path.
+ */
+ leaf = path->nodes[0];
item_size = btrfs_item_size(leaf, path->slots[0]);
extent = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_stripe_extent);
--
2.43.0
Disclaimer: The contents of this e-mail message and any attachments are confidential and are intended solely for addressee. The information may also be legally privileged. This transmission is sent in trust, for the sole purpose of delivery to the intended recipient. If you have received this transmission in error, any use, reproduction or dissemination of this transmission is strictly prohibited. If you are not the intended recipient, please immediately notify the sender by reply e-mail or phone and delete this message and its attachments, if any.
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 6/6] btrfs: check return value of btrfs_partially_delete_raid_extent()
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
` (4 preceding siblings ...)
2026-04-13 6:52 ` [PATCH 5/6] btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf pointer robbieko
@ 2026-04-13 6:52 ` robbieko
2026-04-13 10:00 ` Johannes Thumshirn
2026-04-13 9:11 ` [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path Johannes Thumshirn
` (2 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: robbieko @ 2026-04-13 6:52 UTC (permalink / raw)
To: linux-btrfs; +Cc: robbieko
btrfs_partially_delete_raid_extent() returns an error code (e.g.
-ENOMEM from kzalloc, or errors from btrfs_del_item/btrfs_insert_item),
but all three call sites in btrfs_delete_raid_extent() discard the
return value, silently losing errors and potentially leaving the stripe
tree in an inconsistent state.
Fix by capturing the return value into ret at all three call sites and
breaking out of the loop on error where appropriate.
Signed-off-by: robbieko <robbieko@synology.com>
---
fs/btrfs/raid-stripe-tree.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
index 1e8392a6c5a4..22327f483311 100644
--- a/fs/btrfs/raid-stripe-tree.c
+++ b/fs/btrfs/raid-stripe-tree.c
@@ -223,8 +223,9 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
/* The "left" item. */
path->slots[0]--;
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
- btrfs_partially_delete_raid_extent(trans, path, &key,
- diff_start, 0);
+ ret = btrfs_partially_delete_raid_extent(trans, path,
+ &key,
+ diff_start, 0);
break;
}
@@ -240,8 +241,11 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
if (found_start < start) {
u64 diff_start = start - found_start;
- btrfs_partially_delete_raid_extent(trans, path, &key,
- diff_start, 0);
+ ret = btrfs_partially_delete_raid_extent(trans, path,
+ &key,
+ diff_start, 0);
+ if (ret)
+ break;
start += (key.offset - diff_start);
length -= (key.offset - diff_start);
@@ -264,9 +268,10 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
if (found_end > end) {
u64 diff_end = found_end - end;
- btrfs_partially_delete_raid_extent(trans, path, &key,
- key.offset - length,
- length);
+ ret = btrfs_partially_delete_raid_extent(trans, path,
+ &key,
+ key.offset - length,
+ length);
ASSERT(key.offset - diff_end == length);
break;
}
--
2.43.0
Disclaimer: The contents of this e-mail message and any attachments are confidential and are intended solely for addressee. The information may also be legally privileged. This transmission is sent in trust, for the sole purpose of delivery to the intended recipient. If you have received this transmission in error, any use, reproduction or dissemination of this transmission is strictly prohibited. If you are not the intended recipient, please immediately notify the sender by reply e-mail or phone and delete this message and its attachments, if any.
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
` (5 preceding siblings ...)
2026-04-13 6:52 ` [PATCH 6/6] btrfs: check return value of btrfs_partially_delete_raid_extent() robbieko
@ 2026-04-13 9:11 ` Johannes Thumshirn
2026-04-13 19:16 ` David Sterba
2026-04-17 2:18 ` David Sterba
8 siblings, 0 replies; 18+ messages in thread
From: Johannes Thumshirn @ 2026-04-13 9:11 UTC (permalink / raw)
To: robbieko, linux-btrfs
On 4/13/26 8:52 AM, robbieko wrote:
> This series fixes six bugs in fs/btrfs/raid-stripe-tree.c, all within the
> stripe extent deletion and partial deletion code paths.
>
> Patch 1 fixes btrfs_partially_delete_raid_extent() failing to copy the
> devid when rebuilding a truncated stripe extent, resulting in zeroed-out
> devids and corrupted stripe mappings.
>
> Patch 2 fixes btrfs_delete_raid_extent() using offset=0 for the search
> key, which can miss entries when the target is the first item on a leaf.
> Changed to offset=(u64)-1 with proper boundary handling.
>
> Patch 3 fixes btrfs_previous_item() being called with min_objectid=start,
> which prevents finding the preceding stripe extent whose objectid is less
> than start.
>
> Patch 4 replaces an ASSERT(found_start <= start) with proper error
> handling that returns -ENOENT, avoiding kernel panics on unexpected
> B-tree states.
>
> Patch 5 handles -EAGAIN from btrfs_duplicate_item() in the punch-a-hole
> case and refreshes the stale leaf pointer after a potential leaf split.
>
> Patch 6 adds return value checking for all three call sites of
> btrfs_partially_delete_raid_extent() to avoid silently losing errors.
Hi Robbie,
Thanks for the patches, I'll run through them separately, but there's
tests cases for RST, can you also add tests checking for the above
conditions?
Thanks,
Johannes
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/6] btrfs: copy devid in btrfs_partially_delete_raid_extent()
2026-04-13 6:52 ` [PATCH 1/6] btrfs: copy devid in btrfs_partially_delete_raid_extent() robbieko
@ 2026-04-13 9:14 ` Johannes Thumshirn
0 siblings, 0 replies; 18+ messages in thread
From: Johannes Thumshirn @ 2026-04-13 9:14 UTC (permalink / raw)
To: robbieko, linux-btrfs
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/6] btrfs: fix wrong min_objectid in btrfs_previous_item() call
2026-04-13 6:52 ` [PATCH 3/6] btrfs: fix wrong min_objectid in btrfs_previous_item() call robbieko
@ 2026-04-13 9:43 ` Johannes Thumshirn
0 siblings, 0 replies; 18+ messages in thread
From: Johannes Thumshirn @ 2026-04-13 9:43 UTC (permalink / raw)
To: robbieko, linux-btrfs
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/6] btrfs: replace ASSERT with proper error handling in stripe lookup fallback
2026-04-13 6:52 ` [PATCH 4/6] btrfs: replace ASSERT with proper error handling in stripe lookup fallback robbieko
@ 2026-04-13 9:49 ` Johannes Thumshirn
2026-04-13 19:06 ` David Sterba
0 siblings, 1 reply; 18+ messages in thread
From: Johannes Thumshirn @ 2026-04-13 9:49 UTC (permalink / raw)
To: robbieko, linux-btrfs
Not sure if ENOENT is the correct error here, wouldn't EUCLEAN fit better?
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/6] btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf pointer
2026-04-13 6:52 ` [PATCH 5/6] btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf pointer robbieko
@ 2026-04-13 9:54 ` Johannes Thumshirn
0 siblings, 0 replies; 18+ messages in thread
From: Johannes Thumshirn @ 2026-04-13 9:54 UTC (permalink / raw)
To: robbieko, linux-btrfs
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6/6] btrfs: check return value of btrfs_partially_delete_raid_extent()
2026-04-13 6:52 ` [PATCH 6/6] btrfs: check return value of btrfs_partially_delete_raid_extent() robbieko
@ 2026-04-13 10:00 ` Johannes Thumshirn
0 siblings, 0 replies; 18+ messages in thread
From: Johannes Thumshirn @ 2026-04-13 10:00 UTC (permalink / raw)
To: robbieko, linux-btrfs
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/6] btrfs: fix raid stripe search missing entries at leaf boundaries
2026-04-13 6:52 ` [PATCH 2/6] btrfs: fix raid stripe search missing entries at leaf boundaries robbieko
@ 2026-04-13 10:02 ` Johannes Thumshirn
2026-04-13 19:09 ` David Sterba
1 sibling, 0 replies; 18+ messages in thread
From: Johannes Thumshirn @ 2026-04-13 10:02 UTC (permalink / raw)
To: robbieko, linux-btrfs
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/6] btrfs: replace ASSERT with proper error handling in stripe lookup fallback
2026-04-13 9:49 ` Johannes Thumshirn
@ 2026-04-13 19:06 ` David Sterba
0 siblings, 0 replies; 18+ messages in thread
From: David Sterba @ 2026-04-13 19:06 UTC (permalink / raw)
To: Johannes Thumshirn; +Cc: robbieko, linux-btrfs
On Mon, Apr 13, 2026 at 11:49:39AM +0200, Johannes Thumshirn wrote:
> Not sure if ENOENT is the correct error here, wouldn't EUCLEAN fit better?
Depends on the semantics, if the caller cares about the code then it
should be specific. In this case I think it can be both and slightly
favoring ENOENT. btrfs_delete_raid_extent() returns EINVAL, ENOMEM and
others and the ENOENT for deleting something is understandable. The
caller also ends up aborting the transaction so the error will be
reported.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/6] btrfs: fix raid stripe search missing entries at leaf boundaries
2026-04-13 6:52 ` [PATCH 2/6] btrfs: fix raid stripe search missing entries at leaf boundaries robbieko
2026-04-13 10:02 ` Johannes Thumshirn
@ 2026-04-13 19:09 ` David Sterba
1 sibling, 0 replies; 18+ messages in thread
From: David Sterba @ 2026-04-13 19:09 UTC (permalink / raw)
To: robbieko; +Cc: linux-btrfs
On Mon, Apr 13, 2026 at 02:52:33PM +0800, robbieko wrote:
> In btrfs_delete_raid_extent(), the search key uses offset=0. When the
> target stripe entry is the first item on a leaf, btrfs_search_slot()
> may land on the previous leaf and decrementing the slot from nritems
> still points to the wrong entry, causing the stripe extent to be
> silently missed.
>
> Fix this by searching with offset=(u64)-1 instead. Since no real stripe
> entry has this offset, btrfs_search_slot() always returns 1 with the
> slot pointing past the last matching objectid entry. Then unconditionally
> decrement the slot with a proper slots[0]==0 early-exit check to handle
> the case where no matching entry exists.
>
> Signed-off-by: robbieko <robbieko@synology.com>
> ---
> fs/btrfs/raid-stripe-tree.c | 18 +++++++++++++++---
> 1 file changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
> index 5c519e161331..d35efe74aa1b 100644
> --- a/fs/btrfs/raid-stripe-tree.c
> +++ b/fs/btrfs/raid-stripe-tree.c
> @@ -98,14 +98,26 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
> while (1) {
> key.objectid = start;
> key.type = BTRFS_RAID_STRIPE_KEY;
> - key.offset = 0;
> + key.offset = (u64)-1;
>
> ret = btrfs_search_slot(trans, stripe_root, &key, path, -1, 1);
> if (ret < 0)
> break;
>
> - if (path->slots[0] == btrfs_header_nritems(path->nodes[0]))
> - path->slots[0]--;
> + /*
> + * Search with offset=(u64)-1 ensures we land on the correct
> + * leaf even when the target entry is the first item on a leaf.
> + * Since no real entry has offset=(u64)-1, ret is always 1 and
This would be good to handle, not just assumed. A corruption or fuzzed
image inserting the unexpected key with offset will continue while it
should not. Handled as an EUCLEAN, like it's in many other places after
searching for tree items. I'm not sure if it's 100% covered everywhere
but this case fits the pattern.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
` (6 preceding siblings ...)
2026-04-13 9:11 ` [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path Johannes Thumshirn
@ 2026-04-13 19:16 ` David Sterba
2026-04-17 2:18 ` David Sterba
8 siblings, 0 replies; 18+ messages in thread
From: David Sterba @ 2026-04-13 19:16 UTC (permalink / raw)
To: robbieko; +Cc: linux-btrfs
On Mon, Apr 13, 2026 at 02:52:31PM +0800, robbieko wrote:
> This series fixes six bugs in fs/btrfs/raid-stripe-tree.c, all within the
> stripe extent deletion and partial deletion code paths.
>
> Patch 1 fixes btrfs_partially_delete_raid_extent() failing to copy the
> devid when rebuilding a truncated stripe extent, resulting in zeroed-out
> devids and corrupted stripe mappings.
>
> Patch 2 fixes btrfs_delete_raid_extent() using offset=0 for the search
> key, which can miss entries when the target is the first item on a leaf.
> Changed to offset=(u64)-1 with proper boundary handling.
>
> Patch 3 fixes btrfs_previous_item() being called with min_objectid=start,
> which prevents finding the preceding stripe extent whose objectid is less
> than start.
>
> Patch 4 replaces an ASSERT(found_start <= start) with proper error
> handling that returns -ENOENT, avoiding kernel panics on unexpected
> B-tree states.
>
> Patch 5 handles -EAGAIN from btrfs_duplicate_item() in the punch-a-hole
> case and refreshes the stale leaf pointer after a potential leaf split.
>
> Patch 6 adds return value checking for all three call sites of
> btrfs_partially_delete_raid_extent() to avoid silently losing errors.
Thanks for the fixes. The cover letter does not need to mention each
patch and what it does if it's clear from the patch subjects or the
changelogs. The first paragraph would be enough, eventually you can
mention anything relevant for the series but not worth tracking in the
commit logs.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
` (7 preceding siblings ...)
2026-04-13 19:16 ` David Sterba
@ 2026-04-17 2:18 ` David Sterba
8 siblings, 0 replies; 18+ messages in thread
From: David Sterba @ 2026-04-17 2:18 UTC (permalink / raw)
To: robbieko; +Cc: linux-btrfs
On Mon, Apr 13, 2026 at 02:52:31PM +0800, robbieko wrote:
> This series fixes six bugs in fs/btrfs/raid-stripe-tree.c, all within the
> stripe extent deletion and partial deletion code paths.
>
> Patch 1 fixes btrfs_partially_delete_raid_extent() failing to copy the
> devid when rebuilding a truncated stripe extent, resulting in zeroed-out
> devids and corrupted stripe mappings.
>
> Patch 2 fixes btrfs_delete_raid_extent() using offset=0 for the search
> key, which can miss entries when the target is the first item on a leaf.
> Changed to offset=(u64)-1 with proper boundary handling.
>
> Patch 3 fixes btrfs_previous_item() being called with min_objectid=start,
> which prevents finding the preceding stripe extent whose objectid is less
> than start.
>
> Patch 4 replaces an ASSERT(found_start <= start) with proper error
> handling that returns -ENOENT, avoiding kernel panics on unexpected
> B-tree states.
>
> Patch 5 handles -EAGAIN from btrfs_duplicate_item() in the punch-a-hole
> case and refreshes the stale leaf pointer after a potential leaf split.
>
> Patch 6 adds return value checking for all three call sites of
> btrfs_partially_delete_raid_extent() to avoid silently losing errors.
>
> robbieko (6):
> btrfs: copy devid in btrfs_partially_delete_raid_extent()
> btrfs: fix raid stripe search missing entries at leaf boundaries
> btrfs: fix wrong min_objectid in btrfs_previous_item() call
> btrfs: replace ASSERT with proper error handling in stripe lookup
> fallback
> btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf
> pointer
> btrfs: check return value of btrfs_partially_delete_raid_extent()
Added to for-next, thanks.
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-04-17 2:18 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-13 6:52 [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path robbieko
2026-04-13 6:52 ` [PATCH 1/6] btrfs: copy devid in btrfs_partially_delete_raid_extent() robbieko
2026-04-13 9:14 ` Johannes Thumshirn
2026-04-13 6:52 ` [PATCH 2/6] btrfs: fix raid stripe search missing entries at leaf boundaries robbieko
2026-04-13 10:02 ` Johannes Thumshirn
2026-04-13 19:09 ` David Sterba
2026-04-13 6:52 ` [PATCH 3/6] btrfs: fix wrong min_objectid in btrfs_previous_item() call robbieko
2026-04-13 9:43 ` Johannes Thumshirn
2026-04-13 6:52 ` [PATCH 4/6] btrfs: replace ASSERT with proper error handling in stripe lookup fallback robbieko
2026-04-13 9:49 ` Johannes Thumshirn
2026-04-13 19:06 ` David Sterba
2026-04-13 6:52 ` [PATCH 5/6] btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf pointer robbieko
2026-04-13 9:54 ` Johannes Thumshirn
2026-04-13 6:52 ` [PATCH 6/6] btrfs: check return value of btrfs_partially_delete_raid_extent() robbieko
2026-04-13 10:00 ` Johannes Thumshirn
2026-04-13 9:11 ` [PATCH 0/6] btrfs: fix multiple bugs in raid-stripe-tree deletion path Johannes Thumshirn
2026-04-13 19:16 ` David Sterba
2026-04-17 2:18 ` David Sterba
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox