diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
| -rw-r--r-- | fs/btrfs/ctree.c | 243 |
1 files changed, 183 insertions, 60 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index c4bc570a396e..c3df14ce2cc2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | #include "ctree.h" | 21 | #include "ctree.h" |
| 21 | #include "disk-io.h" | 22 | #include "disk-io.h" |
| 22 | #include "transaction.h" | 23 | #include "transaction.h" |
| @@ -279,7 +280,8 @@ int btrfs_block_can_be_shared(struct btrfs_root *root, | |||
| 279 | static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | 280 | static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, |
| 280 | struct btrfs_root *root, | 281 | struct btrfs_root *root, |
| 281 | struct extent_buffer *buf, | 282 | struct extent_buffer *buf, |
| 282 | struct extent_buffer *cow) | 283 | struct extent_buffer *cow, |
| 284 | int *last_ref) | ||
| 283 | { | 285 | { |
| 284 | u64 refs; | 286 | u64 refs; |
| 285 | u64 owner; | 287 | u64 owner; |
| @@ -365,6 +367,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | |||
| 365 | BUG_ON(ret); | 367 | BUG_ON(ret); |
| 366 | } | 368 | } |
| 367 | clean_tree_block(trans, root, buf); | 369 | clean_tree_block(trans, root, buf); |
| 370 | *last_ref = 1; | ||
| 368 | } | 371 | } |
| 369 | return 0; | 372 | return 0; |
| 370 | } | 373 | } |
| @@ -391,6 +394,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 391 | struct btrfs_disk_key disk_key; | 394 | struct btrfs_disk_key disk_key; |
| 392 | struct extent_buffer *cow; | 395 | struct extent_buffer *cow; |
| 393 | int level; | 396 | int level; |
| 397 | int last_ref = 0; | ||
| 394 | int unlock_orig = 0; | 398 | int unlock_orig = 0; |
| 395 | u64 parent_start; | 399 | u64 parent_start; |
| 396 | 400 | ||
| @@ -441,7 +445,10 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 441 | (unsigned long)btrfs_header_fsid(cow), | 445 | (unsigned long)btrfs_header_fsid(cow), |
| 442 | BTRFS_FSID_SIZE); | 446 | BTRFS_FSID_SIZE); |
| 443 | 447 | ||
| 444 | update_ref_for_cow(trans, root, buf, cow); | 448 | update_ref_for_cow(trans, root, buf, cow, &last_ref); |
| 449 | |||
| 450 | if (root->ref_cows) | ||
| 451 | btrfs_reloc_cow_block(trans, root, buf, cow); | ||
| 445 | 452 | ||
| 446 | if (buf == root->node) { | 453 | if (buf == root->node) { |
| 447 | WARN_ON(parent && parent != buf); | 454 | WARN_ON(parent && parent != buf); |
| @@ -456,8 +463,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 456 | extent_buffer_get(cow); | 463 | extent_buffer_get(cow); |
| 457 | spin_unlock(&root->node_lock); | 464 | spin_unlock(&root->node_lock); |
| 458 | 465 | ||
| 459 | btrfs_free_tree_block(trans, root, buf->start, buf->len, | 466 | btrfs_free_tree_block(trans, root, buf, parent_start, |
| 460 | parent_start, root->root_key.objectid, level); | 467 | last_ref); |
| 461 | free_extent_buffer(buf); | 468 | free_extent_buffer(buf); |
| 462 | add_root_to_dirty_list(root); | 469 | add_root_to_dirty_list(root); |
| 463 | } else { | 470 | } else { |
| @@ -472,8 +479,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 472 | btrfs_set_node_ptr_generation(parent, parent_slot, | 479 | btrfs_set_node_ptr_generation(parent, parent_slot, |
| 473 | trans->transid); | 480 | trans->transid); |
| 474 | btrfs_mark_buffer_dirty(parent); | 481 | btrfs_mark_buffer_dirty(parent); |
| 475 | btrfs_free_tree_block(trans, root, buf->start, buf->len, | 482 | btrfs_free_tree_block(trans, root, buf, parent_start, |
| 476 | parent_start, root->root_key.objectid, level); | 483 | last_ref); |
| 477 | } | 484 | } |
| 478 | if (unlock_orig) | 485 | if (unlock_orig) |
| 479 | btrfs_tree_unlock(buf); | 486 | btrfs_tree_unlock(buf); |
| @@ -948,6 +955,22 @@ int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key, | |||
| 948 | return bin_search(eb, key, level, slot); | 955 | return bin_search(eb, key, level, slot); |
| 949 | } | 956 | } |
| 950 | 957 | ||
| 958 | static void root_add_used(struct btrfs_root *root, u32 size) | ||
| 959 | { | ||
| 960 | spin_lock(&root->accounting_lock); | ||
| 961 | btrfs_set_root_used(&root->root_item, | ||
| 962 | btrfs_root_used(&root->root_item) + size); | ||
| 963 | spin_unlock(&root->accounting_lock); | ||
| 964 | } | ||
| 965 | |||
| 966 | static void root_sub_used(struct btrfs_root *root, u32 size) | ||
| 967 | { | ||
| 968 | spin_lock(&root->accounting_lock); | ||
| 969 | btrfs_set_root_used(&root->root_item, | ||
| 970 | btrfs_root_used(&root->root_item) - size); | ||
| 971 | spin_unlock(&root->accounting_lock); | ||
| 972 | } | ||
| 973 | |||
| 951 | /* given a node and slot number, this reads the blocks it points to. The | 974 | /* given a node and slot number, this reads the blocks it points to. The |
| 952 | * extent buffer is returned with a reference taken (but unlocked). | 975 | * extent buffer is returned with a reference taken (but unlocked). |
| 953 | * NULL is returned on error. | 976 | * NULL is returned on error. |
| @@ -1018,7 +1041,11 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1018 | btrfs_tree_lock(child); | 1041 | btrfs_tree_lock(child); |
| 1019 | btrfs_set_lock_blocking(child); | 1042 | btrfs_set_lock_blocking(child); |
| 1020 | ret = btrfs_cow_block(trans, root, child, mid, 0, &child); | 1043 | ret = btrfs_cow_block(trans, root, child, mid, 0, &child); |
| 1021 | BUG_ON(ret); | 1044 | if (ret) { |
| 1045 | btrfs_tree_unlock(child); | ||
| 1046 | free_extent_buffer(child); | ||
| 1047 | goto enospc; | ||
| 1048 | } | ||
| 1022 | 1049 | ||
| 1023 | spin_lock(&root->node_lock); | 1050 | spin_lock(&root->node_lock); |
| 1024 | root->node = child; | 1051 | root->node = child; |
| @@ -1033,11 +1060,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1033 | btrfs_tree_unlock(mid); | 1060 | btrfs_tree_unlock(mid); |
| 1034 | /* once for the path */ | 1061 | /* once for the path */ |
| 1035 | free_extent_buffer(mid); | 1062 | free_extent_buffer(mid); |
| 1036 | ret = btrfs_free_tree_block(trans, root, mid->start, mid->len, | 1063 | |
| 1037 | 0, root->root_key.objectid, level); | 1064 | root_sub_used(root, mid->len); |
| 1065 | btrfs_free_tree_block(trans, root, mid, 0, 1); | ||
| 1038 | /* once for the root ptr */ | 1066 | /* once for the root ptr */ |
| 1039 | free_extent_buffer(mid); | 1067 | free_extent_buffer(mid); |
| 1040 | return ret; | 1068 | return 0; |
| 1041 | } | 1069 | } |
| 1042 | if (btrfs_header_nritems(mid) > | 1070 | if (btrfs_header_nritems(mid) > |
| 1043 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) | 1071 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) |
| @@ -1087,23 +1115,16 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1087 | if (wret < 0 && wret != -ENOSPC) | 1115 | if (wret < 0 && wret != -ENOSPC) |
| 1088 | ret = wret; | 1116 | ret = wret; |
| 1089 | if (btrfs_header_nritems(right) == 0) { | 1117 | if (btrfs_header_nritems(right) == 0) { |
| 1090 | u64 bytenr = right->start; | ||
| 1091 | u32 blocksize = right->len; | ||
| 1092 | |||
| 1093 | clean_tree_block(trans, root, right); | 1118 | clean_tree_block(trans, root, right); |
| 1094 | btrfs_tree_unlock(right); | 1119 | btrfs_tree_unlock(right); |
| 1095 | free_extent_buffer(right); | ||
| 1096 | right = NULL; | ||
| 1097 | wret = del_ptr(trans, root, path, level + 1, pslot + | 1120 | wret = del_ptr(trans, root, path, level + 1, pslot + |
| 1098 | 1); | 1121 | 1); |
| 1099 | if (wret) | 1122 | if (wret) |
| 1100 | ret = wret; | 1123 | ret = wret; |
| 1101 | wret = btrfs_free_tree_block(trans, root, | 1124 | root_sub_used(root, right->len); |
| 1102 | bytenr, blocksize, 0, | 1125 | btrfs_free_tree_block(trans, root, right, 0, 1); |
| 1103 | root->root_key.objectid, | 1126 | free_extent_buffer(right); |
| 1104 | level); | 1127 | right = NULL; |
| 1105 | if (wret) | ||
| 1106 | ret = wret; | ||
| 1107 | } else { | 1128 | } else { |
| 1108 | struct btrfs_disk_key right_key; | 1129 | struct btrfs_disk_key right_key; |
| 1109 | btrfs_node_key(right, &right_key, 0); | 1130 | btrfs_node_key(right, &right_key, 0); |
| @@ -1135,21 +1156,15 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1135 | BUG_ON(wret == 1); | 1156 | BUG_ON(wret == 1); |
| 1136 | } | 1157 | } |
| 1137 | if (btrfs_header_nritems(mid) == 0) { | 1158 | if (btrfs_header_nritems(mid) == 0) { |
| 1138 | /* we've managed to empty the middle node, drop it */ | ||
| 1139 | u64 bytenr = mid->start; | ||
| 1140 | u32 blocksize = mid->len; | ||
| 1141 | |||
| 1142 | clean_tree_block(trans, root, mid); | 1159 | clean_tree_block(trans, root, mid); |
| 1143 | btrfs_tree_unlock(mid); | 1160 | btrfs_tree_unlock(mid); |
| 1144 | free_extent_buffer(mid); | ||
| 1145 | mid = NULL; | ||
| 1146 | wret = del_ptr(trans, root, path, level + 1, pslot); | 1161 | wret = del_ptr(trans, root, path, level + 1, pslot); |
| 1147 | if (wret) | 1162 | if (wret) |
| 1148 | ret = wret; | 1163 | ret = wret; |
| 1149 | wret = btrfs_free_tree_block(trans, root, bytenr, blocksize, | 1164 | root_sub_used(root, mid->len); |
| 1150 | 0, root->root_key.objectid, level); | 1165 | btrfs_free_tree_block(trans, root, mid, 0, 1); |
| 1151 | if (wret) | 1166 | free_extent_buffer(mid); |
| 1152 | ret = wret; | 1167 | mid = NULL; |
| 1153 | } else { | 1168 | } else { |
| 1154 | /* update the parent key to reflect our changes */ | 1169 | /* update the parent key to reflect our changes */ |
| 1155 | struct btrfs_disk_key mid_key; | 1170 | struct btrfs_disk_key mid_key; |
| @@ -1589,7 +1604,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
| 1589 | btrfs_release_path(NULL, p); | 1604 | btrfs_release_path(NULL, p); |
| 1590 | 1605 | ||
| 1591 | ret = -EAGAIN; | 1606 | ret = -EAGAIN; |
| 1592 | tmp = read_tree_block(root, blocknr, blocksize, gen); | 1607 | tmp = read_tree_block(root, blocknr, blocksize, 0); |
| 1593 | if (tmp) { | 1608 | if (tmp) { |
| 1594 | /* | 1609 | /* |
| 1595 | * If the read above didn't mark this buffer up to date, | 1610 | * If the read above didn't mark this buffer up to date, |
| @@ -1739,7 +1754,6 @@ again: | |||
| 1739 | p->nodes[level + 1], | 1754 | p->nodes[level + 1], |
| 1740 | p->slots[level + 1], &b); | 1755 | p->slots[level + 1], &b); |
| 1741 | if (err) { | 1756 | if (err) { |
| 1742 | free_extent_buffer(b); | ||
| 1743 | ret = err; | 1757 | ret = err; |
| 1744 | goto done; | 1758 | goto done; |
| 1745 | } | 1759 | } |
| @@ -2075,6 +2089,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, | |||
| 2075 | if (IS_ERR(c)) | 2089 | if (IS_ERR(c)) |
| 2076 | return PTR_ERR(c); | 2090 | return PTR_ERR(c); |
| 2077 | 2091 | ||
| 2092 | root_add_used(root, root->nodesize); | ||
| 2093 | |||
| 2078 | memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header)); | 2094 | memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header)); |
| 2079 | btrfs_set_header_nritems(c, 1); | 2095 | btrfs_set_header_nritems(c, 1); |
| 2080 | btrfs_set_header_level(c, level); | 2096 | btrfs_set_header_level(c, level); |
| @@ -2133,6 +2149,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 2133 | int nritems; | 2149 | int nritems; |
| 2134 | 2150 | ||
| 2135 | BUG_ON(!path->nodes[level]); | 2151 | BUG_ON(!path->nodes[level]); |
| 2152 | btrfs_assert_tree_locked(path->nodes[level]); | ||
| 2136 | lower = path->nodes[level]; | 2153 | lower = path->nodes[level]; |
| 2137 | nritems = btrfs_header_nritems(lower); | 2154 | nritems = btrfs_header_nritems(lower); |
| 2138 | BUG_ON(slot > nritems); | 2155 | BUG_ON(slot > nritems); |
| @@ -2201,6 +2218,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
| 2201 | if (IS_ERR(split)) | 2218 | if (IS_ERR(split)) |
| 2202 | return PTR_ERR(split); | 2219 | return PTR_ERR(split); |
| 2203 | 2220 | ||
| 2221 | root_add_used(root, root->nodesize); | ||
| 2222 | |||
| 2204 | memset_extent_buffer(split, 0, 0, sizeof(struct btrfs_header)); | 2223 | memset_extent_buffer(split, 0, 0, sizeof(struct btrfs_header)); |
| 2205 | btrfs_set_header_level(split, btrfs_header_level(c)); | 2224 | btrfs_set_header_level(split, btrfs_header_level(c)); |
| 2206 | btrfs_set_header_bytenr(split, split->start); | 2225 | btrfs_set_header_bytenr(split, split->start); |
| @@ -2285,12 +2304,17 @@ noinline int btrfs_leaf_free_space(struct btrfs_root *root, | |||
| 2285 | return ret; | 2304 | return ret; |
| 2286 | } | 2305 | } |
| 2287 | 2306 | ||
| 2307 | /* | ||
| 2308 | * min slot controls the lowest index we're willing to push to the | ||
| 2309 | * right. We'll push up to and including min_slot, but no lower | ||
| 2310 | */ | ||
| 2288 | static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, | 2311 | static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, |
| 2289 | struct btrfs_root *root, | 2312 | struct btrfs_root *root, |
| 2290 | struct btrfs_path *path, | 2313 | struct btrfs_path *path, |
| 2291 | int data_size, int empty, | 2314 | int data_size, int empty, |
| 2292 | struct extent_buffer *right, | 2315 | struct extent_buffer *right, |
| 2293 | int free_space, u32 left_nritems) | 2316 | int free_space, u32 left_nritems, |
| 2317 | u32 min_slot) | ||
| 2294 | { | 2318 | { |
| 2295 | struct extent_buffer *left = path->nodes[0]; | 2319 | struct extent_buffer *left = path->nodes[0]; |
| 2296 | struct extent_buffer *upper = path->nodes[1]; | 2320 | struct extent_buffer *upper = path->nodes[1]; |
| @@ -2308,7 +2332,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, | |||
| 2308 | if (empty) | 2332 | if (empty) |
| 2309 | nr = 0; | 2333 | nr = 0; |
| 2310 | else | 2334 | else |
| 2311 | nr = 1; | 2335 | nr = max_t(u32, 1, min_slot); |
| 2312 | 2336 | ||
| 2313 | if (path->slots[0] >= left_nritems) | 2337 | if (path->slots[0] >= left_nritems) |
| 2314 | push_space += data_size; | 2338 | push_space += data_size; |
| @@ -2414,6 +2438,9 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, | |||
| 2414 | 2438 | ||
| 2415 | if (left_nritems) | 2439 | if (left_nritems) |
| 2416 | btrfs_mark_buffer_dirty(left); | 2440 | btrfs_mark_buffer_dirty(left); |
| 2441 | else | ||
| 2442 | clean_tree_block(trans, root, left); | ||
| 2443 | |||
| 2417 | btrfs_mark_buffer_dirty(right); | 2444 | btrfs_mark_buffer_dirty(right); |
| 2418 | 2445 | ||
| 2419 | btrfs_item_key(right, &disk_key, 0); | 2446 | btrfs_item_key(right, &disk_key, 0); |
| @@ -2447,10 +2474,14 @@ out_unlock: | |||
| 2447 | * | 2474 | * |
| 2448 | * returns 1 if the push failed because the other node didn't have enough | 2475 | * returns 1 if the push failed because the other node didn't have enough |
| 2449 | * room, 0 if everything worked out and < 0 if there were major errors. | 2476 | * room, 0 if everything worked out and < 0 if there were major errors. |
| 2477 | * | ||
| 2478 | * this will push starting from min_slot to the end of the leaf. It won't | ||
| 2479 | * push any slot lower than min_slot | ||
| 2450 | */ | 2480 | */ |
| 2451 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | 2481 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root |
| 2452 | *root, struct btrfs_path *path, int data_size, | 2482 | *root, struct btrfs_path *path, |
| 2453 | int empty) | 2483 | int min_data_size, int data_size, |
| 2484 | int empty, u32 min_slot) | ||
| 2454 | { | 2485 | { |
| 2455 | struct extent_buffer *left = path->nodes[0]; | 2486 | struct extent_buffer *left = path->nodes[0]; |
| 2456 | struct extent_buffer *right; | 2487 | struct extent_buffer *right; |
| @@ -2492,8 +2523,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 2492 | if (left_nritems == 0) | 2523 | if (left_nritems == 0) |
| 2493 | goto out_unlock; | 2524 | goto out_unlock; |
| 2494 | 2525 | ||
| 2495 | return __push_leaf_right(trans, root, path, data_size, empty, | 2526 | return __push_leaf_right(trans, root, path, min_data_size, empty, |
| 2496 | right, free_space, left_nritems); | 2527 | right, free_space, left_nritems, min_slot); |
| 2497 | out_unlock: | 2528 | out_unlock: |
| 2498 | btrfs_tree_unlock(right); | 2529 | btrfs_tree_unlock(right); |
| 2499 | free_extent_buffer(right); | 2530 | free_extent_buffer(right); |
| @@ -2503,12 +2534,17 @@ out_unlock: | |||
| 2503 | /* | 2534 | /* |
| 2504 | * push some data in the path leaf to the left, trying to free up at | 2535 | * push some data in the path leaf to the left, trying to free up at |
| 2505 | * least data_size bytes. returns zero if the push worked, nonzero otherwise | 2536 | * least data_size bytes. returns zero if the push worked, nonzero otherwise |
| 2537 | * | ||
| 2538 | * max_slot can put a limit on how far into the leaf we'll push items. The | ||
| 2539 | * item at 'max_slot' won't be touched. Use (u32)-1 to make us do all the | ||
| 2540 | * items | ||
| 2506 | */ | 2541 | */ |
| 2507 | static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, | 2542 | static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, |
| 2508 | struct btrfs_root *root, | 2543 | struct btrfs_root *root, |
| 2509 | struct btrfs_path *path, int data_size, | 2544 | struct btrfs_path *path, int data_size, |
| 2510 | int empty, struct extent_buffer *left, | 2545 | int empty, struct extent_buffer *left, |
| 2511 | int free_space, int right_nritems) | 2546 | int free_space, u32 right_nritems, |
| 2547 | u32 max_slot) | ||
| 2512 | { | 2548 | { |
| 2513 | struct btrfs_disk_key disk_key; | 2549 | struct btrfs_disk_key disk_key; |
| 2514 | struct extent_buffer *right = path->nodes[0]; | 2550 | struct extent_buffer *right = path->nodes[0]; |
| @@ -2527,9 +2563,9 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, | |||
| 2527 | slot = path->slots[1]; | 2563 | slot = path->slots[1]; |
| 2528 | 2564 | ||
| 2529 | if (empty) | 2565 | if (empty) |
| 2530 | nr = right_nritems; | 2566 | nr = min(right_nritems, max_slot); |
| 2531 | else | 2567 | else |
| 2532 | nr = right_nritems - 1; | 2568 | nr = min(right_nritems - 1, max_slot); |
| 2533 | 2569 | ||
| 2534 | for (i = 0; i < nr; i++) { | 2570 | for (i = 0; i < nr; i++) { |
| 2535 | item = btrfs_item_nr(right, i); | 2571 | item = btrfs_item_nr(right, i); |
| @@ -2659,6 +2695,8 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, | |||
| 2659 | btrfs_mark_buffer_dirty(left); | 2695 | btrfs_mark_buffer_dirty(left); |
| 2660 | if (right_nritems) | 2696 | if (right_nritems) |
| 2661 | btrfs_mark_buffer_dirty(right); | 2697 | btrfs_mark_buffer_dirty(right); |
| 2698 | else | ||
| 2699 | clean_tree_block(trans, root, right); | ||
| 2662 | 2700 | ||
| 2663 | btrfs_item_key(right, &disk_key, 0); | 2701 | btrfs_item_key(right, &disk_key, 0); |
| 2664 | wret = fixup_low_keys(trans, root, path, &disk_key, 1); | 2702 | wret = fixup_low_keys(trans, root, path, &disk_key, 1); |
| @@ -2668,8 +2706,6 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, | |||
| 2668 | /* then fixup the leaf pointer in the path */ | 2706 | /* then fixup the leaf pointer in the path */ |
| 2669 | if (path->slots[0] < push_items) { | 2707 | if (path->slots[0] < push_items) { |
| 2670 | path->slots[0] += old_left_nritems; | 2708 | path->slots[0] += old_left_nritems; |
| 2671 | if (btrfs_header_nritems(path->nodes[0]) == 0) | ||
| 2672 | clean_tree_block(trans, root, path->nodes[0]); | ||
| 2673 | btrfs_tree_unlock(path->nodes[0]); | 2709 | btrfs_tree_unlock(path->nodes[0]); |
| 2674 | free_extent_buffer(path->nodes[0]); | 2710 | free_extent_buffer(path->nodes[0]); |
| 2675 | path->nodes[0] = left; | 2711 | path->nodes[0] = left; |
| @@ -2690,10 +2726,14 @@ out: | |||
| 2690 | /* | 2726 | /* |
| 2691 | * push some data in the path leaf to the left, trying to free up at | 2727 | * push some data in the path leaf to the left, trying to free up at |
| 2692 | * least data_size bytes. returns zero if the push worked, nonzero otherwise | 2728 | * least data_size bytes. returns zero if the push worked, nonzero otherwise |
| 2729 | * | ||
| 2730 | * max_slot can put a limit on how far into the leaf we'll push items. The | ||
| 2731 | * item at 'max_slot' won't be touched. Use (u32)-1 to make us push all the | ||
| 2732 | * items | ||
| 2693 | */ | 2733 | */ |
| 2694 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | 2734 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root |
| 2695 | *root, struct btrfs_path *path, int data_size, | 2735 | *root, struct btrfs_path *path, int min_data_size, |
| 2696 | int empty) | 2736 | int data_size, int empty, u32 max_slot) |
| 2697 | { | 2737 | { |
| 2698 | struct extent_buffer *right = path->nodes[0]; | 2738 | struct extent_buffer *right = path->nodes[0]; |
| 2699 | struct extent_buffer *left; | 2739 | struct extent_buffer *left; |
| @@ -2739,8 +2779,9 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 2739 | goto out; | 2779 | goto out; |
| 2740 | } | 2780 | } |
| 2741 | 2781 | ||
| 2742 | return __push_leaf_left(trans, root, path, data_size, | 2782 | return __push_leaf_left(trans, root, path, min_data_size, |
| 2743 | empty, left, free_space, right_nritems); | 2783 | empty, left, free_space, right_nritems, |
| 2784 | max_slot); | ||
| 2744 | out: | 2785 | out: |
| 2745 | btrfs_tree_unlock(left); | 2786 | btrfs_tree_unlock(left); |
| 2746 | free_extent_buffer(left); | 2787 | free_extent_buffer(left); |
| @@ -2833,6 +2874,64 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans, | |||
| 2833 | } | 2874 | } |
| 2834 | 2875 | ||
| 2835 | /* | 2876 | /* |
| 2877 | * double splits happen when we need to insert a big item in the middle | ||
| 2878 | * of a leaf. A double split can leave us with 3 mostly empty leaves: | ||
| 2879 | * leaf: [ slots 0 - N] [ our target ] [ N + 1 - total in leaf ] | ||
| 2880 | * A B C | ||
| 2881 | * | ||
| 2882 | * We avoid this by trying to push the items on either side of our target | ||
| 2883 | * into the adjacent leaves. If all goes well we can avoid the double split | ||
| 2884 | * completely. | ||
| 2885 | */ | ||
| 2886 | static noinline int push_for_double_split(struct btrfs_trans_handle *trans, | ||
| 2887 | struct btrfs_root *root, | ||
| 2888 | struct btrfs_path *path, | ||
| 2889 | int data_size) | ||
| 2890 | { | ||
| 2891 | int ret; | ||
| 2892 | int progress = 0; | ||
| 2893 | int slot; | ||
| 2894 | u32 nritems; | ||
| 2895 | |||
| 2896 | slot = path->slots[0]; | ||
| 2897 | |||
| 2898 | /* | ||
| 2899 | * try to push all the items after our slot into the | ||
| 2900 | * right leaf | ||
| 2901 | */ | ||
| 2902 | ret = push_leaf_right(trans, root, path, 1, data_size, 0, slot); | ||
| 2903 | if (ret < 0) | ||
| 2904 | return ret; | ||
| 2905 | |||
| 2906 | if (ret == 0) | ||
| 2907 | progress++; | ||
| 2908 | |||
| 2909 | nritems = btrfs_header_nritems(path->nodes[0]); | ||
| 2910 | /* | ||
| 2911 | * our goal is to get our slot at the start or end of a leaf. If | ||
| 2912 | * we've done so we're done | ||
| 2913 | */ | ||
| 2914 | if (path->slots[0] == 0 || path->slots[0] == nritems) | ||
| 2915 | return 0; | ||
| 2916 | |||
| 2917 | if (btrfs_leaf_free_space(root, path->nodes[0]) >= data_size) | ||
| 2918 | return 0; | ||
| 2919 | |||
| 2920 | /* try to push all the items before our slot into the next leaf */ | ||
| 2921 | slot = path->slots[0]; | ||
| 2922 | ret = push_leaf_left(trans, root, path, 1, data_size, 0, slot); | ||
| 2923 | if (ret < 0) | ||
| 2924 | return ret; | ||
| 2925 | |||
| 2926 | if (ret == 0) | ||
| 2927 | progress++; | ||
| 2928 | |||
| 2929 | if (progress) | ||
| 2930 | return 0; | ||
| 2931 | return 1; | ||
| 2932 | } | ||
| 2933 | |||
| 2934 | /* | ||
| 2836 | * split the path's leaf in two, making sure there is at least data_size | 2935 | * split the path's leaf in two, making sure there is at least data_size |
| 2837 | * available for the resulting leaf level of the path. | 2936 | * available for the resulting leaf level of the path. |
| 2838 | * | 2937 | * |
| @@ -2854,6 +2953,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
| 2854 | int wret; | 2953 | int wret; |
| 2855 | int split; | 2954 | int split; |
| 2856 | int num_doubles = 0; | 2955 | int num_doubles = 0; |
| 2956 | int tried_avoid_double = 0; | ||
| 2857 | 2957 | ||
| 2858 | l = path->nodes[0]; | 2958 | l = path->nodes[0]; |
| 2859 | slot = path->slots[0]; | 2959 | slot = path->slots[0]; |
| @@ -2862,12 +2962,14 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
| 2862 | return -EOVERFLOW; | 2962 | return -EOVERFLOW; |
| 2863 | 2963 | ||
| 2864 | /* first try to make some room by pushing left and right */ | 2964 | /* first try to make some room by pushing left and right */ |
| 2865 | if (data_size && ins_key->type != BTRFS_DIR_ITEM_KEY) { | 2965 | if (data_size) { |
| 2866 | wret = push_leaf_right(trans, root, path, data_size, 0); | 2966 | wret = push_leaf_right(trans, root, path, data_size, |
| 2967 | data_size, 0, 0); | ||
| 2867 | if (wret < 0) | 2968 | if (wret < 0) |
| 2868 | return wret; | 2969 | return wret; |
| 2869 | if (wret) { | 2970 | if (wret) { |
| 2870 | wret = push_leaf_left(trans, root, path, data_size, 0); | 2971 | wret = push_leaf_left(trans, root, path, data_size, |
| 2972 | data_size, 0, (u32)-1); | ||
| 2871 | if (wret < 0) | 2973 | if (wret < 0) |
| 2872 | return wret; | 2974 | return wret; |
| 2873 | } | 2975 | } |
| @@ -2901,6 +3003,8 @@ again: | |||
| 2901 | if (mid != nritems && | 3003 | if (mid != nritems && |
| 2902 | leaf_space_used(l, mid, nritems - mid) + | 3004 | leaf_space_used(l, mid, nritems - mid) + |
| 2903 | data_size > BTRFS_LEAF_DATA_SIZE(root)) { | 3005 | data_size > BTRFS_LEAF_DATA_SIZE(root)) { |
| 3006 | if (data_size && !tried_avoid_double) | ||
| 3007 | goto push_for_double; | ||
| 2904 | split = 2; | 3008 | split = 2; |
| 2905 | } | 3009 | } |
| 2906 | } | 3010 | } |
| @@ -2917,6 +3021,8 @@ again: | |||
| 2917 | if (mid != nritems && | 3021 | if (mid != nritems && |
| 2918 | leaf_space_used(l, mid, nritems - mid) + | 3022 | leaf_space_used(l, mid, nritems - mid) + |
| 2919 | data_size > BTRFS_LEAF_DATA_SIZE(root)) { | 3023 | data_size > BTRFS_LEAF_DATA_SIZE(root)) { |
| 3024 | if (data_size && !tried_avoid_double) | ||
| 3025 | goto push_for_double; | ||
| 2920 | split = 2 ; | 3026 | split = 2 ; |
| 2921 | } | 3027 | } |
| 2922 | } | 3028 | } |
| @@ -2931,10 +3037,10 @@ again: | |||
| 2931 | right = btrfs_alloc_free_block(trans, root, root->leafsize, 0, | 3037 | right = btrfs_alloc_free_block(trans, root, root->leafsize, 0, |
| 2932 | root->root_key.objectid, | 3038 | root->root_key.objectid, |
| 2933 | &disk_key, 0, l->start, 0); | 3039 | &disk_key, 0, l->start, 0); |
| 2934 | if (IS_ERR(right)) { | 3040 | if (IS_ERR(right)) |
| 2935 | BUG_ON(1); | ||
| 2936 | return PTR_ERR(right); | 3041 | return PTR_ERR(right); |
| 2937 | } | 3042 | |
| 3043 | root_add_used(root, root->leafsize); | ||
| 2938 | 3044 | ||
| 2939 | memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); | 3045 | memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); |
| 2940 | btrfs_set_header_bytenr(right, right->start); | 3046 | btrfs_set_header_bytenr(right, right->start); |
| @@ -2997,6 +3103,13 @@ again: | |||
| 2997 | } | 3103 | } |
| 2998 | 3104 | ||
| 2999 | return ret; | 3105 | return ret; |
| 3106 | |||
| 3107 | push_for_double: | ||
| 3108 | push_for_double_split(trans, root, path, data_size); | ||
| 3109 | tried_avoid_double = 1; | ||
| 3110 | if (btrfs_leaf_free_space(root, path->nodes[0]) >= data_size) | ||
| 3111 | return 0; | ||
| 3112 | goto again; | ||
| 3000 | } | 3113 | } |
| 3001 | 3114 | ||
| 3002 | static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, | 3115 | static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, |
| @@ -3040,6 +3153,10 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, | |||
| 3040 | if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0])) | 3153 | if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0])) |
| 3041 | goto err; | 3154 | goto err; |
| 3042 | 3155 | ||
| 3156 | /* the leaf has changed, it now has room. return now */ | ||
| 3157 | if (btrfs_leaf_free_space(root, path->nodes[0]) >= ins_len) | ||
| 3158 | goto err; | ||
| 3159 | |||
| 3043 | if (key.type == BTRFS_EXTENT_DATA_KEY) { | 3160 | if (key.type == BTRFS_EXTENT_DATA_KEY) { |
| 3044 | fi = btrfs_item_ptr(leaf, path->slots[0], | 3161 | fi = btrfs_item_ptr(leaf, path->slots[0], |
| 3045 | struct btrfs_file_extent_item); | 3162 | struct btrfs_file_extent_item); |
| @@ -3049,7 +3166,8 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, | |||
| 3049 | 3166 | ||
| 3050 | btrfs_set_path_blocking(path); | 3167 | btrfs_set_path_blocking(path); |
| 3051 | ret = split_leaf(trans, root, &key, path, ins_len, 1); | 3168 | ret = split_leaf(trans, root, &key, path, ins_len, 1); |
| 3052 | BUG_ON(ret); | 3169 | if (ret) |
| 3170 | goto err; | ||
| 3053 | 3171 | ||
| 3054 | path->keep_locks = 0; | 3172 | path->keep_locks = 0; |
| 3055 | btrfs_unlock_up_safe(path, 1); | 3173 | btrfs_unlock_up_safe(path, 1); |
| @@ -3791,9 +3909,10 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, | |||
| 3791 | */ | 3909 | */ |
| 3792 | btrfs_unlock_up_safe(path, 0); | 3910 | btrfs_unlock_up_safe(path, 0); |
| 3793 | 3911 | ||
| 3794 | ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len, | 3912 | root_sub_used(root, leaf->len); |
| 3795 | 0, root->root_key.objectid, 0); | 3913 | |
| 3796 | return ret; | 3914 | btrfs_free_tree_block(trans, root, leaf, 0, 1); |
| 3915 | return 0; | ||
| 3797 | } | 3916 | } |
| 3798 | /* | 3917 | /* |
| 3799 | * delete the item at the leaf level in path. If that empties | 3918 | * delete the item at the leaf level in path. If that empties |
| @@ -3860,6 +3979,8 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 3860 | if (leaf == root->node) { | 3979 | if (leaf == root->node) { |
| 3861 | btrfs_set_header_level(leaf, 0); | 3980 | btrfs_set_header_level(leaf, 0); |
| 3862 | } else { | 3981 | } else { |
| 3982 | btrfs_set_path_blocking(path); | ||
| 3983 | clean_tree_block(trans, root, leaf); | ||
| 3863 | ret = btrfs_del_leaf(trans, root, path, leaf); | 3984 | ret = btrfs_del_leaf(trans, root, path, leaf); |
| 3864 | BUG_ON(ret); | 3985 | BUG_ON(ret); |
| 3865 | } | 3986 | } |
| @@ -3885,13 +4006,15 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 3885 | extent_buffer_get(leaf); | 4006 | extent_buffer_get(leaf); |
| 3886 | 4007 | ||
| 3887 | btrfs_set_path_blocking(path); | 4008 | btrfs_set_path_blocking(path); |
| 3888 | wret = push_leaf_left(trans, root, path, 1, 1); | 4009 | wret = push_leaf_left(trans, root, path, 1, 1, |
| 4010 | 1, (u32)-1); | ||
| 3889 | if (wret < 0 && wret != -ENOSPC) | 4011 | if (wret < 0 && wret != -ENOSPC) |
| 3890 | ret = wret; | 4012 | ret = wret; |
| 3891 | 4013 | ||
| 3892 | if (path->nodes[0] == leaf && | 4014 | if (path->nodes[0] == leaf && |
| 3893 | btrfs_header_nritems(leaf)) { | 4015 | btrfs_header_nritems(leaf)) { |
| 3894 | wret = push_leaf_right(trans, root, path, 1, 1); | 4016 | wret = push_leaf_right(trans, root, path, 1, |
| 4017 | 1, 1, 0); | ||
| 3895 | if (wret < 0 && wret != -ENOSPC) | 4018 | if (wret < 0 && wret != -ENOSPC) |
| 3896 | ret = wret; | 4019 | ret = wret; |
| 3897 | } | 4020 | } |
