Skip to content

Commit

Permalink
Btrfs: Fix balance_level to free the middle block if there is room in…
Browse files Browse the repository at this point in the history
… 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: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason committed Sep 25, 2008
1 parent 971a1f6 commit bce4eae
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
35 changes: 28 additions & 7 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ static int balance_level(struct btrfs_trans_handle *trans,
/* first, try to make some room in the middle buffer */
if (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)
ret = wret;
if (btrfs_header_nritems(mid) < 2)
Expand Down Expand Up @@ -844,6 +844,11 @@ static int balance_level(struct btrfs_trans_handle *trans,
ret = wret;
goto enospc;
}
if (wret == 1) {
wret = push_node_left(trans, root, left, mid, 1);
if (wret < 0)
ret = wret;
}
BUG_ON(wret == 1);
}
if (btrfs_header_nritems(mid) == 0) {
Expand Down Expand Up @@ -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(dst) != trans->transid);

if (!empty && src_nritems <= 2)
if (!empty && src_nritems <= 8)
return 1;

if (push_items <= 0) {
return 1;
}

if (empty)
if (empty) {
push_items = min(src_nritems, push_items);
else
push_items = min(src_nritems - 2, push_items);
if (push_items < src_nritems) {
/* 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,
btrfs_node_key_ptr_offset(dst_nritems),
Expand Down Expand Up @@ -1308,13 +1323,19 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
src_nritems = btrfs_header_nritems(src);
dst_nritems = btrfs_header_nritems(dst);
push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
if (push_items <= 0)
if (push_items <= 0) {
return 1;
}

if (src_nritems < 4) {
return 1;
}

max_push = src_nritems / 2 + 1;
/* don't try to empty the node */
if (max_push >= src_nritems)
if (max_push >= src_nritems) {
return 1;
}

if (max_push < push_items)
push_items = max_push;
Expand Down
4 changes: 2 additions & 2 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,13 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
int bit;
int ret;
int full_search = 0;
int factor = 8;
int factor = 10;

block_group_cache = &info->block_group_cache;
total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);

if (!owner)
factor = 8;
factor = 10;

bit = block_group_state_bits(data);

Expand Down

0 comments on commit bce4eae

Please sign in to comment.