diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-05-12 12:59:19 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:03 -0400 |
commit | ca7a79ad8dbe24669a8ced01f9fc0126b872745d (patch) | |
tree | 0d53d8e6fd9ff9aece4e703581918c7817175d5d /fs | |
parent | 188de649c51f03df3f8a601aea0110a3870815c2 (diff) |
Btrfs: Pass down the expected generation number when reading tree blocks
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.c | 55 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 30 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 7 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 15 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 3 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 9 |
6 files changed, 55 insertions, 64 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 29e5674b043d..289d71d8653a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -302,6 +302,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
302 | struct extent_buffer *cur; | 302 | struct extent_buffer *cur; |
303 | struct extent_buffer *tmp; | 303 | struct extent_buffer *tmp; |
304 | u64 blocknr; | 304 | u64 blocknr; |
305 | u64 gen; | ||
305 | u64 search_start = *last_ret; | 306 | u64 search_start = *last_ret; |
306 | u64 last_block = 0; | 307 | u64 last_block = 0; |
307 | u64 other; | 308 | u64 other; |
@@ -354,6 +355,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
354 | 355 | ||
355 | progress_passed = 1; | 356 | progress_passed = 1; |
356 | blocknr = btrfs_node_blockptr(parent, i); | 357 | blocknr = btrfs_node_blockptr(parent, i); |
358 | gen = btrfs_node_ptr_generation(parent, i); | ||
357 | if (last_block == 0) | 359 | if (last_block == 0) |
358 | last_block = blocknr; | 360 | last_block = blocknr; |
359 | 361 | ||
@@ -387,15 +389,14 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
387 | } | 389 | } |
388 | if (!cur) { | 390 | if (!cur) { |
389 | cur = read_tree_block(root, blocknr, | 391 | cur = read_tree_block(root, blocknr, |
390 | blocksize); | 392 | blocksize, gen); |
391 | } else if (!uptodate) { | 393 | } else if (!uptodate) { |
392 | btrfs_read_buffer(cur); | 394 | btrfs_read_buffer(cur, gen); |
393 | } | 395 | } |
394 | } | 396 | } |
395 | if (search_start == 0) | 397 | if (search_start == 0) |
396 | search_start = last_block; | 398 | search_start = last_block; |
397 | 399 | ||
398 | btrfs_verify_block_csum(root, cur); | ||
399 | err = __btrfs_cow_block(trans, root, cur, parent, i, | 400 | err = __btrfs_cow_block(trans, root, cur, parent, i, |
400 | &tmp, search_start, | 401 | &tmp, search_start, |
401 | min(16 * blocksize, | 402 | min(16 * blocksize, |
@@ -696,12 +697,17 @@ static int bin_search(struct extent_buffer *eb, struct btrfs_key *key, | |||
696 | static struct extent_buffer *read_node_slot(struct btrfs_root *root, | 697 | static struct extent_buffer *read_node_slot(struct btrfs_root *root, |
697 | struct extent_buffer *parent, int slot) | 698 | struct extent_buffer *parent, int slot) |
698 | { | 699 | { |
700 | int level = btrfs_header_level(parent); | ||
699 | if (slot < 0) | 701 | if (slot < 0) |
700 | return NULL; | 702 | return NULL; |
701 | if (slot >= btrfs_header_nritems(parent)) | 703 | if (slot >= btrfs_header_nritems(parent)) |
702 | return NULL; | 704 | return NULL; |
705 | |||
706 | BUG_ON(level == 0); | ||
707 | |||
703 | return read_tree_block(root, btrfs_node_blockptr(parent, slot), | 708 | return read_tree_block(root, btrfs_node_blockptr(parent, slot), |
704 | btrfs_level_size(root, btrfs_header_level(parent) - 1)); | 709 | btrfs_level_size(root, level - 1), |
710 | btrfs_node_ptr_generation(parent, slot)); | ||
705 | } | 711 | } |
706 | 712 | ||
707 | static int balance_level(struct btrfs_trans_handle *trans, | 713 | static int balance_level(struct btrfs_trans_handle *trans, |
@@ -1076,7 +1082,8 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, | |||
1076 | if ((search >= lowest_read && search <= highest_read) || | 1082 | if ((search >= lowest_read && search <= highest_read) || |
1077 | (search < lowest_read && lowest_read - search <= 32768) || | 1083 | (search < lowest_read && lowest_read - search <= 32768) || |
1078 | (search > highest_read && search - highest_read <= 32768)) { | 1084 | (search > highest_read && search - highest_read <= 32768)) { |
1079 | readahead_tree_block(root, search, blocksize); | 1085 | readahead_tree_block(root, search, blocksize, |
1086 | btrfs_node_ptr_generation(node, nr)); | ||
1080 | nread += blocksize; | 1087 | nread += blocksize; |
1081 | } | 1088 | } |
1082 | nscan++; | 1089 | nscan++; |
@@ -1109,8 +1116,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1109 | ins_len, int cow) | 1116 | ins_len, int cow) |
1110 | { | 1117 | { |
1111 | struct extent_buffer *b; | 1118 | struct extent_buffer *b; |
1112 | u64 bytenr; | ||
1113 | u64 ptr_gen; | ||
1114 | int slot; | 1119 | int slot; |
1115 | int ret; | 1120 | int ret; |
1116 | int level; | 1121 | int level; |
@@ -1174,20 +1179,12 @@ again: | |||
1174 | /* this is only true while dropping a snapshot */ | 1179 | /* this is only true while dropping a snapshot */ |
1175 | if (level == lowest_level) | 1180 | if (level == lowest_level) |
1176 | break; | 1181 | break; |
1177 | bytenr = btrfs_node_blockptr(b, slot); | 1182 | |
1178 | ptr_gen = btrfs_node_ptr_generation(b, slot); | ||
1179 | if (should_reada) | 1183 | if (should_reada) |
1180 | reada_for_search(root, p, level, slot, | 1184 | reada_for_search(root, p, level, slot, |
1181 | key->objectid); | 1185 | key->objectid); |
1182 | b = read_tree_block(root, bytenr, | 1186 | |
1183 | btrfs_level_size(root, level - 1)); | 1187 | b = read_node_slot(root, b, slot); |
1184 | if (ptr_gen != btrfs_header_generation(b)) { | ||
1185 | printk("block %llu bad gen wanted %llu " | ||
1186 | "found %llu\n", | ||
1187 | (unsigned long long)b->start, | ||
1188 | (unsigned long long)ptr_gen, | ||
1189 | (unsigned long long)btrfs_header_generation(b)); | ||
1190 | } | ||
1191 | } else { | 1188 | } else { |
1192 | p->slots[level] = slot; | 1189 | p->slots[level] = slot; |
1193 | if (ins_len > 0 && btrfs_leaf_free_space(root, b) < | 1190 | if (ins_len > 0 && btrfs_leaf_free_space(root, b) < |
@@ -1650,8 +1647,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1650 | if (slot >= btrfs_header_nritems(upper) - 1) | 1647 | if (slot >= btrfs_header_nritems(upper) - 1) |
1651 | return 1; | 1648 | return 1; |
1652 | 1649 | ||
1653 | right = read_tree_block(root, btrfs_node_blockptr(upper, slot + 1), | 1650 | right = read_node_slot(root, upper, slot + 1); |
1654 | root->leafsize); | ||
1655 | free_space = btrfs_leaf_free_space(root, right); | 1651 | free_space = btrfs_leaf_free_space(root, right); |
1656 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1652 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
1657 | free_extent_buffer(right); | 1653 | free_extent_buffer(right); |
@@ -1826,8 +1822,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1826 | return 1; | 1822 | return 1; |
1827 | } | 1823 | } |
1828 | 1824 | ||
1829 | left = read_tree_block(root, btrfs_node_blockptr(path->nodes[1], | 1825 | left = read_node_slot(root, path->nodes[1], slot - 1); |
1830 | slot - 1), root->leafsize); | ||
1831 | free_space = btrfs_leaf_free_space(root, left); | 1826 | free_space = btrfs_leaf_free_space(root, left); |
1832 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1827 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
1833 | free_extent_buffer(left); | 1828 | free_extent_buffer(left); |
@@ -2742,7 +2737,6 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2742 | */ | 2737 | */ |
2743 | int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) | 2738 | int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) |
2744 | { | 2739 | { |
2745 | u64 bytenr; | ||
2746 | int slot; | 2740 | int slot; |
2747 | int level = 1; | 2741 | int level = 1; |
2748 | struct extent_buffer *c; | 2742 | struct extent_buffer *c; |
@@ -2762,12 +2756,10 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
2762 | } | 2756 | } |
2763 | slot--; | 2757 | slot--; |
2764 | 2758 | ||
2765 | bytenr = btrfs_node_blockptr(c, slot); | ||
2766 | if (next) | 2759 | if (next) |
2767 | free_extent_buffer(next); | 2760 | free_extent_buffer(next); |
2768 | 2761 | ||
2769 | next = read_tree_block(root, bytenr, | 2762 | next = read_node_slot(root, c, slot); |
2770 | btrfs_level_size(root, level - 1)); | ||
2771 | break; | 2763 | break; |
2772 | } | 2764 | } |
2773 | path->slots[level] = slot; | 2765 | path->slots[level] = slot; |
@@ -2782,8 +2774,7 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
2782 | path->slots[level] = slot; | 2774 | path->slots[level] = slot; |
2783 | if (!level) | 2775 | if (!level) |
2784 | break; | 2776 | break; |
2785 | next = read_tree_block(root, btrfs_node_blockptr(next, slot), | 2777 | next = read_node_slot(root, next, slot); |
2786 | btrfs_level_size(root, level - 1)); | ||
2787 | } | 2778 | } |
2788 | return 0; | 2779 | return 0; |
2789 | } | 2780 | } |
@@ -2797,7 +2788,6 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
2797 | { | 2788 | { |
2798 | int slot; | 2789 | int slot; |
2799 | int level = 1; | 2790 | int level = 1; |
2800 | u64 bytenr; | ||
2801 | struct extent_buffer *c; | 2791 | struct extent_buffer *c; |
2802 | struct extent_buffer *next = NULL; | 2792 | struct extent_buffer *next = NULL; |
2803 | 2793 | ||
@@ -2814,15 +2804,13 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
2814 | continue; | 2804 | continue; |
2815 | } | 2805 | } |
2816 | 2806 | ||
2817 | bytenr = btrfs_node_blockptr(c, slot); | ||
2818 | if (next) | 2807 | if (next) |
2819 | free_extent_buffer(next); | 2808 | free_extent_buffer(next); |
2820 | 2809 | ||
2821 | if (path->reada) | 2810 | if (path->reada) |
2822 | reada_for_search(root, path, level, slot, 0); | 2811 | reada_for_search(root, path, level, slot, 0); |
2823 | 2812 | ||
2824 | next = read_tree_block(root, bytenr, | 2813 | next = read_node_slot(root, c, slot); |
2825 | btrfs_level_size(root, level -1)); | ||
2826 | break; | 2814 | break; |
2827 | } | 2815 | } |
2828 | path->slots[level] = slot; | 2816 | path->slots[level] = slot; |
@@ -2836,8 +2824,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
2836 | break; | 2824 | break; |
2837 | if (path->reada) | 2825 | if (path->reada) |
2838 | reada_for_search(root, path, level, 0, 0); | 2826 | reada_for_search(root, path, level, 0, 0); |
2839 | next = read_tree_block(root, btrfs_node_blockptr(next, 0), | 2827 | next = read_node_slot(root, next, 0); |
2840 | btrfs_level_size(root, level - 1)); | ||
2841 | } | 2828 | } |
2842 | return 0; | 2829 | return 0; |
2843 | } | 2830 | } |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c3083165b172..edee7a44f861 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -207,7 +207,7 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, | |||
207 | 207 | ||
208 | static int btree_read_extent_buffer_pages(struct btrfs_root *root, | 208 | static int btree_read_extent_buffer_pages(struct btrfs_root *root, |
209 | struct extent_buffer *eb, | 209 | struct extent_buffer *eb, |
210 | u64 start) | 210 | u64 start, u64 parent_transid) |
211 | { | 211 | { |
212 | struct extent_io_tree *io_tree; | 212 | struct extent_io_tree *io_tree; |
213 | int ret; | 213 | int ret; |
@@ -254,7 +254,8 @@ int csum_dirty_buffer(struct btrfs_root *root, struct page *page) | |||
254 | WARN_ON(1); | 254 | WARN_ON(1); |
255 | } | 255 | } |
256 | eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); | 256 | eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); |
257 | ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE); | 257 | ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE, |
258 | btrfs_header_generation(eb)); | ||
258 | BUG_ON(ret); | 259 | BUG_ON(ret); |
259 | btrfs_clear_buffer_defrag(eb); | 260 | btrfs_clear_buffer_defrag(eb); |
260 | found_start = btrfs_header_bytenr(eb); | 261 | found_start = btrfs_header_bytenr(eb); |
@@ -562,7 +563,8 @@ static struct address_space_operations btree_aops = { | |||
562 | .sync_page = block_sync_page, | 563 | .sync_page = block_sync_page, |
563 | }; | 564 | }; |
564 | 565 | ||
565 | int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize) | 566 | int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, |
567 | u64 parent_transid) | ||
566 | { | 568 | { |
567 | struct extent_buffer *buf = NULL; | 569 | struct extent_buffer *buf = NULL; |
568 | struct inode *btree_inode = root->fs_info->btree_inode; | 570 | struct inode *btree_inode = root->fs_info->btree_inode; |
@@ -592,12 +594,6 @@ static int close_all_devices(struct btrfs_fs_info *fs_info) | |||
592 | return 0; | 594 | return 0; |
593 | } | 595 | } |
594 | 596 | ||
595 | int btrfs_verify_block_csum(struct btrfs_root *root, | ||
596 | struct extent_buffer *buf) | ||
597 | { | ||
598 | return btrfs_buffer_uptodate(buf); | ||
599 | } | ||
600 | |||
601 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, | 597 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
602 | u64 bytenr, u32 blocksize) | 598 | u64 bytenr, u32 blocksize) |
603 | { | 599 | { |
@@ -621,7 +617,7 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, | |||
621 | 617 | ||
622 | 618 | ||
623 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | 619 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, |
624 | u32 blocksize) | 620 | u32 blocksize, u64 parent_transid) |
625 | { | 621 | { |
626 | struct extent_buffer *buf = NULL; | 622 | struct extent_buffer *buf = NULL; |
627 | struct inode *btree_inode = root->fs_info->btree_inode; | 623 | struct inode *btree_inode = root->fs_info->btree_inode; |
@@ -634,7 +630,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | |||
634 | if (!buf) | 630 | if (!buf) |
635 | return NULL; | 631 | return NULL; |
636 | 632 | ||
637 | ret = btree_read_extent_buffer_pages(root, buf, 0); | 633 | ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); |
638 | 634 | ||
639 | if (ret == 0) { | 635 | if (ret == 0) { |
640 | buf->flags |= EXTENT_UPTODATE; | 636 | buf->flags |= EXTENT_UPTODATE; |
@@ -715,7 +711,7 @@ static int find_and_setup_root(struct btrfs_root *tree_root, | |||
715 | 711 | ||
716 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); | 712 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); |
717 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | 713 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
718 | blocksize); | 714 | blocksize, 0); |
719 | BUG_ON(!root->node); | 715 | BUG_ON(!root->node); |
720 | return 0; | 716 | return 0; |
721 | } | 717 | } |
@@ -771,7 +767,7 @@ out: | |||
771 | } | 767 | } |
772 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); | 768 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); |
773 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | 769 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
774 | blocksize); | 770 | blocksize, 0); |
775 | BUG_ON(!root->node); | 771 | BUG_ON(!root->node); |
776 | insert: | 772 | insert: |
777 | root->ref_cows = 1; | 773 | root->ref_cows = 1; |
@@ -1288,7 +1284,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1288 | 1284 | ||
1289 | chunk_root->node = read_tree_block(chunk_root, | 1285 | chunk_root->node = read_tree_block(chunk_root, |
1290 | btrfs_super_chunk_root(disk_super), | 1286 | btrfs_super_chunk_root(disk_super), |
1291 | blocksize); | 1287 | blocksize, 0); |
1292 | BUG_ON(!chunk_root->node); | 1288 | BUG_ON(!chunk_root->node); |
1293 | 1289 | ||
1294 | read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid, | 1290 | read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid, |
@@ -1304,7 +1300,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1304 | 1300 | ||
1305 | tree_root->node = read_tree_block(tree_root, | 1301 | tree_root->node = read_tree_block(tree_root, |
1306 | btrfs_super_root(disk_super), | 1302 | btrfs_super_root(disk_super), |
1307 | blocksize); | 1303 | blocksize, 0); |
1308 | if (!tree_root->node) | 1304 | if (!tree_root->node) |
1309 | goto fail_sb_buffer; | 1305 | goto fail_sb_buffer; |
1310 | 1306 | ||
@@ -1732,11 +1728,11 @@ int btrfs_clear_buffer_defrag(struct extent_buffer *buf) | |||
1732 | EXTENT_DEFRAG, GFP_NOFS); | 1728 | EXTENT_DEFRAG, GFP_NOFS); |
1733 | } | 1729 | } |
1734 | 1730 | ||
1735 | int btrfs_read_buffer(struct extent_buffer *buf) | 1731 | int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) |
1736 | { | 1732 | { |
1737 | struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; | 1733 | struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; |
1738 | int ret; | 1734 | int ret; |
1739 | ret = btree_read_extent_buffer_pages(root, buf, 0); | 1735 | ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); |
1740 | if (ret == 0) { | 1736 | if (ret == 0) { |
1741 | buf->flags |= EXTENT_UPTODATE; | 1737 | buf->flags |= EXTENT_UPTODATE; |
1742 | } | 1738 | } |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 5d5f6979c41c..e29c895d5230 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -25,8 +25,9 @@ struct btrfs_device; | |||
25 | struct btrfs_fs_devices; | 25 | struct btrfs_fs_devices; |
26 | 26 | ||
27 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | 27 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, |
28 | u32 blocksize); | 28 | u32 blocksize, u64 parent_transid); |
29 | int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize); | 29 | int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, |
30 | u64 parent_transid); | ||
30 | struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, | 31 | struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, |
31 | u64 bytenr, u32 blocksize); | 32 | u64 bytenr, u32 blocksize); |
32 | int clean_tree_block(struct btrfs_trans_handle *trans, | 33 | int clean_tree_block(struct btrfs_trans_handle *trans, |
@@ -65,7 +66,7 @@ int btrfs_buffer_defrag(struct extent_buffer *buf); | |||
65 | int btrfs_buffer_defrag_done(struct extent_buffer *buf); | 66 | int btrfs_buffer_defrag_done(struct extent_buffer *buf); |
66 | int btrfs_clear_buffer_defrag(struct extent_buffer *buf); | 67 | int btrfs_clear_buffer_defrag(struct extent_buffer *buf); |
67 | int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf); | 68 | int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf); |
68 | int btrfs_read_buffer(struct extent_buffer *buf); | 69 | int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid); |
69 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len); | 70 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len); |
70 | void btrfs_csum_final(u32 crc, char *result); | 71 | void btrfs_csum_final(u32 crc, char *result); |
71 | void btrfs_throttle(struct btrfs_root *root); | 72 | void btrfs_throttle(struct btrfs_root *root); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index df95fb660d49..db07dde4a870 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1338,7 +1338,8 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, | |||
1338 | &extent_item, sizeof(extent_item)); | 1338 | &extent_item, sizeof(extent_item)); |
1339 | clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, | 1339 | clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, |
1340 | GFP_NOFS); | 1340 | GFP_NOFS); |
1341 | eb = read_tree_block(extent_root, ins.objectid, ins.offset); | 1341 | eb = read_tree_block(extent_root, ins.objectid, ins.offset, |
1342 | trans->transid); | ||
1342 | level = btrfs_header_level(eb); | 1343 | level = btrfs_header_level(eb); |
1343 | if (level == 0) { | 1344 | if (level == 0) { |
1344 | btrfs_item_key(eb, &first, 0); | 1345 | btrfs_item_key(eb, &first, 0); |
@@ -2076,7 +2077,8 @@ static void noinline reada_walk_down(struct btrfs_root *root, | |||
2076 | } | 2077 | } |
2077 | } | 2078 | } |
2078 | mutex_unlock(&root->fs_info->fs_mutex); | 2079 | mutex_unlock(&root->fs_info->fs_mutex); |
2079 | ret = readahead_tree_block(root, bytenr, blocksize); | 2080 | ret = readahead_tree_block(root, bytenr, blocksize, |
2081 | btrfs_node_ptr_generation(node, i)); | ||
2080 | last = bytenr + blocksize; | 2082 | last = bytenr + blocksize; |
2081 | cond_resched(); | 2083 | cond_resched(); |
2082 | mutex_lock(&root->fs_info->fs_mutex); | 2084 | mutex_lock(&root->fs_info->fs_mutex); |
@@ -2096,6 +2098,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2096 | u64 root_owner; | 2098 | u64 root_owner; |
2097 | u64 root_gen; | 2099 | u64 root_gen; |
2098 | u64 bytenr; | 2100 | u64 bytenr; |
2101 | u64 ptr_gen; | ||
2099 | struct extent_buffer *next; | 2102 | struct extent_buffer *next; |
2100 | struct extent_buffer *cur; | 2103 | struct extent_buffer *cur; |
2101 | struct extent_buffer *parent; | 2104 | struct extent_buffer *parent; |
@@ -2132,6 +2135,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2132 | break; | 2135 | break; |
2133 | } | 2136 | } |
2134 | bytenr = btrfs_node_blockptr(cur, path->slots[*level]); | 2137 | bytenr = btrfs_node_blockptr(cur, path->slots[*level]); |
2138 | ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); | ||
2135 | blocksize = btrfs_level_size(root, *level - 1); | 2139 | blocksize = btrfs_level_size(root, *level - 1); |
2136 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); | 2140 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); |
2137 | BUG_ON(ret); | 2141 | BUG_ON(ret); |
@@ -2152,7 +2156,8 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2152 | reada_walk_down(root, cur, path->slots[*level]); | 2156 | reada_walk_down(root, cur, path->slots[*level]); |
2153 | 2157 | ||
2154 | mutex_unlock(&root->fs_info->fs_mutex); | 2158 | mutex_unlock(&root->fs_info->fs_mutex); |
2155 | next = read_tree_block(root, bytenr, blocksize); | 2159 | next = read_tree_block(root, bytenr, blocksize, |
2160 | ptr_gen); | ||
2156 | mutex_lock(&root->fs_info->fs_mutex); | 2161 | mutex_lock(&root->fs_info->fs_mutex); |
2157 | 2162 | ||
2158 | /* we've dropped the lock, double check */ | 2163 | /* we've dropped the lock, double check */ |
@@ -2173,8 +2178,6 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2173 | BUG_ON(ret); | 2178 | BUG_ON(ret); |
2174 | continue; | 2179 | continue; |
2175 | } | 2180 | } |
2176 | } else if (next) { | ||
2177 | btrfs_verify_block_csum(root, next); | ||
2178 | } | 2181 | } |
2179 | WARN_ON(*level <= 0); | 2182 | WARN_ON(*level <= 0); |
2180 | if (path->nodes[*level-1]) | 2183 | if (path->nodes[*level-1]) |
@@ -2609,7 +2612,7 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
2609 | int i; | 2612 | int i; |
2610 | 2613 | ||
2611 | eb = read_tree_block(found_root, extent_key->objectid, | 2614 | eb = read_tree_block(found_root, extent_key->objectid, |
2612 | extent_key->offset); | 2615 | extent_key->offset, 0); |
2613 | level = btrfs_header_level(eb); | 2616 | level = btrfs_header_level(eb); |
2614 | 2617 | ||
2615 | if (level == 0) | 2618 | if (level == 0) |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index e99f3249d05a..14d863720302 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
@@ -186,7 +186,8 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c) | |||
186 | for (i = 0; i < nr; i++) { | 186 | for (i = 0; i < nr; i++) { |
187 | struct extent_buffer *next = read_tree_block(root, | 187 | struct extent_buffer *next = read_tree_block(root, |
188 | btrfs_node_blockptr(c, i), | 188 | btrfs_node_blockptr(c, i), |
189 | btrfs_level_size(root, level - 1)); | 189 | btrfs_level_size(root, level - 1), |
190 | btrfs_node_ptr_generation(c, i)); | ||
190 | if (btrfs_is_leaf(next) && | 191 | if (btrfs_is_leaf(next) && |
191 | btrfs_header_level(c) != 1) | 192 | btrfs_header_level(c) != 1) |
192 | BUG(); | 193 | BUG(); |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 256af1870eef..5085e9e693b9 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -28,6 +28,7 @@ static void reada_defrag(struct btrfs_root *root, | |||
28 | int i; | 28 | int i; |
29 | u32 nritems; | 29 | u32 nritems; |
30 | u64 bytenr; | 30 | u64 bytenr; |
31 | u64 gen; | ||
31 | u32 blocksize; | 32 | u32 blocksize; |
32 | int ret; | 33 | int ret; |
33 | 34 | ||
@@ -35,7 +36,8 @@ static void reada_defrag(struct btrfs_root *root, | |||
35 | nritems = btrfs_header_nritems(node); | 36 | nritems = btrfs_header_nritems(node); |
36 | for (i = 0; i < nritems; i++) { | 37 | for (i = 0; i < nritems; i++) { |
37 | bytenr = btrfs_node_blockptr(node, i); | 38 | bytenr = btrfs_node_blockptr(node, i); |
38 | ret = readahead_tree_block(root, bytenr, blocksize); | 39 | gen = btrfs_node_ptr_generation(node, i); |
40 | ret = readahead_tree_block(root, bytenr, blocksize, gen); | ||
39 | if (ret) | 41 | if (ret) |
40 | break; | 42 | break; |
41 | } | 43 | } |
@@ -101,10 +103,11 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, | |||
101 | path->slots[*level]++; | 103 | path->slots[*level]++; |
102 | continue; | 104 | continue; |
103 | } | 105 | } |
104 | btrfs_verify_block_csum(root, next); | ||
105 | } else { | 106 | } else { |
106 | next = read_tree_block(root, bytenr, | 107 | next = read_tree_block(root, bytenr, |
107 | btrfs_level_size(root, *level - 1)); | 108 | btrfs_level_size(root, *level - 1), |
109 | btrfs_node_ptr_generation(cur, | ||
110 | path->slots[*level])); | ||
108 | } | 111 | } |
109 | ret = btrfs_cow_block(trans, root, next, path->nodes[*level], | 112 | ret = btrfs_cow_block(trans, root, next, path->nodes[*level], |
110 | path->slots[*level], &next); | 113 | path->slots[*level], &next); |