diff options
| -rw-r--r-- | fs/btrfs/ctree.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 07c1a96aa4a8..69ce3f7deeef 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -38,7 +38,8 @@ static int balance_node_right(struct btrfs_trans_handle *trans, | |||
| 38 | struct extent_buffer *dst_buf, | 38 | struct extent_buffer *dst_buf, |
| 39 | struct extent_buffer *src_buf); | 39 | struct extent_buffer *src_buf); |
| 40 | static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 40 | static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 41 | struct btrfs_path *path, int level, int slot); | 41 | struct btrfs_path *path, int level, int slot, |
| 42 | int tree_mod_log); | ||
| 42 | static void tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, | 43 | static void tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, |
| 43 | struct extent_buffer *eb); | 44 | struct extent_buffer *eb); |
| 44 | struct extent_buffer *read_old_tree_block(struct btrfs_root *root, u64 bytenr, | 45 | struct extent_buffer *read_old_tree_block(struct btrfs_root *root, u64 bytenr, |
| @@ -1465,7 +1466,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1465 | if (btrfs_header_nritems(right) == 0) { | 1466 | if (btrfs_header_nritems(right) == 0) { |
| 1466 | clean_tree_block(trans, root, right); | 1467 | clean_tree_block(trans, root, right); |
| 1467 | btrfs_tree_unlock(right); | 1468 | btrfs_tree_unlock(right); |
| 1468 | del_ptr(trans, root, path, level + 1, pslot + 1); | 1469 | del_ptr(trans, root, path, level + 1, pslot + 1, 1); |
| 1469 | root_sub_used(root, right->len); | 1470 | root_sub_used(root, right->len); |
| 1470 | btrfs_free_tree_block(trans, root, right, 0, 1); | 1471 | btrfs_free_tree_block(trans, root, right, 0, 1); |
| 1471 | free_extent_buffer_stale(right); | 1472 | free_extent_buffer_stale(right); |
| @@ -1509,7 +1510,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1509 | if (btrfs_header_nritems(mid) == 0) { | 1510 | if (btrfs_header_nritems(mid) == 0) { |
| 1510 | clean_tree_block(trans, root, mid); | 1511 | clean_tree_block(trans, root, mid); |
| 1511 | btrfs_tree_unlock(mid); | 1512 | btrfs_tree_unlock(mid); |
| 1512 | del_ptr(trans, root, path, level + 1, pslot); | 1513 | del_ptr(trans, root, path, level + 1, pslot, 1); |
| 1513 | root_sub_used(root, mid->len); | 1514 | root_sub_used(root, mid->len); |
| 1514 | btrfs_free_tree_block(trans, root, mid, 0, 1); | 1515 | btrfs_free_tree_block(trans, root, mid, 0, 1); |
| 1515 | free_extent_buffer_stale(mid); | 1516 | free_extent_buffer_stale(mid); |
| @@ -2626,10 +2627,11 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, | |||
| 2626 | static void insert_ptr(struct btrfs_trans_handle *trans, | 2627 | static void insert_ptr(struct btrfs_trans_handle *trans, |
| 2627 | struct btrfs_root *root, struct btrfs_path *path, | 2628 | struct btrfs_root *root, struct btrfs_path *path, |
| 2628 | struct btrfs_disk_key *key, u64 bytenr, | 2629 | struct btrfs_disk_key *key, u64 bytenr, |
| 2629 | int slot, int level) | 2630 | int slot, int level, int tree_mod_log) |
| 2630 | { | 2631 | { |
| 2631 | struct extent_buffer *lower; | 2632 | struct extent_buffer *lower; |
| 2632 | int nritems; | 2633 | int nritems; |
| 2634 | int ret; | ||
| 2633 | 2635 | ||
| 2634 | BUG_ON(!path->nodes[level]); | 2636 | BUG_ON(!path->nodes[level]); |
| 2635 | btrfs_assert_tree_locked(path->nodes[level]); | 2637 | btrfs_assert_tree_locked(path->nodes[level]); |
| @@ -2638,11 +2640,19 @@ static void insert_ptr(struct btrfs_trans_handle *trans, | |||
| 2638 | BUG_ON(slot > nritems); | 2640 | BUG_ON(slot > nritems); |
| 2639 | BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(root)); | 2641 | BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(root)); |
| 2640 | if (slot != nritems) { | 2642 | if (slot != nritems) { |
| 2643 | if (tree_mod_log && level) | ||
| 2644 | tree_mod_log_eb_move(root->fs_info, lower, slot + 1, | ||
| 2645 | slot, nritems - slot); | ||
| 2641 | memmove_extent_buffer(lower, | 2646 | memmove_extent_buffer(lower, |
| 2642 | btrfs_node_key_ptr_offset(slot + 1), | 2647 | btrfs_node_key_ptr_offset(slot + 1), |
| 2643 | btrfs_node_key_ptr_offset(slot), | 2648 | btrfs_node_key_ptr_offset(slot), |
| 2644 | (nritems - slot) * sizeof(struct btrfs_key_ptr)); | 2649 | (nritems - slot) * sizeof(struct btrfs_key_ptr)); |
| 2645 | } | 2650 | } |
| 2651 | if (tree_mod_log && level) { | ||
| 2652 | ret = tree_mod_log_insert_key(root->fs_info, lower, slot, | ||
| 2653 | MOD_LOG_KEY_ADD); | ||
| 2654 | BUG_ON(ret < 0); | ||
| 2655 | } | ||
| 2646 | btrfs_set_node_key(lower, key, slot); | 2656 | btrfs_set_node_key(lower, key, slot); |
| 2647 | btrfs_set_node_blockptr(lower, slot, bytenr); | 2657 | btrfs_set_node_blockptr(lower, slot, bytenr); |
| 2648 | WARN_ON(trans->transid == 0); | 2658 | WARN_ON(trans->transid == 0); |
| @@ -2726,7 +2736,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
| 2726 | btrfs_mark_buffer_dirty(split); | 2736 | btrfs_mark_buffer_dirty(split); |
| 2727 | 2737 | ||
| 2728 | insert_ptr(trans, root, path, &disk_key, split->start, | 2738 | insert_ptr(trans, root, path, &disk_key, split->start, |
| 2729 | path->slots[level + 1] + 1, level + 1); | 2739 | path->slots[level + 1] + 1, level + 1, 1); |
| 2730 | 2740 | ||
| 2731 | if (path->slots[level] >= mid) { | 2741 | if (path->slots[level] >= mid) { |
| 2732 | path->slots[level] -= mid; | 2742 | path->slots[level] -= mid; |
| @@ -3263,7 +3273,7 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans, | |||
| 3263 | btrfs_set_header_nritems(l, mid); | 3273 | btrfs_set_header_nritems(l, mid); |
| 3264 | btrfs_item_key(right, &disk_key, 0); | 3274 | btrfs_item_key(right, &disk_key, 0); |
| 3265 | insert_ptr(trans, root, path, &disk_key, right->start, | 3275 | insert_ptr(trans, root, path, &disk_key, right->start, |
| 3266 | path->slots[1] + 1, 1); | 3276 | path->slots[1] + 1, 1, 0); |
| 3267 | 3277 | ||
| 3268 | btrfs_mark_buffer_dirty(right); | 3278 | btrfs_mark_buffer_dirty(right); |
| 3269 | btrfs_mark_buffer_dirty(l); | 3279 | btrfs_mark_buffer_dirty(l); |
| @@ -3470,7 +3480,7 @@ again: | |||
| 3470 | if (mid <= slot) { | 3480 | if (mid <= slot) { |
| 3471 | btrfs_set_header_nritems(right, 0); | 3481 | btrfs_set_header_nritems(right, 0); |
| 3472 | insert_ptr(trans, root, path, &disk_key, right->start, | 3482 | insert_ptr(trans, root, path, &disk_key, right->start, |
| 3473 | path->slots[1] + 1, 1); | 3483 | path->slots[1] + 1, 1, 0); |
| 3474 | btrfs_tree_unlock(path->nodes[0]); | 3484 | btrfs_tree_unlock(path->nodes[0]); |
| 3475 | free_extent_buffer(path->nodes[0]); | 3485 | free_extent_buffer(path->nodes[0]); |
| 3476 | path->nodes[0] = right; | 3486 | path->nodes[0] = right; |
| @@ -3479,7 +3489,7 @@ again: | |||
| 3479 | } else { | 3489 | } else { |
| 3480 | btrfs_set_header_nritems(right, 0); | 3490 | btrfs_set_header_nritems(right, 0); |
| 3481 | insert_ptr(trans, root, path, &disk_key, right->start, | 3491 | insert_ptr(trans, root, path, &disk_key, right->start, |
| 3482 | path->slots[1], 1); | 3492 | path->slots[1], 1, 0); |
| 3483 | btrfs_tree_unlock(path->nodes[0]); | 3493 | btrfs_tree_unlock(path->nodes[0]); |
| 3484 | free_extent_buffer(path->nodes[0]); | 3494 | free_extent_buffer(path->nodes[0]); |
| 3485 | path->nodes[0] = right; | 3495 | path->nodes[0] = right; |
| @@ -4191,19 +4201,31 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 4191 | * empty a node. | 4201 | * empty a node. |
| 4192 | */ | 4202 | */ |
| 4193 | static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 4203 | static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 4194 | struct btrfs_path *path, int level, int slot) | 4204 | struct btrfs_path *path, int level, int slot, |
| 4205 | int tree_mod_log) | ||
| 4195 | { | 4206 | { |
| 4196 | struct extent_buffer *parent = path->nodes[level]; | 4207 | struct extent_buffer *parent = path->nodes[level]; |
| 4197 | u32 nritems; | 4208 | u32 nritems; |
| 4209 | int ret; | ||
| 4198 | 4210 | ||
| 4199 | nritems = btrfs_header_nritems(parent); | 4211 | nritems = btrfs_header_nritems(parent); |
| 4200 | if (slot != nritems - 1) { | 4212 | if (slot != nritems - 1) { |
| 4213 | if (tree_mod_log && level) | ||
| 4214 | tree_mod_log_eb_move(root->fs_info, parent, slot, | ||
| 4215 | slot + 1, nritems - slot - 1); | ||
| 4201 | memmove_extent_buffer(parent, | 4216 | memmove_extent_buffer(parent, |
| 4202 | btrfs_node_key_ptr_offset(slot), | 4217 | btrfs_node_key_ptr_offset(slot), |
| 4203 | btrfs_node_key_ptr_offset(slot + 1), | 4218 | btrfs_node_key_ptr_offset(slot + 1), |
| 4204 | sizeof(struct btrfs_key_ptr) * | 4219 | sizeof(struct btrfs_key_ptr) * |
| 4205 | (nritems - slot - 1)); | 4220 | (nritems - slot - 1)); |
| 4206 | } | 4221 | } |
| 4222 | |||
| 4223 | if (tree_mod_log && level) { | ||
| 4224 | ret = tree_mod_log_insert_key(root->fs_info, parent, slot, | ||
| 4225 | MOD_LOG_KEY_REMOVE); | ||
| 4226 | BUG_ON(ret < 0); | ||
| 4227 | } | ||
| 4228 | |||
| 4207 | nritems--; | 4229 | nritems--; |
| 4208 | btrfs_set_header_nritems(parent, nritems); | 4230 | btrfs_set_header_nritems(parent, nritems); |
| 4209 | if (nritems == 0 && parent == root->node) { | 4231 | if (nritems == 0 && parent == root->node) { |
| @@ -4235,7 +4257,7 @@ static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans, | |||
| 4235 | struct extent_buffer *leaf) | 4257 | struct extent_buffer *leaf) |
| 4236 | { | 4258 | { |
| 4237 | WARN_ON(btrfs_header_generation(leaf) != trans->transid); | 4259 | WARN_ON(btrfs_header_generation(leaf) != trans->transid); |
| 4238 | del_ptr(trans, root, path, 1, path->slots[1]); | 4260 | del_ptr(trans, root, path, 1, path->slots[1], 1); |
| 4239 | 4261 | ||
| 4240 | /* | 4262 | /* |
| 4241 | * btrfs_free_extent is expensive, we want to make sure we | 4263 | * btrfs_free_extent is expensive, we want to make sure we |
