aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-26 05:43:17 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-30 09:17:29 -0400
commitf230475e62f77930e776881deb6e95cfd2226bd4 (patch)
treebf57ab6531a988d5566138b9a4cf916ecfcbbf3f /fs/btrfs/ctree.c
parentbd989ba359f2acb8bc5f5490e19010fc0a6f8356 (diff)
Btrfs: put all block modifications into the tree mod log
When running functions that can make changes to the internal trees (e.g. btrfs_search_slot), we check if somebody may be interested in the block we're currently modifying. If so, we record our modification to be able to rewind it later on. Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 72b9f97e2fdc..07c1a96aa4a8 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -39,6 +39,14 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
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);
42static void tree_mod_log_free_eb(struct btrfs_fs_info *fs_info,
43 struct extent_buffer *eb);
44struct extent_buffer *read_old_tree_block(struct btrfs_root *root, u64 bytenr,
45 u32 blocksize, u64 parent_transid,
46 u64 time_seq);
47struct extent_buffer *btrfs_find_old_tree_block(struct btrfs_root *root,
48 u64 bytenr, u32 blocksize,
49 u64 time_seq);
42 50
43struct btrfs_path *btrfs_alloc_path(void) 51struct btrfs_path *btrfs_alloc_path(void)
44{ 52{
@@ -816,6 +824,12 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
816 ret = btrfs_dec_ref(trans, root, buf, 1, 1); 824 ret = btrfs_dec_ref(trans, root, buf, 1, 1);
817 BUG_ON(ret); /* -ENOMEM */ 825 BUG_ON(ret); /* -ENOMEM */
818 } 826 }
827 /*
828 * don't log freeing in case we're freeing the root node, this
829 * is done by tree_mod_log_set_root_pointer later
830 */
831 if (buf != root->node && btrfs_header_level(buf) != 0)
832 tree_mod_log_free_eb(root->fs_info, buf);
819 clean_tree_block(trans, root, buf); 833 clean_tree_block(trans, root, buf);
820 *last_ref = 1; 834 *last_ref = 1;
821 } 835 }
@@ -913,6 +927,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
913 parent_start = 0; 927 parent_start = 0;
914 928
915 extent_buffer_get(cow); 929 extent_buffer_get(cow);
930 tree_mod_log_set_root_pointer(root, cow);
916 rcu_assign_pointer(root->node, cow); 931 rcu_assign_pointer(root->node, cow);
917 932
918 btrfs_free_tree_block(trans, root, buf, parent_start, 933 btrfs_free_tree_block(trans, root, buf, parent_start,
@@ -926,6 +941,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
926 parent_start = 0; 941 parent_start = 0;
927 942
928 WARN_ON(trans->transid != btrfs_header_generation(parent)); 943 WARN_ON(trans->transid != btrfs_header_generation(parent));
944 tree_mod_log_insert_key(root->fs_info, parent, parent_slot,
945 MOD_LOG_KEY_REPLACE);
929 btrfs_set_node_blockptr(parent, parent_slot, 946 btrfs_set_node_blockptr(parent, parent_slot,
930 cow->start); 947 cow->start);
931 btrfs_set_node_ptr_generation(parent, parent_slot, 948 btrfs_set_node_ptr_generation(parent, parent_slot,
@@ -1381,6 +1398,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1381 goto enospc; 1398 goto enospc;
1382 } 1399 }
1383 1400
1401 tree_mod_log_set_root_pointer(root, child);
1384 rcu_assign_pointer(root->node, child); 1402 rcu_assign_pointer(root->node, child);
1385 1403
1386 add_root_to_dirty_list(root); 1404 add_root_to_dirty_list(root);
@@ -1455,6 +1473,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1455 } else { 1473 } else {
1456 struct btrfs_disk_key right_key; 1474 struct btrfs_disk_key right_key;
1457 btrfs_node_key(right, &right_key, 0); 1475 btrfs_node_key(right, &right_key, 0);
1476 tree_mod_log_set_node_key(root->fs_info, parent,
1477 &right_key, pslot + 1, 0);
1458 btrfs_set_node_key(parent, &right_key, pslot + 1); 1478 btrfs_set_node_key(parent, &right_key, pslot + 1);
1459 btrfs_mark_buffer_dirty(parent); 1479 btrfs_mark_buffer_dirty(parent);
1460 } 1480 }
@@ -1498,6 +1518,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1498 /* update the parent key to reflect our changes */ 1518 /* update the parent key to reflect our changes */
1499 struct btrfs_disk_key mid_key; 1519 struct btrfs_disk_key mid_key;
1500 btrfs_node_key(mid, &mid_key, 0); 1520 btrfs_node_key(mid, &mid_key, 0);
1521 tree_mod_log_set_node_key(root->fs_info, parent, &mid_key,
1522 pslot, 0);
1501 btrfs_set_node_key(parent, &mid_key, pslot); 1523 btrfs_set_node_key(parent, &mid_key, pslot);
1502 btrfs_mark_buffer_dirty(parent); 1524 btrfs_mark_buffer_dirty(parent);
1503 } 1525 }
@@ -1595,6 +1617,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
1595 struct btrfs_disk_key disk_key; 1617 struct btrfs_disk_key disk_key;
1596 orig_slot += left_nr; 1618 orig_slot += left_nr;
1597 btrfs_node_key(mid, &disk_key, 0); 1619 btrfs_node_key(mid, &disk_key, 0);
1620 tree_mod_log_set_node_key(root->fs_info, parent,
1621 &disk_key, pslot, 0);
1598 btrfs_set_node_key(parent, &disk_key, pslot); 1622 btrfs_set_node_key(parent, &disk_key, pslot);
1599 btrfs_mark_buffer_dirty(parent); 1623 btrfs_mark_buffer_dirty(parent);
1600 if (btrfs_header_nritems(left) > orig_slot) { 1624 if (btrfs_header_nritems(left) > orig_slot) {
@@ -1646,6 +1670,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
1646 struct btrfs_disk_key disk_key; 1670 struct btrfs_disk_key disk_key;
1647 1671
1648 btrfs_node_key(right, &disk_key, 0); 1672 btrfs_node_key(right, &disk_key, 0);
1673 tree_mod_log_set_node_key(root->fs_info, parent,
1674 &disk_key, pslot + 1, 0);
1649 btrfs_set_node_key(parent, &disk_key, pslot + 1); 1675 btrfs_set_node_key(parent, &disk_key, pslot + 1);
1650 btrfs_mark_buffer_dirty(parent); 1676 btrfs_mark_buffer_dirty(parent);
1651 1677
@@ -2348,6 +2374,7 @@ static void fixup_low_keys(struct btrfs_trans_handle *trans,
2348 if (!path->nodes[i]) 2374 if (!path->nodes[i])
2349 break; 2375 break;
2350 t = path->nodes[i]; 2376 t = path->nodes[i];
2377 tree_mod_log_set_node_key(root->fs_info, t, key, tslot, 1);
2351 btrfs_set_node_key(t, key, tslot); 2378 btrfs_set_node_key(t, key, tslot);
2352 btrfs_mark_buffer_dirty(path->nodes[i]); 2379 btrfs_mark_buffer_dirty(path->nodes[i]);
2353 if (tslot != 0) 2380 if (tslot != 0)
@@ -2430,12 +2457,16 @@ static int push_node_left(struct btrfs_trans_handle *trans,
2430 } else 2457 } else
2431 push_items = min(src_nritems - 8, push_items); 2458 push_items = min(src_nritems - 8, push_items);
2432 2459
2460 tree_mod_log_eb_copy(root->fs_info, dst, src, dst_nritems, 0,
2461 push_items);
2433 copy_extent_buffer(dst, src, 2462 copy_extent_buffer(dst, src,
2434 btrfs_node_key_ptr_offset(dst_nritems), 2463 btrfs_node_key_ptr_offset(dst_nritems),
2435 btrfs_node_key_ptr_offset(0), 2464 btrfs_node_key_ptr_offset(0),
2436 push_items * sizeof(struct btrfs_key_ptr)); 2465 push_items * sizeof(struct btrfs_key_ptr));
2437 2466
2438 if (push_items < src_nritems) { 2467 if (push_items < src_nritems) {
2468 tree_mod_log_eb_move(root->fs_info, src, 0, push_items,
2469 src_nritems - push_items);
2439 memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), 2470 memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
2440 btrfs_node_key_ptr_offset(push_items), 2471 btrfs_node_key_ptr_offset(push_items),
2441 (src_nritems - push_items) * 2472 (src_nritems - push_items) *
@@ -2489,11 +2520,14 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
2489 if (max_push < push_items) 2520 if (max_push < push_items)
2490 push_items = max_push; 2521 push_items = max_push;
2491 2522
2523 tree_mod_log_eb_move(root->fs_info, dst, push_items, 0, dst_nritems);
2492 memmove_extent_buffer(dst, btrfs_node_key_ptr_offset(push_items), 2524 memmove_extent_buffer(dst, btrfs_node_key_ptr_offset(push_items),
2493 btrfs_node_key_ptr_offset(0), 2525 btrfs_node_key_ptr_offset(0),
2494 (dst_nritems) * 2526 (dst_nritems) *
2495 sizeof(struct btrfs_key_ptr)); 2527 sizeof(struct btrfs_key_ptr));
2496 2528
2529 tree_mod_log_eb_copy(root->fs_info, dst, src, 0,
2530 src_nritems - push_items, push_items);
2497 copy_extent_buffer(dst, src, 2531 copy_extent_buffer(dst, src,
2498 btrfs_node_key_ptr_offset(0), 2532 btrfs_node_key_ptr_offset(0),
2499 btrfs_node_key_ptr_offset(src_nritems - push_items), 2533 btrfs_node_key_ptr_offset(src_nritems - push_items),
@@ -2568,6 +2602,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
2568 btrfs_mark_buffer_dirty(c); 2602 btrfs_mark_buffer_dirty(c);
2569 2603
2570 old = root->node; 2604 old = root->node;
2605 tree_mod_log_set_root_pointer(root, c);
2571 rcu_assign_pointer(root->node, c); 2606 rcu_assign_pointer(root->node, c);
2572 2607
2573 /* the super has an extra ref to root->node */ 2608 /* the super has an extra ref to root->node */
@@ -2678,6 +2713,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
2678 (unsigned long)btrfs_header_chunk_tree_uuid(split), 2713 (unsigned long)btrfs_header_chunk_tree_uuid(split),
2679 BTRFS_UUID_SIZE); 2714 BTRFS_UUID_SIZE);
2680 2715
2716 tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid);
2681 copy_extent_buffer(split, c, 2717 copy_extent_buffer(split, c,
2682 btrfs_node_key_ptr_offset(0), 2718 btrfs_node_key_ptr_offset(0),
2683 btrfs_node_key_ptr_offset(mid), 2719 btrfs_node_key_ptr_offset(mid),