diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 319f9f9bf8d457f1528c1186c96956c1bf1589dc..29e5674b043d09112b101a14f8ab26a06755bdec 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -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) @@ -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) { @@ -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), @@ -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; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index cc0d7f30c36b7be2b3d3f3796bae41d7b7f92a1d..c49592c5127afddff9e29aab00b9e87e9623c850 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -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);