Commit bce4eae9 authored by Chris Mason's avatar Chris Mason

Btrfs: Fix balance_level to free the middle block if there is room in the left one

balance level starts by trying to empty the middle block, and then
pushes from the right to the middle.  This might empty the right block
and leave a small number of pointers in the middle.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 971a1f66
...@@ -789,7 +789,7 @@ static int balance_level(struct btrfs_trans_handle *trans, ...@@ -789,7 +789,7 @@ static int balance_level(struct btrfs_trans_handle *trans,
/* first, try to make some room in the middle buffer */ /* first, try to make some room in the middle buffer */
if (left) { if (left) {
orig_slot += btrfs_header_nritems(left); orig_slot += btrfs_header_nritems(left);
wret = push_node_left(trans, root, left, mid, 0); wret = push_node_left(trans, root, left, mid, 1);
if (wret < 0) if (wret < 0)
ret = wret; ret = wret;
if (btrfs_header_nritems(mid) < 2) if (btrfs_header_nritems(mid) < 2)
...@@ -844,6 +844,11 @@ static int balance_level(struct btrfs_trans_handle *trans, ...@@ -844,6 +844,11 @@ static int balance_level(struct btrfs_trans_handle *trans,
ret = wret; ret = wret;
goto enospc; goto enospc;
} }
if (wret == 1) {
wret = push_node_left(trans, root, left, mid, 1);
if (wret < 0)
ret = wret;
}
BUG_ON(wret == 1); BUG_ON(wret == 1);
} }
if (btrfs_header_nritems(mid) == 0) { if (btrfs_header_nritems(mid) == 0) {
...@@ -1252,17 +1257,27 @@ static int push_node_left(struct btrfs_trans_handle *trans, ...@@ -1252,17 +1257,27 @@ static int push_node_left(struct btrfs_trans_handle *trans,
WARN_ON(btrfs_header_generation(src) != trans->transid); WARN_ON(btrfs_header_generation(src) != trans->transid);
WARN_ON(btrfs_header_generation(dst) != trans->transid); WARN_ON(btrfs_header_generation(dst) != trans->transid);
if (!empty && src_nritems <= 2) if (!empty && src_nritems <= 8)
return 1; return 1;
if (push_items <= 0) { if (push_items <= 0) {
return 1; return 1;
} }
if (empty) if (empty) {
push_items = min(src_nritems, push_items); push_items = min(src_nritems, push_items);
else if (push_items < src_nritems) {
push_items = min(src_nritems - 2, push_items); /* leave at least 8 pointers in the node if
* we aren't going to empty it
*/
if (src_nritems - push_items < 8) {
if (push_items <= 8)
return 1;
push_items -= 8;
}
}
} else
push_items = min(src_nritems - 8, push_items);
copy_extent_buffer(dst, src, copy_extent_buffer(dst, src,
btrfs_node_key_ptr_offset(dst_nritems), btrfs_node_key_ptr_offset(dst_nritems),
...@@ -1308,13 +1323,19 @@ static int balance_node_right(struct btrfs_trans_handle *trans, ...@@ -1308,13 +1323,19 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
src_nritems = btrfs_header_nritems(src); src_nritems = btrfs_header_nritems(src);
dst_nritems = btrfs_header_nritems(dst); dst_nritems = btrfs_header_nritems(dst);
push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
if (push_items <= 0) if (push_items <= 0) {
return 1; return 1;
}
if (src_nritems < 4) {
return 1;
}
max_push = src_nritems / 2 + 1; max_push = src_nritems / 2 + 1;
/* don't try to empty the node */ /* don't try to empty the node */
if (max_push >= src_nritems) if (max_push >= src_nritems) {
return 1; return 1;
}
if (max_push < push_items) if (max_push < push_items)
push_items = max_push; push_items = max_push;
......
...@@ -306,13 +306,13 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -306,13 +306,13 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
int bit; int bit;
int ret; int ret;
int full_search = 0; int full_search = 0;
int factor = 8; int factor = 10;
block_group_cache = &info->block_group_cache; block_group_cache = &info->block_group_cache;
total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
if (!owner) if (!owner)
factor = 8; factor = 10;
bit = block_group_state_bits(data); bit = block_group_state_bits(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