]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: use a kmem_cache for free space control structures
authorFilipe Manana <fdmanana@suse.com>
Wed, 15 Apr 2026 12:12:13 +0000 (13:12 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 8 Jun 2026 13:53:29 +0000 (15:53 +0200)
We are currently allocating the free space control structures for block
groups using the generic slabs, and given that the size of the
btrfs_free_space_ctl structure is 152 bytes (on a release kernel), we end
up using the kmalloc-192 slab and therefore waste quite some memory since
on a 4K page system we can only fit 21 free space control structures per
page. These structures are allocated and delallocated every time we create
and remove block groups.

So use a kmem_cache for free space control structures, this way on a 4K
page system we can fit 26 structures instead of 21.

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

index a32de3a822d24613ccb999c428b4a911fafe9f6d..01560307014383e1f2c704205e1134efa31d5092 100644 (file)
@@ -23,6 +23,7 @@
 #include "extent-tree.h"
 
 static struct kmem_cache *block_group_cache;
+static struct kmem_cache *free_space_ctl_cache;
 
 int __init btrfs_init_block_group(void)
 {
@@ -31,12 +32,22 @@ int __init btrfs_init_block_group(void)
                                              0, 0, NULL);
        if (!block_group_cache)
                return -ENOMEM;
+
+       free_space_ctl_cache = kmem_cache_create("btrfs_free_space_ctl",
+                                                sizeof(struct btrfs_free_space_ctl),
+                                                0, 0, NULL);
+       if (!free_space_ctl_cache) {
+               kmem_cache_destroy(block_group_cache);
+               return -ENOMEM;
+       }
+
        return 0;
 }
 
 void __cold btrfs_exit_block_group(void)
 {
        kmem_cache_destroy(block_group_cache);
+       kmem_cache_destroy(free_space_ctl_cache);
 }
 
 #ifdef CONFIG_BTRFS_DEBUG
@@ -197,7 +208,7 @@ void btrfs_put_block_group(struct btrfs_block_group *cache)
                        btrfs_discard_cancel_work(&cache->fs_info->discard_ctl,
                                                  cache);
 
-               kfree(cache->free_space_ctl);
+               kmem_cache_free(free_space_ctl_cache, cache->free_space_ctl);
                btrfs_free_chunk_map(cache->physical_map);
                kmem_cache_free(block_group_cache, cache);
        }
@@ -2392,7 +2403,7 @@ static struct btrfs_block_group *btrfs_create_block_group(
        if (!cache)
                return NULL;
 
-       cache->free_space_ctl = kzalloc_obj(*cache->free_space_ctl, GFP_NOFS);
+       cache->free_space_ctl = kmem_cache_zalloc(free_space_ctl_cache, GFP_NOFS);
        if (!cache->free_space_ctl) {
                kmem_cache_free(block_group_cache, cache);
                return NULL;