Commit ca7a79ad8dbe24669a8ced01f9fc0126b872745d
1 parent
188de649c5
Exists in
master
and in
7 other branches
Btrfs: Pass down the expected generation number when reading tree blocks
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Showing 6 changed files with 55 additions and 64 deletions Side-by-side Diff
fs/btrfs/ctree.c
... | ... | @@ -302,6 +302,7 @@ |
302 | 302 | struct extent_buffer *cur; |
303 | 303 | struct extent_buffer *tmp; |
304 | 304 | u64 blocknr; |
305 | + u64 gen; | |
305 | 306 | u64 search_start = *last_ret; |
306 | 307 | u64 last_block = 0; |
307 | 308 | u64 other; |
... | ... | @@ -354,6 +355,7 @@ |
354 | 355 | |
355 | 356 | progress_passed = 1; |
356 | 357 | blocknr = btrfs_node_blockptr(parent, i); |
358 | + gen = btrfs_node_ptr_generation(parent, i); | |
357 | 359 | if (last_block == 0) |
358 | 360 | last_block = blocknr; |
359 | 361 | |
360 | 362 | |
361 | 363 | |
... | ... | @@ -387,15 +389,14 @@ |
387 | 389 | } |
388 | 390 | if (!cur) { |
389 | 391 | cur = read_tree_block(root, blocknr, |
390 | - blocksize); | |
392 | + blocksize, gen); | |
391 | 393 | } else if (!uptodate) { |
392 | - btrfs_read_buffer(cur); | |
394 | + btrfs_read_buffer(cur, gen); | |
393 | 395 | } |
394 | 396 | } |
395 | 397 | if (search_start == 0) |
396 | 398 | search_start = last_block; |
397 | 399 | |
398 | - btrfs_verify_block_csum(root, cur); | |
399 | 400 | err = __btrfs_cow_block(trans, root, cur, parent, i, |
400 | 401 | &tmp, search_start, |
401 | 402 | min(16 * blocksize, |
402 | 403 | |
403 | 404 | |
... | ... | @@ -696,12 +697,17 @@ |
696 | 697 | static struct extent_buffer *read_node_slot(struct btrfs_root *root, |
697 | 698 | struct extent_buffer *parent, int slot) |
698 | 699 | { |
700 | + int level = btrfs_header_level(parent); | |
699 | 701 | if (slot < 0) |
700 | 702 | return NULL; |
701 | 703 | if (slot >= btrfs_header_nritems(parent)) |
702 | 704 | return NULL; |
705 | + | |
706 | + BUG_ON(level == 0); | |
707 | + | |
703 | 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 | 713 | static int balance_level(struct btrfs_trans_handle *trans, |
... | ... | @@ -1076,7 +1082,8 @@ |
1076 | 1082 | if ((search >= lowest_read && search <= highest_read) || |
1077 | 1083 | (search < lowest_read && lowest_read - search <= 32768) || |
1078 | 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 | 1087 | nread += blocksize; |
1081 | 1088 | } |
1082 | 1089 | nscan++; |
... | ... | @@ -1109,8 +1116,6 @@ |
1109 | 1116 | ins_len, int cow) |
1110 | 1117 | { |
1111 | 1118 | struct extent_buffer *b; |
1112 | - u64 bytenr; | |
1113 | - u64 ptr_gen; | |
1114 | 1119 | int slot; |
1115 | 1120 | int ret; |
1116 | 1121 | int level; |
1117 | 1122 | |
... | ... | @@ -1174,20 +1179,12 @@ |
1174 | 1179 | /* this is only true while dropping a snapshot */ |
1175 | 1180 | if (level == lowest_level) |
1176 | 1181 | break; |
1177 | - bytenr = btrfs_node_blockptr(b, slot); | |
1178 | - ptr_gen = btrfs_node_ptr_generation(b, slot); | |
1182 | + | |
1179 | 1183 | if (should_reada) |
1180 | 1184 | reada_for_search(root, p, level, slot, |
1181 | 1185 | key->objectid); |
1182 | - b = read_tree_block(root, bytenr, | |
1183 | - btrfs_level_size(root, level - 1)); | |
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 | - } | |
1186 | + | |
1187 | + b = read_node_slot(root, b, slot); | |
1191 | 1188 | } else { |
1192 | 1189 | p->slots[level] = slot; |
1193 | 1190 | if (ins_len > 0 && btrfs_leaf_free_space(root, b) < |
... | ... | @@ -1650,8 +1647,7 @@ |
1650 | 1647 | if (slot >= btrfs_header_nritems(upper) - 1) |
1651 | 1648 | return 1; |
1652 | 1649 | |
1653 | - right = read_tree_block(root, btrfs_node_blockptr(upper, slot + 1), | |
1654 | - root->leafsize); | |
1650 | + right = read_node_slot(root, upper, slot + 1); | |
1655 | 1651 | free_space = btrfs_leaf_free_space(root, right); |
1656 | 1652 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
1657 | 1653 | free_extent_buffer(right); |
... | ... | @@ -1826,8 +1822,7 @@ |
1826 | 1822 | return 1; |
1827 | 1823 | } |
1828 | 1824 | |
1829 | - left = read_tree_block(root, btrfs_node_blockptr(path->nodes[1], | |
1830 | - slot - 1), root->leafsize); | |
1825 | + left = read_node_slot(root, path->nodes[1], slot - 1); | |
1831 | 1826 | free_space = btrfs_leaf_free_space(root, left); |
1832 | 1827 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
1833 | 1828 | free_extent_buffer(left); |
... | ... | @@ -2742,7 +2737,6 @@ |
2742 | 2737 | */ |
2743 | 2738 | int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) |
2744 | 2739 | { |
2745 | - u64 bytenr; | |
2746 | 2740 | int slot; |
2747 | 2741 | int level = 1; |
2748 | 2742 | struct extent_buffer *c; |
2749 | 2743 | |
... | ... | @@ -2762,12 +2756,10 @@ |
2762 | 2756 | } |
2763 | 2757 | slot--; |
2764 | 2758 | |
2765 | - bytenr = btrfs_node_blockptr(c, slot); | |
2766 | 2759 | if (next) |
2767 | 2760 | free_extent_buffer(next); |
2768 | 2761 | |
2769 | - next = read_tree_block(root, bytenr, | |
2770 | - btrfs_level_size(root, level - 1)); | |
2762 | + next = read_node_slot(root, c, slot); | |
2771 | 2763 | break; |
2772 | 2764 | } |
2773 | 2765 | path->slots[level] = slot; |
... | ... | @@ -2782,8 +2774,7 @@ |
2782 | 2774 | path->slots[level] = slot; |
2783 | 2775 | if (!level) |
2784 | 2776 | break; |
2785 | - next = read_tree_block(root, btrfs_node_blockptr(next, slot), | |
2786 | - btrfs_level_size(root, level - 1)); | |
2777 | + next = read_node_slot(root, next, slot); | |
2787 | 2778 | } |
2788 | 2779 | return 0; |
2789 | 2780 | } |
... | ... | @@ -2797,7 +2788,6 @@ |
2797 | 2788 | { |
2798 | 2789 | int slot; |
2799 | 2790 | int level = 1; |
2800 | - u64 bytenr; | |
2801 | 2791 | struct extent_buffer *c; |
2802 | 2792 | struct extent_buffer *next = NULL; |
2803 | 2793 | |
2804 | 2794 | |
... | ... | @@ -2814,15 +2804,13 @@ |
2814 | 2804 | continue; |
2815 | 2805 | } |
2816 | 2806 | |
2817 | - bytenr = btrfs_node_blockptr(c, slot); | |
2818 | 2807 | if (next) |
2819 | 2808 | free_extent_buffer(next); |
2820 | 2809 | |
2821 | 2810 | if (path->reada) |
2822 | 2811 | reada_for_search(root, path, level, slot, 0); |
2823 | 2812 | |
2824 | - next = read_tree_block(root, bytenr, | |
2825 | - btrfs_level_size(root, level -1)); | |
2813 | + next = read_node_slot(root, c, slot); | |
2826 | 2814 | break; |
2827 | 2815 | } |
2828 | 2816 | path->slots[level] = slot; |
... | ... | @@ -2836,8 +2824,7 @@ |
2836 | 2824 | break; |
2837 | 2825 | if (path->reada) |
2838 | 2826 | reada_for_search(root, path, level, 0, 0); |
2839 | - next = read_tree_block(root, btrfs_node_blockptr(next, 0), | |
2840 | - btrfs_level_size(root, level - 1)); | |
2827 | + next = read_node_slot(root, next, 0); | |
2841 | 2828 | } |
2842 | 2829 | return 0; |
2843 | 2830 | } |
fs/btrfs/disk-io.c
... | ... | @@ -207,7 +207,7 @@ |
207 | 207 | |
208 | 208 | static int btree_read_extent_buffer_pages(struct btrfs_root *root, |
209 | 209 | struct extent_buffer *eb, |
210 | - u64 start) | |
210 | + u64 start, u64 parent_transid) | |
211 | 211 | { |
212 | 212 | struct extent_io_tree *io_tree; |
213 | 213 | int ret; |
... | ... | @@ -254,7 +254,8 @@ |
254 | 254 | WARN_ON(1); |
255 | 255 | } |
256 | 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 | 259 | BUG_ON(ret); |
259 | 260 | btrfs_clear_buffer_defrag(eb); |
260 | 261 | found_start = btrfs_header_bytenr(eb); |
... | ... | @@ -562,7 +563,8 @@ |
562 | 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 | 569 | struct extent_buffer *buf = NULL; |
568 | 570 | struct inode *btree_inode = root->fs_info->btree_inode; |
... | ... | @@ -592,12 +594,6 @@ |
592 | 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 | 597 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
602 | 598 | u64 bytenr, u32 blocksize) |
603 | 599 | { |
... | ... | @@ -621,7 +617,7 @@ |
621 | 617 | |
622 | 618 | |
623 | 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 | 622 | struct extent_buffer *buf = NULL; |
627 | 623 | struct inode *btree_inode = root->fs_info->btree_inode; |
... | ... | @@ -634,7 +630,7 @@ |
634 | 630 | if (!buf) |
635 | 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 | 635 | if (ret == 0) { |
640 | 636 | buf->flags |= EXTENT_UPTODATE; |
... | ... | @@ -715,7 +711,7 @@ |
715 | 711 | |
716 | 712 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); |
717 | 713 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
718 | - blocksize); | |
714 | + blocksize, 0); | |
719 | 715 | BUG_ON(!root->node); |
720 | 716 | return 0; |
721 | 717 | } |
... | ... | @@ -771,7 +767,7 @@ |
771 | 767 | } |
772 | 768 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); |
773 | 769 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
774 | - blocksize); | |
770 | + blocksize, 0); | |
775 | 771 | BUG_ON(!root->node); |
776 | 772 | insert: |
777 | 773 | root->ref_cows = 1; |
... | ... | @@ -1288,7 +1284,7 @@ |
1288 | 1284 | |
1289 | 1285 | chunk_root->node = read_tree_block(chunk_root, |
1290 | 1286 | btrfs_super_chunk_root(disk_super), |
1291 | - blocksize); | |
1287 | + blocksize, 0); | |
1292 | 1288 | BUG_ON(!chunk_root->node); |
1293 | 1289 | |
1294 | 1290 | read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid, |
... | ... | @@ -1304,7 +1300,7 @@ |
1304 | 1300 | |
1305 | 1301 | tree_root->node = read_tree_block(tree_root, |
1306 | 1302 | btrfs_super_root(disk_super), |
1307 | - blocksize); | |
1303 | + blocksize, 0); | |
1308 | 1304 | if (!tree_root->node) |
1309 | 1305 | goto fail_sb_buffer; |
1310 | 1306 | |
1311 | 1307 | |
... | ... | @@ -1732,11 +1728,11 @@ |
1732 | 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 | 1733 | struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; |
1738 | 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 | 1736 | if (ret == 0) { |
1741 | 1737 | buf->flags |= EXTENT_UPTODATE; |
1742 | 1738 | } |
fs/btrfs/disk-io.h
... | ... | @@ -25,8 +25,9 @@ |
25 | 25 | struct btrfs_fs_devices; |
26 | 26 | |
27 | 27 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, |
28 | - u32 blocksize); | |
29 | -int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize); | |
28 | + u32 blocksize, u64 parent_transid); | |
29 | +int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, | |
30 | + u64 parent_transid); | |
30 | 31 | struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, |
31 | 32 | u64 bytenr, u32 blocksize); |
32 | 33 | int clean_tree_block(struct btrfs_trans_handle *trans, |
... | ... | @@ -65,7 +66,7 @@ |
65 | 66 | int btrfs_buffer_defrag_done(struct extent_buffer *buf); |
66 | 67 | int btrfs_clear_buffer_defrag(struct extent_buffer *buf); |
67 | 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 | 70 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len); |
70 | 71 | void btrfs_csum_final(u32 crc, char *result); |
71 | 72 | void btrfs_throttle(struct btrfs_root *root); |
fs/btrfs/extent-tree.c
... | ... | @@ -1338,7 +1338,8 @@ |
1338 | 1338 | &extent_item, sizeof(extent_item)); |
1339 | 1339 | clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, |
1340 | 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 | 1343 | level = btrfs_header_level(eb); |
1343 | 1344 | if (level == 0) { |
1344 | 1345 | btrfs_item_key(eb, &first, 0); |
... | ... | @@ -2076,7 +2077,8 @@ |
2076 | 2077 | } |
2077 | 2078 | } |
2078 | 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 | 2082 | last = bytenr + blocksize; |
2081 | 2083 | cond_resched(); |
2082 | 2084 | mutex_lock(&root->fs_info->fs_mutex); |
... | ... | @@ -2096,6 +2098,7 @@ |
2096 | 2098 | u64 root_owner; |
2097 | 2099 | u64 root_gen; |
2098 | 2100 | u64 bytenr; |
2101 | + u64 ptr_gen; | |
2099 | 2102 | struct extent_buffer *next; |
2100 | 2103 | struct extent_buffer *cur; |
2101 | 2104 | struct extent_buffer *parent; |
... | ... | @@ -2132,6 +2135,7 @@ |
2132 | 2135 | break; |
2133 | 2136 | } |
2134 | 2137 | bytenr = btrfs_node_blockptr(cur, path->slots[*level]); |
2138 | + ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); | |
2135 | 2139 | blocksize = btrfs_level_size(root, *level - 1); |
2136 | 2140 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); |
2137 | 2141 | BUG_ON(ret); |
... | ... | @@ -2152,7 +2156,8 @@ |
2152 | 2156 | reada_walk_down(root, cur, path->slots[*level]); |
2153 | 2157 | |
2154 | 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 | 2161 | mutex_lock(&root->fs_info->fs_mutex); |
2157 | 2162 | |
2158 | 2163 | /* we've dropped the lock, double check */ |
... | ... | @@ -2173,8 +2178,6 @@ |
2173 | 2178 | BUG_ON(ret); |
2174 | 2179 | continue; |
2175 | 2180 | } |
2176 | - } else if (next) { | |
2177 | - btrfs_verify_block_csum(root, next); | |
2178 | 2181 | } |
2179 | 2182 | WARN_ON(*level <= 0); |
2180 | 2183 | if (path->nodes[*level-1]) |
... | ... | @@ -2609,7 +2612,7 @@ |
2609 | 2612 | int i; |
2610 | 2613 | |
2611 | 2614 | eb = read_tree_block(found_root, extent_key->objectid, |
2612 | - extent_key->offset); | |
2615 | + extent_key->offset, 0); | |
2613 | 2616 | level = btrfs_header_level(eb); |
2614 | 2617 | |
2615 | 2618 | if (level == 0) |
fs/btrfs/print-tree.c
... | ... | @@ -186,7 +186,8 @@ |
186 | 186 | for (i = 0; i < nr; i++) { |
187 | 187 | struct extent_buffer *next = read_tree_block(root, |
188 | 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 | 191 | if (btrfs_is_leaf(next) && |
191 | 192 | btrfs_header_level(c) != 1) |
192 | 193 | BUG(); |
fs/btrfs/tree-defrag.c
... | ... | @@ -28,6 +28,7 @@ |
28 | 28 | int i; |
29 | 29 | u32 nritems; |
30 | 30 | u64 bytenr; |
31 | + u64 gen; | |
31 | 32 | u32 blocksize; |
32 | 33 | int ret; |
33 | 34 | |
... | ... | @@ -35,7 +36,8 @@ |
35 | 36 | nritems = btrfs_header_nritems(node); |
36 | 37 | for (i = 0; i < nritems; i++) { |
37 | 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 | 41 | if (ret) |
40 | 42 | break; |
41 | 43 | } |
42 | 44 | |
... | ... | @@ -101,10 +103,11 @@ |
101 | 103 | path->slots[*level]++; |
102 | 104 | continue; |
103 | 105 | } |
104 | - btrfs_verify_block_csum(root, next); | |
105 | 106 | } else { |
106 | 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 | 112 | ret = btrfs_cow_block(trans, root, next, path->nodes[*level], |
110 | 113 | path->slots[*level], &next); |