]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: tree-checker: introduce checks for FREE_SPACE_EXTENT
authorQu Wenruo <wqu@suse.com>
Mon, 9 Mar 2026 22:19:26 +0000 (08:49 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 Apr 2026 16:56:01 +0000 (18:56 +0200)
Introduce FREE_SPACE_EXTENT checks, which include:

- The key alignment check
  The objectid is the logical bytenr of the free space, and offset is the
  length of the free space, thus they should all be aligned to the fs
  block size.

- The item size check
  The FREE_SPACE_EXTENT item should have a size of zero.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/tree-checker.c

index c4826b0484e6aa50d6b3e1852a683a43fe3f4e9e..f4a8f1c643ed53f438c59e6abae2977d0d9b8dfe 100644 (file)
@@ -1992,6 +1992,32 @@ static int check_free_space_info(struct extent_buffer *leaf, struct btrfs_key *k
        return 0;
 }
 
+static int check_free_space_extent(struct extent_buffer *leaf, struct btrfs_key *key, int slot)
+{
+       struct btrfs_fs_info *fs_info = leaf->fs_info;
+       const u32 blocksize = fs_info->sectorsize;
+
+       if (unlikely(!IS_ALIGNED(key->objectid, blocksize))) {
+               generic_err(leaf, slot,
+               "free space extent key objectid is not aligned to %u, has " BTRFS_KEY_FMT,
+                           blocksize, BTRFS_KEY_FMT_VALUE(key));
+               return -EUCLEAN;
+       }
+       if (unlikely(!IS_ALIGNED(key->offset, blocksize))) {
+               generic_err(leaf, slot,
+               "free space extent key offset is not aligned to %u, has " BTRFS_KEY_FMT,
+                           blocksize, BTRFS_KEY_FMT_VALUE(key));
+               return -EUCLEAN;
+       }
+       if (unlikely(btrfs_item_size(leaf, slot) != 0)) {
+               generic_err(leaf, slot,
+                           "invalid item size for free space info, has %u expect 0",
+                           btrfs_item_size(leaf, slot));
+               return -EUCLEAN;
+       }
+       return 0;
+}
+
 /*
  * Common point to switch the item-specific validation.
  */
@@ -2058,6 +2084,9 @@ static enum btrfs_tree_block_status check_leaf_item(struct extent_buffer *leaf,
        case BTRFS_FREE_SPACE_INFO_KEY:
                ret = check_free_space_info(leaf, key, slot);
                break;
+       case BTRFS_FREE_SPACE_EXTENT_KEY:
+               ret = check_free_space_extent(leaf, key, slot);
+               break;
        }
 
        if (unlikely(ret))