btrfs: remove op field from struct btrfs_free_space_ctl

The op field always points to the same use_bitmap function, the only
exception is during self tests where we make it temporarily point to a
different function. So just because of this op pointer field we are
increasing the structure size by 8 bytes.

Instead of storing a pointer to a use_bitmap function in struct
btrfs_free_space_ctl, move the pointer to struct btrfs_info, make
insert_into_bitmap() use that pointer if we are running the self tests
and initialize that pointer to the current, default use_bitmap function
(now exported for the tests as btrfs_use_bitmap). This way we reduce
the size of struct btrfs_free_space_ctl from 136 to 128 bytes and can
now fit 32 structures in a 4K page instead of 30. This also avoids the
cost of the indirection of a function pointer call when we are not
running the self tests.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Filipe Manana 2026-04-15 19:34:38 +01:00 committed by David Sterba
parent 08d9e2162c
commit 2a1ed20f0d
5 changed files with 31 additions and 33 deletions

View File

@ -2253,7 +2253,8 @@ static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl,
}
static bool use_bitmap(struct btrfs_free_space_ctl *ctl,
EXPORT_FOR_TESTS
bool btrfs_use_bitmap(struct btrfs_free_space_ctl *ctl,
struct btrfs_free_space *info)
{
struct btrfs_block_group *block_group = ctl->block_group;
@ -2303,15 +2304,11 @@ static bool use_bitmap(struct btrfs_free_space_ctl *ctl,
return true;
}
static const struct btrfs_free_space_op free_space_op = {
.use_bitmap = use_bitmap,
};
static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl,
struct btrfs_free_space *info)
{
struct btrfs_free_space *bitmap_info;
struct btrfs_block_group *block_group = NULL;
struct btrfs_block_group *block_group = ctl->block_group;
int added = 0;
u64 bytes, offset, bytes_added;
enum btrfs_trim_state trim_state;
@ -2321,18 +2318,20 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl,
offset = info->offset;
trim_state = info->trim_state;
if (!ctl->op->use_bitmap(ctl, info))
return 0;
if (ctl->op == &free_space_op)
block_group = ctl->block_group;
if (btrfs_is_testing(block_group->fs_info)) {
if (!block_group->fs_info->use_bitmap(ctl, info))
return 0;
} else {
if (!btrfs_use_bitmap(ctl, info))
return 0;
}
again:
/*
* Since we link bitmaps right into the cluster we need to see if we
* have a cluster here, and if so and it has our bitmap we need to add
* the free space to that bitmap.
*/
if (block_group && !list_empty(&block_group->cluster_list)) {
if (!list_empty(&block_group->cluster_list)) {
struct btrfs_free_cluster *cluster;
struct rb_node *node;
struct btrfs_free_space *entry;
@ -2953,7 +2952,6 @@ void btrfs_init_free_space_ctl(struct btrfs_block_group *block_group,
{
spin_lock_init(&ctl->tree_lock);
ctl->block_group = block_group;
ctl->op = &free_space_op;
ctl->free_space_bytes = RB_ROOT_CACHED;
INIT_LIST_HEAD(&ctl->trimming_ranges);
mutex_init(&ctl->cache_writeout_mutex);

View File

@ -83,17 +83,11 @@ struct btrfs_free_space_ctl {
u64 free_space;
s32 discardable_extents[BTRFS_STAT_NR_ENTRIES];
s64 discardable_bytes[BTRFS_STAT_NR_ENTRIES];
const struct btrfs_free_space_op *op;
struct btrfs_block_group *block_group;
struct mutex cache_writeout_mutex;
struct list_head trimming_ranges;
};
struct btrfs_free_space_op {
bool (*use_bitmap)(struct btrfs_free_space_ctl *ctl,
struct btrfs_free_space *info);
};
struct btrfs_io_ctl {
void *cur, *orig;
struct page *page;
@ -170,6 +164,8 @@ bool btrfs_free_space_cache_v1_active(struct btrfs_fs_info *fs_info);
int btrfs_set_free_space_cache_v1_active(struct btrfs_fs_info *fs_info, bool active);
/* Support functions for running our sanity tests */
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
bool btrfs_use_bitmap(struct btrfs_free_space_ctl *ctl,
struct btrfs_free_space *info);
int test_add_free_space_entry(struct btrfs_block_group *cache,
u64 offset, u64 bytes, bool bitmap);
int test_check_exists(struct btrfs_block_group *cache, u64 offset, u64 bytes);

View File

@ -486,6 +486,9 @@ struct btrfs_delayed_root {
wait_queue_head_t wait;
};
struct btrfs_free_space_ctl;
struct btrfs_free_space;
struct btrfs_fs_info {
u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
unsigned long flags;
@ -951,6 +954,10 @@ struct btrfs_fs_info {
spinlock_t eb_leak_lock;
struct list_head allocated_ebs;
#endif
/* Used by self tests only. */
bool (*use_bitmap)(struct btrfs_free_space_ctl *ctl,
struct btrfs_free_space *info);
};
#define folio_to_inode(_folio) (BTRFS_I(_Generic((_folio), \

View File

@ -145,6 +145,7 @@ struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(u32 nodesize, u32 sectorsize)
fs_info->csum_size = 4;
fs_info->csums_per_leaf = BTRFS_MAX_ITEM_SIZE(fs_info) /
fs_info->csum_size;
fs_info->use_bitmap = btrfs_use_bitmap;
set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
test_mnt->mnt_sb->s_fs_info = fs_info;

View File

@ -398,10 +398,8 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group *cache,
int ret;
u64 offset;
u64 max_extent_size;
const struct btrfs_free_space_op test_free_space_ops = {
.use_bitmap = test_use_bitmap,
};
const struct btrfs_free_space_op *orig_free_space_ops;
bool (*orig_use_bitmap)(struct btrfs_free_space_ctl *ctl,
struct btrfs_free_space *info);
test_msg("running space stealing from bitmap to extent tests");
@ -423,8 +421,8 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group *cache,
* that forces use of bitmaps as soon as we have at least 1
* extent entry.
*/
orig_free_space_ops = cache->free_space_ctl->op;
cache->free_space_ctl->op = &test_free_space_ops;
orig_use_bitmap = cache->fs_info->use_bitmap;
cache->fs_info->use_bitmap = test_use_bitmap;
/*
* Extent entry covering free space range [128Mb - 256Kb, 128Mb - 128Kb[
@ -818,7 +816,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group *cache,
if (ret)
return ret;
cache->free_space_ctl->op = orig_free_space_ops;
cache->fs_info->use_bitmap = orig_use_bitmap;
btrfs_remove_free_space_cache(cache);
return 0;
@ -832,10 +830,8 @@ static bool bytes_index_use_bitmap(struct btrfs_free_space_ctl *ctl,
static int test_bytes_index(struct btrfs_block_group *cache, u32 sectorsize)
{
const struct btrfs_free_space_op test_free_space_ops = {
.use_bitmap = bytes_index_use_bitmap,
};
const struct btrfs_free_space_op *orig_free_space_ops;
bool (*orig_use_bitmap)(struct btrfs_free_space_ctl *ctl,
struct btrfs_free_space *info);
struct btrfs_free_space_ctl *ctl = cache->free_space_ctl;
struct btrfs_free_space *entry;
struct rb_node *node;
@ -892,8 +888,8 @@ static int test_bytes_index(struct btrfs_block_group *cache, u32 sectorsize)
/* Now validate bitmaps with different ->max_extent_size. */
btrfs_remove_free_space_cache(cache);
orig_free_space_ops = cache->free_space_ctl->op;
cache->free_space_ctl->op = &test_free_space_ops;
orig_use_bitmap = cache->fs_info->use_bitmap;
cache->fs_info->use_bitmap = bytes_index_use_bitmap;
ret = test_add_free_space_entry(cache, 0, sectorsize, 1);
if (ret) {
@ -997,7 +993,7 @@ static int test_bytes_index(struct btrfs_block_group *cache, u32 sectorsize)
return -EINVAL;
}
cache->free_space_ctl->op = orig_free_space_ops;
cache->fs_info->use_bitmap = orig_use_bitmap;
btrfs_remove_free_space_cache(cache);
return 0;
}