Re: [PATCH] btrfs: replace BUG_ON() with error return in get_new_location()
From: Qu Wenruo
Date: Sat Apr 25 2026 - 04:07:27 EST
在 2026/4/25 15:40, Teng Liu 写道:
In get_new_location(), BUG_ON() crashes the kernel if the looked up
file extent item has any of offset, compression, encryption, or other
encoding set. While entries created by the relocation code itself are
not expected to have these fields set, the values come from on-disk
data and a malformed file system can reach this code with non-zero
values, panicking the kernel during a balance operation.
Replace the BUG_ON() with a return of -EUCLEAN, the established error
code in fs/btrfs/relocation.c for filesystem corruption. The caller in
replace_file_extents() already handles errors from get_new_location()
by breaking out of the loop without aborting the transaction so no
caller changes are needed.
Reported-by: syzbot+3e20d8f3d41bac5dc9a2@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=3e20d8f3d41bac5dc9a2
Signed-off-by: Teng Liu <27rabbitlt@xxxxxxxxx>
---
fs/btrfs/relocation.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 1c42c5180bdd..ce751c35945f 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -835,10 +835,11 @@ static int get_new_location(struct inode *reloc_inode, u64 *new_bytenr,
fi = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_file_extent_item);
- BUG_ON(btrfs_file_extent_offset(leaf, fi) ||
- btrfs_file_extent_compression(leaf, fi) ||
- btrfs_file_extent_encryption(leaf, fi) ||
- btrfs_file_extent_other_encoding(leaf, fi));
+ if (unlikely(btrfs_file_extent_offset(leaf, fi) ||
+ btrfs_file_extent_compression(leaf, fi) ||
+ btrfs_file_extent_encryption(leaf, fi) ||
+ btrfs_file_extent_other_encoding(leaf, fi)))
+ return -EUCLEAN;
Every EUCLEAN should be paired with an error message.
And in this particular case, it's better to provide the tree dump, to really be sure that such data is corrupted other than caused by some bugs.
if (num_bytes != btrfs_file_extent_disk_num_bytes(leaf, fi))
return -EINVAL;