diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 35 |
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; |