]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: remove remapped block groups from the free-space-tree
authorMark Harmstone <mark@harmstone.com>
Wed, 7 Jan 2026 14:09:04 +0000 (14:09 +0000)
committerDavid Sterba <dsterba@suse.com>
Tue, 3 Feb 2026 06:54:34 +0000 (07:54 +0100)
No new allocations can be done from block groups that have the REMAPPED
flag set, so there's no value in their having entries in the free-space
tree.

Prevent a search through the free-space tree being scheduled for such a
block group, and prevent any additions to the in-memory free-space tree.

Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Mark Harmstone <mark@harmstone.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/block-group.c
fs/btrfs/free-space-cache.c

index 9d64cc60a42b5fdf33dba065ac8f6bfd65b56ba3..a2f95ac5a8d0a8a02ea5fcf37ff0e502fdc03c85 100644 (file)
@@ -933,6 +933,13 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait)
        if (btrfs_is_zoned(fs_info))
                return 0;
 
+       /*
+        * No allocations can be done from remapped block groups, so they have
+        * no entries in the free-space tree.
+        */
+       if (cache->flags & BTRFS_BLOCK_GROUP_REMAPPED)
+               return 0;
+
        caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS);
        if (!caching_ctl)
                return -ENOMEM;
@@ -1246,10 +1253,16 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
         * deletes the block group item from the extent tree, allowing for
         * another task to attempt to create another block group with the same
         * item key (and failing with -EEXIST and a transaction abort).
+        *
+        * If the REMAPPED flag has been set the block group's free space
+        * has already been removed, so we can skip the call to
+        * btrfs_remove_block_group_free_space().
         */
-       ret = btrfs_remove_block_group_free_space(trans, block_group);
-       if (ret)
-               goto out;
+       if (!(block_group->flags & BTRFS_BLOCK_GROUP_REMAPPED)) {
+               ret = btrfs_remove_block_group_free_space(trans, block_group);
+               if (ret)
+                       goto out;
+       }
 
        ret = remove_block_group_item(trans, path, block_group);
        if (ret < 0)
index f0f72850fab24794d06426ca22b79da92749bd62..8d4db3d57cf74784e2bcdecb99a670f1b0956de1 100644 (file)
@@ -2756,6 +2756,9 @@ int btrfs_add_free_space(struct btrfs_block_group *block_group,
 {
        enum btrfs_trim_state trim_state = BTRFS_TRIM_STATE_UNTRIMMED;
 
+       if (block_group->flags & BTRFS_BLOCK_GROUP_REMAPPED)
+               return 0;
+
        if (btrfs_is_zoned(block_group->fs_info))
                return __btrfs_add_free_space_zoned(block_group, bytenr, size,
                                                    true);