aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-26 05:45:21 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-30 09:17:32 -0400
commitf3ea38da3e76455fbd6d405cdca4d050ed085458 (patch)
tree8d0a86f40ca9516cb1a174c0716075e230bbfa0f /fs/btrfs
parentf230475e62f77930e776881deb6e95cfd2226bd4 (diff)
Btrfs: add del_ptr and insert_ptr modifications to the tree mod log
Record all relevant modifications to block pointers in the tree mod log so that we can rewind them later on for backref walking. Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.c42
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);
40static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, 40static 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);
42static void tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, 43static void tree_mod_log_free_eb(struct btrfs_fs_info *fs_info,
43 struct extent_buffer *eb); 44 struct extent_buffer *eb);
44struct extent_buffer *read_old_tree_block(struct btrfs_root *root, u64 bytenr, 45struct 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,
2626static void insert_ptr(struct btrfs_trans_handle *trans, 2627static 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 */
4193static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, 4203static 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