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