Btrfs: reduce size of struct extent_state
The tree field of struct extent_state was only used to figure out if an extent state was connected to an inode's io tree or not. For this we can just use the rb_node field itself. On a x86_64 system with this change the sizeof(struct extent_state) is reduced from 96 bytes down to 88 bytes, meaning that with a page size of 4096 bytes we can now store 46 extent states per page instead of 42. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
parent
6f84e23646
commit
27a3507de9
|
@ -25,6 +25,11 @@ static struct kmem_cache *extent_state_cache;
|
||||||
static struct kmem_cache *extent_buffer_cache;
|
static struct kmem_cache *extent_buffer_cache;
|
||||||
static struct bio_set *btrfs_bioset;
|
static struct bio_set *btrfs_bioset;
|
||||||
|
|
||||||
|
static inline bool extent_state_in_tree(const struct extent_state *state)
|
||||||
|
{
|
||||||
|
return !RB_EMPTY_NODE(&state->rb_node);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_BTRFS_DEBUG
|
#ifdef CONFIG_BTRFS_DEBUG
|
||||||
static LIST_HEAD(buffers);
|
static LIST_HEAD(buffers);
|
||||||
static LIST_HEAD(states);
|
static LIST_HEAD(states);
|
||||||
|
@ -59,9 +64,9 @@ void btrfs_leak_debug_check(void)
|
||||||
|
|
||||||
while (!list_empty(&states)) {
|
while (!list_empty(&states)) {
|
||||||
state = list_entry(states.next, struct extent_state, leak_list);
|
state = list_entry(states.next, struct extent_state, leak_list);
|
||||||
printk(KERN_ERR "BTRFS: state leak: start %llu end %llu "
|
pr_err("BTRFS: state leak: start %llu end %llu state %lu in tree %d refs %d\n",
|
||||||
"state %lu in tree %p refs %d\n",
|
state->start, state->end, state->state,
|
||||||
state->start, state->end, state->state, state->tree,
|
extent_state_in_tree(state),
|
||||||
atomic_read(&state->refs));
|
atomic_read(&state->refs));
|
||||||
list_del(&state->leak_list);
|
list_del(&state->leak_list);
|
||||||
kmem_cache_free(extent_state_cache, state);
|
kmem_cache_free(extent_state_cache, state);
|
||||||
|
@ -209,7 +214,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask)
|
||||||
return state;
|
return state;
|
||||||
state->state = 0;
|
state->state = 0;
|
||||||
state->private = 0;
|
state->private = 0;
|
||||||
state->tree = NULL;
|
RB_CLEAR_NODE(&state->rb_node);
|
||||||
btrfs_leak_debug_add(&state->leak_list, &states);
|
btrfs_leak_debug_add(&state->leak_list, &states);
|
||||||
atomic_set(&state->refs, 1);
|
atomic_set(&state->refs, 1);
|
||||||
init_waitqueue_head(&state->wq);
|
init_waitqueue_head(&state->wq);
|
||||||
|
@ -222,7 +227,7 @@ void free_extent_state(struct extent_state *state)
|
||||||
if (!state)
|
if (!state)
|
||||||
return;
|
return;
|
||||||
if (atomic_dec_and_test(&state->refs)) {
|
if (atomic_dec_and_test(&state->refs)) {
|
||||||
WARN_ON(state->tree);
|
WARN_ON(extent_state_in_tree(state));
|
||||||
btrfs_leak_debug_del(&state->leak_list);
|
btrfs_leak_debug_del(&state->leak_list);
|
||||||
trace_free_extent_state(state, _RET_IP_);
|
trace_free_extent_state(state, _RET_IP_);
|
||||||
kmem_cache_free(extent_state_cache, state);
|
kmem_cache_free(extent_state_cache, state);
|
||||||
|
@ -371,8 +376,8 @@ static void merge_state(struct extent_io_tree *tree,
|
||||||
other->state == state->state) {
|
other->state == state->state) {
|
||||||
merge_cb(tree, state, other);
|
merge_cb(tree, state, other);
|
||||||
state->start = other->start;
|
state->start = other->start;
|
||||||
other->tree = NULL;
|
|
||||||
rb_erase(&other->rb_node, &tree->state);
|
rb_erase(&other->rb_node, &tree->state);
|
||||||
|
RB_CLEAR_NODE(&other->rb_node);
|
||||||
free_extent_state(other);
|
free_extent_state(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,8 +388,8 @@ static void merge_state(struct extent_io_tree *tree,
|
||||||
other->state == state->state) {
|
other->state == state->state) {
|
||||||
merge_cb(tree, state, other);
|
merge_cb(tree, state, other);
|
||||||
state->end = other->end;
|
state->end = other->end;
|
||||||
other->tree = NULL;
|
|
||||||
rb_erase(&other->rb_node, &tree->state);
|
rb_erase(&other->rb_node, &tree->state);
|
||||||
|
RB_CLEAR_NODE(&other->rb_node);
|
||||||
free_extent_state(other);
|
free_extent_state(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -442,7 +447,6 @@ static int insert_state(struct extent_io_tree *tree,
|
||||||
found->start, found->end, start, end);
|
found->start, found->end, start, end);
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
state->tree = tree;
|
|
||||||
merge_state(tree, state);
|
merge_state(tree, state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -486,7 +490,6 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
|
||||||
free_extent_state(prealloc);
|
free_extent_state(prealloc);
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
prealloc->tree = tree;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,9 +527,9 @@ static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
|
||||||
wake_up(&state->wq);
|
wake_up(&state->wq);
|
||||||
if (state->state == 0) {
|
if (state->state == 0) {
|
||||||
next = next_state(state);
|
next = next_state(state);
|
||||||
if (state->tree) {
|
if (extent_state_in_tree(state)) {
|
||||||
rb_erase(&state->rb_node, &tree->state);
|
rb_erase(&state->rb_node, &tree->state);
|
||||||
state->tree = NULL;
|
RB_CLEAR_NODE(&state->rb_node);
|
||||||
free_extent_state(state);
|
free_extent_state(state);
|
||||||
} else {
|
} else {
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
|
@ -606,8 +609,8 @@ again:
|
||||||
cached_state = NULL;
|
cached_state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cached && cached->tree && cached->start <= start &&
|
if (cached && extent_state_in_tree(cached) &&
|
||||||
cached->end > start) {
|
cached->start <= start && cached->end > start) {
|
||||||
if (clear)
|
if (clear)
|
||||||
atomic_dec(&cached->refs);
|
atomic_dec(&cached->refs);
|
||||||
state = cached;
|
state = cached;
|
||||||
|
@ -843,7 +846,7 @@ again:
|
||||||
if (cached_state && *cached_state) {
|
if (cached_state && *cached_state) {
|
||||||
state = *cached_state;
|
state = *cached_state;
|
||||||
if (state->start <= start && state->end > start &&
|
if (state->start <= start && state->end > start &&
|
||||||
state->tree) {
|
extent_state_in_tree(state)) {
|
||||||
node = &state->rb_node;
|
node = &state->rb_node;
|
||||||
goto hit_next;
|
goto hit_next;
|
||||||
}
|
}
|
||||||
|
@ -1069,7 +1072,7 @@ again:
|
||||||
if (cached_state && *cached_state) {
|
if (cached_state && *cached_state) {
|
||||||
state = *cached_state;
|
state = *cached_state;
|
||||||
if (state->start <= start && state->end > start &&
|
if (state->start <= start && state->end > start &&
|
||||||
state->tree) {
|
extent_state_in_tree(state)) {
|
||||||
node = &state->rb_node;
|
node = &state->rb_node;
|
||||||
goto hit_next;
|
goto hit_next;
|
||||||
}
|
}
|
||||||
|
@ -1459,7 +1462,7 @@ int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
|
||||||
spin_lock(&tree->lock);
|
spin_lock(&tree->lock);
|
||||||
if (cached_state && *cached_state) {
|
if (cached_state && *cached_state) {
|
||||||
state = *cached_state;
|
state = *cached_state;
|
||||||
if (state->end == start - 1 && state->tree) {
|
if (state->end == start - 1 && extent_state_in_tree(state)) {
|
||||||
n = rb_next(&state->rb_node);
|
n = rb_next(&state->rb_node);
|
||||||
while (n) {
|
while (n) {
|
||||||
state = rb_entry(n, struct extent_state,
|
state = rb_entry(n, struct extent_state,
|
||||||
|
@ -1905,7 +1908,7 @@ int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end,
|
||||||
int bitset = 0;
|
int bitset = 0;
|
||||||
|
|
||||||
spin_lock(&tree->lock);
|
spin_lock(&tree->lock);
|
||||||
if (cached && cached->tree && cached->start <= start &&
|
if (cached && extent_state_in_tree(cached) && cached->start <= start &&
|
||||||
cached->end > start)
|
cached->end > start)
|
||||||
node = &cached->rb_node;
|
node = &cached->rb_node;
|
||||||
else
|
else
|
||||||
|
|
|
@ -108,7 +108,6 @@ struct extent_state {
|
||||||
struct rb_node rb_node;
|
struct rb_node rb_node;
|
||||||
|
|
||||||
/* ADD NEW ELEMENTS AFTER THIS */
|
/* ADD NEW ELEMENTS AFTER THIS */
|
||||||
struct extent_io_tree *tree;
|
|
||||||
wait_queue_head_t wq;
|
wait_queue_head_t wq;
|
||||||
atomic_t refs;
|
atomic_t refs;
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
|
|
Loading…
Reference in New Issue