]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: use a kmem_cache for block groups
authorFilipe Manana <fdmanana@suse.com>
Wed, 15 Apr 2026 11:26:40 +0000 (12:26 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 8 Jun 2026 13:53:28 +0000 (15:53 +0200)
We are currently allocating block groups using the generic slabs, and
given that the size of btrfs_block_group structure is 672 bytes (on a
release kernel), we end up using the kmalloc-1024 slab and therefore
waste quite some memory since on a 4K page system we can only fit 4
block groups per page. The block groups are also allocated and
delallocated with some frequency, specially if we have auto reclaim
enabled.

So use a kmem_cache for block groups, this way on a 4K page system we
can fit 6 block groups per page instead of 4.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/block-group.c
fs/btrfs/block-group.h
fs/btrfs/super.c

index b611c64119dbca6ed54bb28c066fc23c4a224027..a32de3a822d24613ccb999c428b4a911fafe9f6d 100644 (file)
 #include "accessors.h"
 #include "extent-tree.h"
 
+static struct kmem_cache *block_group_cache;
+
+int __init btrfs_init_block_group(void)
+{
+       block_group_cache = kmem_cache_create("btrfs_block_group",
+                                             sizeof(struct btrfs_block_group),
+                                             0, 0, NULL);
+       if (!block_group_cache)
+               return -ENOMEM;
+       return 0;
+}
+
+void __cold btrfs_exit_block_group(void)
+{
+       kmem_cache_destroy(block_group_cache);
+}
+
 #ifdef CONFIG_BTRFS_DEBUG
 int btrfs_should_fragment_free_space(const struct btrfs_block_group *block_group)
 {
@@ -182,7 +199,7 @@ void btrfs_put_block_group(struct btrfs_block_group *cache)
 
                kfree(cache->free_space_ctl);
                btrfs_free_chunk_map(cache->physical_map);
-               kfree(cache);
+               kmem_cache_free(block_group_cache, cache);
        }
 }
 
@@ -2371,13 +2388,13 @@ static struct btrfs_block_group *btrfs_create_block_group(
 {
        struct btrfs_block_group *cache;
 
-       cache = kzalloc_obj(*cache, GFP_NOFS);
+       cache = kmem_cache_zalloc(block_group_cache, GFP_NOFS);
        if (!cache)
                return NULL;
 
        cache->free_space_ctl = kzalloc_obj(*cache->free_space_ctl, GFP_NOFS);
        if (!cache->free_space_ctl) {
-               kfree(cache);
+               kmem_cache_free(block_group_cache, cache);
                return NULL;
        }
 
index 0504cb357992152cc43e671be052191e7c131a25..b414f4268d2d310c4443beac61dc44864d444817 100644 (file)
@@ -320,6 +320,9 @@ static inline u64 btrfs_block_group_available_space(const struct btrfs_block_gro
 int btrfs_should_fragment_free_space(const struct btrfs_block_group *block_group);
 #endif
 
+int __init btrfs_init_block_group(void);
+void __cold btrfs_exit_block_group(void);
+
 struct btrfs_block_group *btrfs_lookup_first_block_group(
                struct btrfs_fs_info *info, u64 bytenr);
 struct btrfs_block_group *btrfs_lookup_block_group(
index f67a268f36a6d6a2535d03177897545adb0d9765..a60bce413d33b5ecf221bba73fc3362c7f76457a 100644 (file)
@@ -2603,6 +2603,9 @@ static const struct init_sequence mod_init_seq[] = {
        }, {
                .init_func = btrfs_init_compress,
                .exit_func = btrfs_exit_compress,
+       }, {
+               .init_func = btrfs_init_block_group,
+               .exit_func = btrfs_exit_block_group,
        }, {
                .init_func = btrfs_init_cachep,
                .exit_func = btrfs_destroy_cachep,