Commit 4c469798 authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba

btrfs: shrink the size of struct btrfs_delayed_item

Currently struct btrfs_delayed_item has a base size of 96 bytes, but its
size can be decreased by doing the following 2 tweaks:

1) Change data_len from u32 to u16. Our maximum possible leaf size is 64K,
   so the data_len can never be larger than that, and in fact it is always
   much smaller than that. The max length for a dentry's name is ensured
   at the VFS level (PATH_MAX, 4096 bytes) and in struct btrfs_inode_ref
   and btrfs_dir_item we use a u16 to store the name's length;

2) Change 'ins_or_del' to a 1 bit enum, which is all we need since it
   can only have 2 values. After this there's also no longer the need to
   BUG_ON() before using 'ins_or_del' in several places. Also rename the
   field from 'ins_or_del' to 'type', which is more clear.

These two tweaks decrease the size of struct btrfs_delayed_item from 96
bytes down to 88 bytes. A previous patch already reduced the size of this
structure by 16 bytes, but an upcoming change will increase its size by
16 bytes (adding a struct list_head element).
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 4cbf37f5
...@@ -302,14 +302,16 @@ static inline void btrfs_release_prepared_delayed_node( ...@@ -302,14 +302,16 @@ static inline void btrfs_release_prepared_delayed_node(
__btrfs_release_delayed_node(node, 1); __btrfs_release_delayed_node(node, 1);
} }
static struct btrfs_delayed_item *btrfs_alloc_delayed_item(u32 data_len, static struct btrfs_delayed_item *btrfs_alloc_delayed_item(u16 data_len,
struct btrfs_delayed_node *node) struct btrfs_delayed_node *node,
enum btrfs_delayed_item_type type)
{ {
struct btrfs_delayed_item *item; struct btrfs_delayed_item *item;
item = kmalloc(sizeof(*item) + data_len, GFP_NOFS); item = kmalloc(sizeof(*item) + data_len, GFP_NOFS);
if (item) { if (item) {
item->data_len = data_len; item->data_len = data_len;
item->ins_or_del = 0; item->type = type;
item->bytes_reserved = 0; item->bytes_reserved = 0;
item->delayed_node = node; item->delayed_node = node;
RB_CLEAR_NODE(&item->rb_node); RB_CLEAR_NODE(&item->rb_node);
...@@ -356,12 +358,11 @@ static int __btrfs_add_delayed_item(struct btrfs_delayed_node *delayed_node, ...@@ -356,12 +358,11 @@ static int __btrfs_add_delayed_item(struct btrfs_delayed_node *delayed_node,
struct btrfs_delayed_item *item; struct btrfs_delayed_item *item;
bool leftmost = true; bool leftmost = true;
if (ins->ins_or_del == BTRFS_DELAYED_INSERTION_ITEM) if (ins->type == BTRFS_DELAYED_INSERTION_ITEM)
root = &delayed_node->ins_root; root = &delayed_node->ins_root;
else if (ins->ins_or_del == BTRFS_DELAYED_DELETION_ITEM)
root = &delayed_node->del_root;
else else
BUG(); root = &delayed_node->del_root;
p = &root->rb_root.rb_node; p = &root->rb_root.rb_node;
node = &ins->rb_node; node = &ins->rb_node;
...@@ -383,7 +384,7 @@ static int __btrfs_add_delayed_item(struct btrfs_delayed_node *delayed_node, ...@@ -383,7 +384,7 @@ static int __btrfs_add_delayed_item(struct btrfs_delayed_node *delayed_node,
rb_link_node(node, parent_node, p); rb_link_node(node, parent_node, p);
rb_insert_color_cached(node, root, leftmost); rb_insert_color_cached(node, root, leftmost);
if (ins->ins_or_del == BTRFS_DELAYED_INSERTION_ITEM && if (ins->type == BTRFS_DELAYED_INSERTION_ITEM &&
ins->index >= delayed_node->index_cnt) ins->index >= delayed_node->index_cnt)
delayed_node->index_cnt = ins->index + 1; delayed_node->index_cnt = ins->index + 1;
...@@ -414,10 +415,8 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item) ...@@ -414,10 +415,8 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
delayed_root = delayed_item->delayed_node->root->fs_info->delayed_root; delayed_root = delayed_item->delayed_node->root->fs_info->delayed_root;
BUG_ON(!delayed_root); BUG_ON(!delayed_root);
BUG_ON(delayed_item->ins_or_del != BTRFS_DELAYED_DELETION_ITEM &&
delayed_item->ins_or_del != BTRFS_DELAYED_INSERTION_ITEM);
if (delayed_item->ins_or_del == BTRFS_DELAYED_INSERTION_ITEM) if (delayed_item->type == BTRFS_DELAYED_INSERTION_ITEM)
root = &delayed_item->delayed_node->ins_root; root = &delayed_item->delayed_node->ins_root;
else else
root = &delayed_item->delayed_node->del_root; root = &delayed_item->delayed_node->del_root;
...@@ -509,7 +508,7 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, ...@@ -509,7 +508,7 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
* for the number of leaves that will be used, based on the delayed * for the number of leaves that will be used, based on the delayed
* node's index_items_size field. * node's index_items_size field.
*/ */
if (item->ins_or_del == BTRFS_DELAYED_DELETION_ITEM) if (item->type == BTRFS_DELAYED_DELETION_ITEM)
item->bytes_reserved = num_bytes; item->bytes_reserved = num_bytes;
} }
...@@ -646,6 +645,7 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, ...@@ -646,6 +645,7 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans,
const int max_size = BTRFS_LEAF_DATA_SIZE(fs_info); const int max_size = BTRFS_LEAF_DATA_SIZE(fs_info);
struct btrfs_item_batch batch; struct btrfs_item_batch batch;
struct btrfs_key first_key; struct btrfs_key first_key;
const u32 first_data_size = first_item->data_len;
int total_size; int total_size;
char *ins_data = NULL; char *ins_data = NULL;
int ret; int ret;
...@@ -674,9 +674,9 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, ...@@ -674,9 +674,9 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans,
ASSERT(first_item->bytes_reserved == 0); ASSERT(first_item->bytes_reserved == 0);
list_add_tail(&first_item->tree_list, &item_list); list_add_tail(&first_item->tree_list, &item_list);
batch.total_data_size = first_item->data_len; batch.total_data_size = first_data_size;
batch.nr = 1; batch.nr = 1;
total_size = first_item->data_len + sizeof(struct btrfs_item); total_size = first_data_size + sizeof(struct btrfs_item);
curr = first_item; curr = first_item;
while (true) { while (true) {
...@@ -711,7 +711,7 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, ...@@ -711,7 +711,7 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans,
first_key.type = BTRFS_DIR_INDEX_KEY; first_key.type = BTRFS_DIR_INDEX_KEY;
first_key.offset = first_item->index; first_key.offset = first_item->index;
batch.keys = &first_key; batch.keys = &first_key;
batch.data_sizes = &first_item->data_len; batch.data_sizes = &first_data_size;
} else { } else {
struct btrfs_key *ins_keys; struct btrfs_key *ins_keys;
u32 *ins_sizes; u32 *ins_sizes;
...@@ -1427,14 +1427,14 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1427,14 +1427,14 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
return PTR_ERR(delayed_node); return PTR_ERR(delayed_node);
delayed_item = btrfs_alloc_delayed_item(sizeof(*dir_item) + name_len, delayed_item = btrfs_alloc_delayed_item(sizeof(*dir_item) + name_len,
delayed_node); delayed_node,
BTRFS_DELAYED_INSERTION_ITEM);
if (!delayed_item) { if (!delayed_item) {
ret = -ENOMEM; ret = -ENOMEM;
goto release_node; goto release_node;
} }
delayed_item->index = index; delayed_item->index = index;
delayed_item->ins_or_del = BTRFS_DELAYED_INSERTION_ITEM;
dir_item = (struct btrfs_dir_item *)delayed_item->data; dir_item = (struct btrfs_dir_item *)delayed_item->data;
dir_item->location = *disk_key; dir_item->location = *disk_key;
...@@ -1566,14 +1566,13 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans, ...@@ -1566,14 +1566,13 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans,
if (!ret) if (!ret)
goto end; goto end;
item = btrfs_alloc_delayed_item(0, node); item = btrfs_alloc_delayed_item(0, node, BTRFS_DELAYED_DELETION_ITEM);
if (!item) { if (!item) {
ret = -ENOMEM; ret = -ENOMEM;
goto end; goto end;
} }
item->index = index; item->index = index;
item->ins_or_del = BTRFS_DELAYED_DELETION_ITEM;
ret = btrfs_delayed_item_reserve_metadata(trans, item); ret = btrfs_delayed_item_reserve_metadata(trans, item);
/* /*
......
...@@ -16,9 +16,10 @@ ...@@ -16,9 +16,10 @@
#include <linux/refcount.h> #include <linux/refcount.h>
#include "ctree.h" #include "ctree.h"
/* types of the delayed item */ enum btrfs_delayed_item_type {
#define BTRFS_DELAYED_INSERTION_ITEM 1 BTRFS_DELAYED_INSERTION_ITEM,
#define BTRFS_DELAYED_DELETION_ITEM 2 BTRFS_DELAYED_DELETION_ITEM
};
struct btrfs_delayed_root { struct btrfs_delayed_root {
spinlock_t lock; spinlock_t lock;
...@@ -80,8 +81,9 @@ struct btrfs_delayed_item { ...@@ -80,8 +81,9 @@ struct btrfs_delayed_item {
u64 bytes_reserved; u64 bytes_reserved;
struct btrfs_delayed_node *delayed_node; struct btrfs_delayed_node *delayed_node;
refcount_t refs; refcount_t refs;
int ins_or_del; enum btrfs_delayed_item_type type:8;
u32 data_len; /* The maximum leaf size is 64K, so u16 is more than enough. */
u16 data_len;
char data[]; char data[];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment