diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 55 |
1 files changed, 21 insertions, 34 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 | } |