aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 319f9f9bf8d4..29e5674b043d 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -789,7 +789,7 @@ static int balance_level(struct btrfs_trans_handle *trans,
789 /* first, try to make some room in the middle buffer */ 789 /* first, try to make some room in the middle buffer */
790 if (left) { 790 if (left) {
791 orig_slot += btrfs_header_nritems(left); 791 orig_slot += btrfs_header_nritems(left);
792 wret = push_node_left(trans, root, left, mid, 0); 792 wret = push_node_left(trans, root, left, mid, 1);
793 if (wret < 0) 793 if (wret < 0)
794 ret = wret; 794 ret = wret;
795 if (btrfs_header_nritems(mid) < 2) 795 if (btrfs_header_nritems(mid) < 2)
@@ -844,6 +844,11 @@ static int balance_level(struct btrfs_trans_handle *trans,
844 ret = wret; 844 ret = wret;
845 goto enospc; 845 goto enospc;
846 } 846 }
847 if (wret == 1) {
848 wret = push_node_left(trans, root, left, mid, 1);
849 if (wret < 0)
850 ret = wret;
851 }
847 BUG_ON(wret == 1); 852 BUG_ON(wret == 1);
848 } 853 }
849 if (btrfs_header_nritems(mid) == 0) { 854 if (btrfs_header_nritems(mid) == 0) {
@@ -1252,17 +1257,27 @@ static int push_node_left(struct btrfs_trans_handle *trans,
1252 WARN_ON(btrfs_header_generation(src) != trans->transid); 1257 WARN_ON(btrfs_header_generation(src) != trans->transid);
1253 WARN_ON(btrfs_header_generation(dst) != trans->transid); 1258 WARN_ON(btrfs_header_generation(dst) != trans->transid);
1254 1259
1255 if (!empty && src_nritems <= 2) 1260 if (!empty && src_nritems <= 8)
1256 return 1; 1261 return 1;
1257 1262
1258 if (push_items <= 0) { 1263 if (push_items <= 0) {
1259 return 1; 1264 return 1;
1260 } 1265 }
1261 1266
1262 if (empty) 1267 if (empty) {
1263 push_items = min(src_nritems, push_items); 1268 push_items = min(src_nritems, push_items);
1264 else 1269 if (push_items < src_nritems) {
1265 push_items = min(src_nritems - 2, push_items); 1270 /* leave at least 8 pointers in the node if
1271 * we aren't going to empty it
1272 */
1273 if (src_nritems - push_items < 8) {
1274 if (push_items <= 8)
1275 return 1;
1276 push_items -= 8;
1277 }
1278 }
1279 } else
1280 push_items = min(src_nritems - 8, push_items);
1266 1281
1267 copy_extent_buffer(dst, src, 1282 copy_extent_buffer(dst, src,
1268 btrfs_node_key_ptr_offset(dst_nritems), 1283 btrfs_node_key_ptr_offset(dst_nritems),
@@ -1308,13 +1323,19 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
1308 src_nritems = btrfs_header_nritems(src); 1323 src_nritems = btrfs_header_nritems(src);
1309 dst_nritems = btrfs_header_nritems(dst); 1324 dst_nritems = btrfs_header_nritems(dst);
1310 push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; 1325 push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems;
1311 if (push_items <= 0) 1326 if (push_items <= 0) {
1312 return 1; 1327 return 1;
1328 }
1329
1330 if (src_nritems < 4) {
1331 return 1;
1332 }
1313 1333
1314 max_push = src_nritems / 2 + 1; 1334 max_push = src_nritems / 2 + 1;
1315 /* don't try to empty the node */ 1335 /* don't try to empty the node */
1316 if (max_push >= src_nritems) 1336 if (max_push >= src_nritems) {
1317 return 1; 1337 return 1;
1338 }
1318 1339
1319 if (max_push < push_items) 1340 if (max_push < push_items)
1320 push_items = max_push; 1341 push_items = max_push;