]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: reduce size of struct tree_mod_elem
authorFilipe Manana <fdmanana@suse.com>
Tue, 1 Jul 2025 22:01:56 +0000 (23:01 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 21 Jul 2025 22:09:20 +0000 (00:09 +0200)
Several members are used for specific types of tree mod log operations so
they can be placed in a union in order to reduce the structure's size.

This reduces the structure size from 112 bytes to 88 bytes on x86_64,
so we can now use the kmalloc-96 slab instead of the kmalloc-128 slab.

Reviewed-by: Boris Burkov <boris@bur.io>
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/tree-mod-log.c

index dcb8aef6e9007335076e137c2c7e856df697ce8e..9e8cb3b7c0643fcf6edff22373659224847a5c00 100644 (file)
@@ -27,18 +27,29 @@ struct tree_mod_elem {
        /* This is used for BTRFS_MOD_LOG_KEY* and BTRFS_MOD_LOG_ROOT_REPLACE. */
        u64 generation;
 
-       /* Those are used for op == BTRFS_MOD_LOG_KEY_{REPLACE,REMOVE}. */
-       struct btrfs_disk_key key;
-       u64 blockptr;
-
-       /* This is used for op == BTRFS_MOD_LOG_MOVE_KEYS. */
-       struct {
-               int dst_slot;
-               int nr_items;
-       } move;
-
-       /* This is used for op == BTRFS_MOD_LOG_ROOT_REPLACE. */
-       struct tree_mod_root old_root;
+       union {
+               /*
+                * This is used for the following op types:
+                *
+                *    BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING
+                *    BTRFS_MOD_LOG_KEY_REMOVE_WHILE_MOVING
+                *    BTRFS_MOD_LOG_KEY_REMOVE
+                *    BTRFS_MOD_LOG_KEY_REPLACE
+                */
+               struct {
+                       struct btrfs_disk_key key;
+                       u64 blockptr;
+               } slot_change;
+
+               /* This is used for op == BTRFS_MOD_LOG_MOVE_KEYS. */
+               struct {
+                       int dst_slot;
+                       int nr_items;
+               } move;
+
+               /* This is used for op == BTRFS_MOD_LOG_ROOT_REPLACE. */
+               struct tree_mod_root old_root;
+       };
 };
 
 /*
@@ -228,15 +239,17 @@ static struct tree_mod_elem *alloc_tree_mod_elem(const struct extent_buffer *eb,
 {
        struct tree_mod_elem *tm;
 
+       /* Can't be one of these types, due to union in struct tree_mod_elem. */
+       ASSERT(op != BTRFS_MOD_LOG_MOVE_KEYS);
+       ASSERT(op != BTRFS_MOD_LOG_ROOT_REPLACE);
+
        tm = kzalloc(sizeof(*tm), GFP_NOFS);
        if (!tm)
                return NULL;
 
        tm->logical = eb->start;
-       if (op != BTRFS_MOD_LOG_KEY_ADD) {
-               btrfs_node_key(eb, &tm->key, slot);
-               tm->blockptr = btrfs_node_blockptr(eb, slot);
-       }
+       btrfs_node_key(eb, &tm->slot_change.key, slot);
+       tm->slot_change.blockptr = btrfs_node_blockptr(eb, slot);
        tm->op = op;
        tm->slot = slot;
        tm->generation = btrfs_node_ptr_generation(eb, slot);
@@ -854,8 +867,8 @@ static void tree_mod_log_rewind(struct btrfs_fs_info *fs_info,
                        fallthrough;
                case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_MOVING:
                case BTRFS_MOD_LOG_KEY_REMOVE:
-                       btrfs_set_node_key(eb, &tm->key, tm->slot);
-                       btrfs_set_node_blockptr(eb, tm->slot, tm->blockptr);
+                       btrfs_set_node_key(eb, &tm->slot_change.key, tm->slot);
+                       btrfs_set_node_blockptr(eb, tm->slot, tm->slot_change.blockptr);
                        btrfs_set_node_ptr_generation(eb, tm->slot,
                                                      tm->generation);
                        n++;
@@ -864,8 +877,8 @@ static void tree_mod_log_rewind(struct btrfs_fs_info *fs_info,
                        break;
                case BTRFS_MOD_LOG_KEY_REPLACE:
                        BUG_ON(tm->slot >= n);
-                       btrfs_set_node_key(eb, &tm->key, tm->slot);
-                       btrfs_set_node_blockptr(eb, tm->slot, tm->blockptr);
+                       btrfs_set_node_key(eb, &tm->slot_change.key, tm->slot);
+                       btrfs_set_node_blockptr(eb, tm->slot, tm->slot_change.blockptr);
                        btrfs_set_node_ptr_generation(eb, tm->slot,
                                                      tm->generation);
                        break;