summaryrefslogtreecommitdiff
path: root/fs/btrfs/relocation.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-03-21 08:42:17 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-03-21 08:42:17 -0700
commit8991448e56cb2118b561eeda193af53b4ff6b632 (patch)
treea7ae3e706dda9f4a4a2a4802ee4a3af3eb6e5b4b /fs/btrfs/relocation.c
parenta0c83177734ab98623795e1ba2cf4b72c23de5e7 (diff)
parentb17b79ff896305fd74980a5f72afec370ee88ca4 (diff)
downloadlinux-next-8991448e56cb2118b561eeda193af53b4ff6b632.tar.gz
linux-next-8991448e56cb2118b561eeda193af53b4ff6b632.zip
Merge tag 'for-7.0-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "Another batch of fixes for problems that have been identified by tools analyzing code or by fuzzing. Most of them are short, two patches fix the same thing in many places so the diffs are bigger. - handle potential NULL pointer errors after attempting to read extent and checksum trees - prevent ENOSPC when creating many qgroups by ioctls in the same transaction - encoded write ioctl fixes (with 64K page and 4K block size): - fix unexpected bio length - do not let compressed bios and pages interfere with page cache - compression fixes on setups with 64K page and 4K block size: fix folio length assertions (zstd and lzo) - remap tree fixes: - make sure to hold block group reference while moving it - handle early exit when moving block group to unused list - handle deleted subvolumes with inconsistent state of deletion progress" * tag 'for-7.0-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: reject root items with drop_progress and zero drop_level btrfs: check block group before marking it unused in balance_remap_chunks() btrfs: hold block group reference during entire move_existing_remap() btrfs: fix an incorrect ASSERT() condition inside lzo_decompress_bio() btrfs: fix an incorrect ASSERT() condition inside zstd_decompress_bio() btrfs: do not touch page cache for encoded writes btrfs: fix a bug that makes encoded write bio larger than expected btrfs: reserve enough transaction items for qgroup ioctls btrfs: check for NULL root after calls to btrfs_csum_root() btrfs: check for NULL root after calls to btrfs_extent_root()
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r--fs/btrfs/relocation.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index b2343aed7a5d..033f74fd6225 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4185,6 +4185,8 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info,
dest_addr = ins.objectid;
dest_length = ins.offset;
+ dest_bg = btrfs_lookup_block_group(fs_info, dest_addr);
+
if (!is_data && !IS_ALIGNED(dest_length, fs_info->nodesize)) {
u64 new_length = ALIGN_DOWN(dest_length, fs_info->nodesize);
@@ -4295,15 +4297,12 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info,
if (unlikely(ret))
goto end;
- dest_bg = btrfs_lookup_block_group(fs_info, dest_addr);
-
adjust_block_group_remap_bytes(trans, dest_bg, dest_length);
mutex_lock(&dest_bg->free_space_lock);
bg_needs_free_space = test_bit(BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE,
&dest_bg->runtime_flags);
mutex_unlock(&dest_bg->free_space_lock);
- btrfs_put_block_group(dest_bg);
if (bg_needs_free_space) {
ret = btrfs_add_block_group_free_space(trans, dest_bg);
@@ -4333,13 +4332,13 @@ end:
btrfs_end_transaction(trans);
}
} else {
- dest_bg = btrfs_lookup_block_group(fs_info, dest_addr);
btrfs_free_reserved_bytes(dest_bg, dest_length, 0);
- btrfs_put_block_group(dest_bg);
ret = btrfs_commit_transaction(trans);
}
+ btrfs_put_block_group(dest_bg);
+
return ret;
}
@@ -4954,6 +4953,12 @@ static int do_remap_reloc_trans(struct btrfs_fs_info *fs_info,
struct btrfs_space_info *sinfo = src_bg->space_info;
extent_root = btrfs_extent_root(fs_info, src_bg->start);
+ if (unlikely(!extent_root)) {
+ btrfs_err(fs_info,
+ "missing extent root for block group at offset %llu",
+ src_bg->start);
+ return -EUCLEAN;
+ }
trans = btrfs_start_transaction(extent_root, 0);
if (IS_ERR(trans))
@@ -5306,6 +5311,13 @@ int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start,
int ret;
bool bg_is_ro = false;
+ if (unlikely(!extent_root)) {
+ btrfs_err(fs_info,
+ "missing extent root for block group at offset %llu",
+ group_start);
+ return -EUCLEAN;
+ }
+
/*
* This only gets set if we had a half-deleted snapshot on mount. We
* cannot allow relocation to start while we're still trying to clean up
@@ -5536,12 +5548,17 @@ int btrfs_recover_relocation(struct btrfs_fs_info *fs_info)
goto out;
}
+ rc->extent_root = btrfs_extent_root(fs_info, 0);
+ if (unlikely(!rc->extent_root)) {
+ btrfs_err(fs_info, "missing extent root for extent at bytenr 0");
+ ret = -EUCLEAN;
+ goto out;
+ }
+
ret = reloc_chunk_start(fs_info);
if (ret < 0)
goto out_end;
- rc->extent_root = btrfs_extent_root(fs_info, 0);
-
set_reloc_control(rc);
trans = btrfs_join_transaction(rc->extent_root);
@@ -5636,6 +5653,14 @@ int btrfs_reloc_clone_csums(struct btrfs_ordered_extent *ordered)
LIST_HEAD(list);
int ret;
+ if (unlikely(!csum_root)) {
+ btrfs_mark_ordered_extent_error(ordered);
+ btrfs_err(fs_info,
+ "missing csum root for extent at bytenr %llu",
+ disk_bytenr);
+ return -EUCLEAN;
+ }
+
ret = btrfs_lookup_csums_list(csum_root, disk_bytenr,
disk_bytenr + ordered->num_bytes - 1,
&list, false);