Btrfs: Pass down the expected generation number when reading tree blocks

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 29e5674..289d71d 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -302,6 +302,7 @@
 	struct extent_buffer *cur;
 	struct extent_buffer *tmp;
 	u64 blocknr;
+	u64 gen;
 	u64 search_start = *last_ret;
 	u64 last_block = 0;
 	u64 other;
@@ -354,6 +355,7 @@
 
 		progress_passed = 1;
 		blocknr = btrfs_node_blockptr(parent, i);
+		gen = btrfs_node_ptr_generation(parent, i);
 		if (last_block == 0)
 			last_block = blocknr;
 
@@ -387,15 +389,14 @@
 			}
 			if (!cur) {
 				cur = read_tree_block(root, blocknr,
-							 blocksize);
+							 blocksize, gen);
 			} else if (!uptodate) {
-				btrfs_read_buffer(cur);
+				btrfs_read_buffer(cur, gen);
 			}
 		}
 		if (search_start == 0)
 			search_start = last_block;
 
-		btrfs_verify_block_csum(root, cur);
 		err = __btrfs_cow_block(trans, root, cur, parent, i,
 					&tmp, search_start,
 					min(16 * blocksize,
@@ -696,12 +697,17 @@
 static struct extent_buffer *read_node_slot(struct btrfs_root *root,
 				   struct extent_buffer *parent, int slot)
 {
+	int level = btrfs_header_level(parent);
 	if (slot < 0)
 		return NULL;
 	if (slot >= btrfs_header_nritems(parent))
 		return NULL;
+
+	BUG_ON(level == 0);
+
 	return read_tree_block(root, btrfs_node_blockptr(parent, slot),
-		       btrfs_level_size(root, btrfs_header_level(parent) - 1));
+		       btrfs_level_size(root, level - 1),
+		       btrfs_node_ptr_generation(parent, slot));
 }
 
 static int balance_level(struct btrfs_trans_handle *trans,
@@ -1076,7 +1082,8 @@
 		if ((search >= lowest_read && search <= highest_read) ||
 		    (search < lowest_read && lowest_read - search <= 32768) ||
 		    (search > highest_read && search - highest_read <= 32768)) {
-			readahead_tree_block(root, search, blocksize);
+			readahead_tree_block(root, search, blocksize,
+				     btrfs_node_ptr_generation(node, nr));
 			nread += blocksize;
 		}
 		nscan++;
@@ -1109,8 +1116,6 @@
 		      ins_len, int cow)
 {
 	struct extent_buffer *b;
-	u64 bytenr;
-	u64 ptr_gen;
 	int slot;
 	int ret;
 	int level;
@@ -1174,20 +1179,12 @@
 			/* this is only true while dropping a snapshot */
 			if (level == lowest_level)
 				break;
-			bytenr = btrfs_node_blockptr(b, slot);
-			ptr_gen = btrfs_node_ptr_generation(b, slot);
+
 			if (should_reada)
 				reada_for_search(root, p, level, slot,
 						 key->objectid);
-			b = read_tree_block(root, bytenr,
-					    btrfs_level_size(root, level - 1));
-			if (ptr_gen != btrfs_header_generation(b)) {
-				printk("block %llu bad gen wanted %llu "
-				       "found %llu\n",
-			        (unsigned long long)b->start,
-				(unsigned long long)ptr_gen,
-			        (unsigned long long)btrfs_header_generation(b));
-			}
+
+			b = read_node_slot(root, b, slot);
 		} else {
 			p->slots[level] = slot;
 			if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
@@ -1650,8 +1647,7 @@
 	if (slot >= btrfs_header_nritems(upper) - 1)
 		return 1;
 
-	right = read_tree_block(root, btrfs_node_blockptr(upper, slot + 1),
-				root->leafsize);
+	right = read_node_slot(root, upper, slot + 1);
 	free_space = btrfs_leaf_free_space(root, right);
 	if (free_space < data_size + sizeof(struct btrfs_item)) {
 		free_extent_buffer(right);
@@ -1826,8 +1822,7 @@
 		return 1;
 	}
 
-	left = read_tree_block(root, btrfs_node_blockptr(path->nodes[1],
-			       slot - 1), root->leafsize);
+	left = read_node_slot(root, path->nodes[1], slot - 1);
 	free_space = btrfs_leaf_free_space(root, left);
 	if (free_space < data_size + sizeof(struct btrfs_item)) {
 		free_extent_buffer(left);
@@ -2742,7 +2737,6 @@
  */
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
 {
-	u64 bytenr;
 	int slot;
 	int level = 1;
 	struct extent_buffer *c;
@@ -2762,12 +2756,10 @@
 		}
 		slot--;
 
-		bytenr = btrfs_node_blockptr(c, slot);
 		if (next)
 			free_extent_buffer(next);
 
-		next = read_tree_block(root, bytenr,
-				       btrfs_level_size(root, level - 1));
+		next = read_node_slot(root, c, slot);
 		break;
 	}
 	path->slots[level] = slot;
@@ -2782,8 +2774,7 @@
 		path->slots[level] = slot;
 		if (!level)
 			break;
-		next = read_tree_block(root, btrfs_node_blockptr(next, slot),
-				       btrfs_level_size(root, level - 1));
+		next = read_node_slot(root, next, slot);
 	}
 	return 0;
 }
@@ -2797,7 +2788,6 @@
 {
 	int slot;
 	int level = 1;
-	u64 bytenr;
 	struct extent_buffer *c;
 	struct extent_buffer *next = NULL;
 
@@ -2814,15 +2804,13 @@
 			continue;
 		}
 
-		bytenr = btrfs_node_blockptr(c, slot);
 		if (next)
 			free_extent_buffer(next);
 
 		if (path->reada)
 			reada_for_search(root, path, level, slot, 0);
 
-		next = read_tree_block(root, bytenr,
-				       btrfs_level_size(root, level -1));
+		next = read_node_slot(root, c, slot);
 		break;
 	}
 	path->slots[level] = slot;
@@ -2836,8 +2824,7 @@
 			break;
 		if (path->reada)
 			reada_for_search(root, path, level, 0, 0);
-		next = read_tree_block(root, btrfs_node_blockptr(next, 0),
-				       btrfs_level_size(root, level - 1));
+		next = read_node_slot(root, next, 0);
 	}
 	return 0;
 }
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index c308316..edee7a4 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -207,7 +207,7 @@
 
 static int btree_read_extent_buffer_pages(struct btrfs_root *root,
 					  struct extent_buffer *eb,
-					  u64 start)
+					  u64 start, u64 parent_transid)
 {
 	struct extent_io_tree *io_tree;
 	int ret;
@@ -254,7 +254,8 @@
 		WARN_ON(1);
 	}
 	eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS);
-	ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE);
+	ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE,
+					     btrfs_header_generation(eb));
 	BUG_ON(ret);
 	btrfs_clear_buffer_defrag(eb);
 	found_start = btrfs_header_bytenr(eb);
@@ -562,7 +563,8 @@
 	.sync_page	= block_sync_page,
 };
 
-int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
+int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
+			 u64 parent_transid)
 {
 	struct extent_buffer *buf = NULL;
 	struct inode *btree_inode = root->fs_info->btree_inode;
@@ -592,12 +594,6 @@
 	return 0;
 }
 
-int btrfs_verify_block_csum(struct btrfs_root *root,
-			    struct extent_buffer *buf)
-{
-	return btrfs_buffer_uptodate(buf);
-}
-
 struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
 					    u64 bytenr, u32 blocksize)
 {
@@ -621,7 +617,7 @@
 
 
 struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
-				      u32 blocksize)
+				      u32 blocksize, u64 parent_transid)
 {
 	struct extent_buffer *buf = NULL;
 	struct inode *btree_inode = root->fs_info->btree_inode;
@@ -634,7 +630,7 @@
 	if (!buf)
 		return NULL;
 
-	ret = btree_read_extent_buffer_pages(root, buf, 0);
+	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
 
 	if (ret == 0) {
 		buf->flags |= EXTENT_UPTODATE;
@@ -715,7 +711,7 @@
 
 	blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
 	root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
-				     blocksize);
+				     blocksize, 0);
 	BUG_ON(!root->node);
 	return 0;
 }
@@ -771,7 +767,7 @@
 	}
 	blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
 	root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
-				     blocksize);
+				     blocksize, 0);
 	BUG_ON(!root->node);
 insert:
 	root->ref_cows = 1;
@@ -1288,7 +1284,7 @@
 
 	chunk_root->node = read_tree_block(chunk_root,
 					   btrfs_super_chunk_root(disk_super),
-					   blocksize);
+					   blocksize, 0);
 	BUG_ON(!chunk_root->node);
 
 	read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid,
@@ -1304,7 +1300,7 @@
 
 	tree_root->node = read_tree_block(tree_root,
 					  btrfs_super_root(disk_super),
-					  blocksize);
+					  blocksize, 0);
 	if (!tree_root->node)
 		goto fail_sb_buffer;
 
@@ -1732,11 +1728,11 @@
 		     EXTENT_DEFRAG, GFP_NOFS);
 }
 
-int btrfs_read_buffer(struct extent_buffer *buf)
+int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid)
 {
 	struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root;
 	int ret;
-	ret = btree_read_extent_buffer_pages(root, buf, 0);
+	ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
 	if (ret == 0) {
 		buf->flags |= EXTENT_UPTODATE;
 	}
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 5d5f697..e29c895 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -25,8 +25,9 @@
 struct btrfs_fs_devices;
 
 struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
-				      u32 blocksize);
-int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize);
+				      u32 blocksize, u64 parent_transid);
+int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
+			 u64 parent_transid);
 struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
 						   u64 bytenr, u32 blocksize);
 int clean_tree_block(struct btrfs_trans_handle *trans,
@@ -65,7 +66,7 @@
 int btrfs_buffer_defrag_done(struct extent_buffer *buf);
 int btrfs_clear_buffer_defrag(struct extent_buffer *buf);
 int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf);
-int btrfs_read_buffer(struct extent_buffer *buf);
+int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid);
 u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);
 void btrfs_csum_final(u32 crc, char *result);
 void btrfs_throttle(struct btrfs_root *root);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index df95fb6..db07dde 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1338,7 +1338,8 @@
 					&extent_item, sizeof(extent_item));
 		clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED,
 				  GFP_NOFS);
-		eb = read_tree_block(extent_root, ins.objectid, ins.offset);
+		eb = read_tree_block(extent_root, ins.objectid, ins.offset,
+				     trans->transid);
 		level = btrfs_header_level(eb);
 		if (level == 0) {
 			btrfs_item_key(eb, &first, 0);
@@ -2076,7 +2077,8 @@
 			}
 		}
 		mutex_unlock(&root->fs_info->fs_mutex);
-		ret = readahead_tree_block(root, bytenr, blocksize);
+		ret = readahead_tree_block(root, bytenr, blocksize,
+					   btrfs_node_ptr_generation(node, i));
 		last = bytenr + blocksize;
 		cond_resched();
 		mutex_lock(&root->fs_info->fs_mutex);
@@ -2096,6 +2098,7 @@
 	u64 root_owner;
 	u64 root_gen;
 	u64 bytenr;
+	u64 ptr_gen;
 	struct extent_buffer *next;
 	struct extent_buffer *cur;
 	struct extent_buffer *parent;
@@ -2132,6 +2135,7 @@
 			break;
 		}
 		bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
+		ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
 		blocksize = btrfs_level_size(root, *level - 1);
 		ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs);
 		BUG_ON(ret);
@@ -2152,7 +2156,8 @@
 			reada_walk_down(root, cur, path->slots[*level]);
 
 			mutex_unlock(&root->fs_info->fs_mutex);
-			next = read_tree_block(root, bytenr, blocksize);
+			next = read_tree_block(root, bytenr, blocksize,
+					       ptr_gen);
 			mutex_lock(&root->fs_info->fs_mutex);
 
 			/* we've dropped the lock, double check */
@@ -2173,8 +2178,6 @@
 				BUG_ON(ret);
 				continue;
 			}
-		} else if (next) {
-			btrfs_verify_block_csum(root, next);
 		}
 		WARN_ON(*level <= 0);
 		if (path->nodes[*level-1])
@@ -2609,7 +2612,7 @@
 		int i;
 
 		eb = read_tree_block(found_root, extent_key->objectid,
-				     extent_key->offset);
+				     extent_key->offset, 0);
 		level = btrfs_header_level(eb);
 
 		if (level == 0)
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c
index e99f324..14d8637 100644
--- a/fs/btrfs/print-tree.c
+++ b/fs/btrfs/print-tree.c
@@ -186,7 +186,8 @@
 	for (i = 0; i < nr; i++) {
 		struct extent_buffer *next = read_tree_block(root,
 					btrfs_node_blockptr(c, i),
-					btrfs_level_size(root, level - 1));
+					btrfs_level_size(root, level - 1),
+					btrfs_node_ptr_generation(c, i));
 		if (btrfs_is_leaf(next) &&
 		    btrfs_header_level(c) != 1)
 			BUG();
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 256af18..5085e9e 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -28,6 +28,7 @@
 	int i;
 	u32 nritems;
 	u64 bytenr;
+	u64 gen;
 	u32 blocksize;
 	int ret;
 
@@ -35,7 +36,8 @@
 	nritems = btrfs_header_nritems(node);
 	for (i = 0; i < nritems; i++) {
 		bytenr = btrfs_node_blockptr(node, i);
-		ret = readahead_tree_block(root, bytenr, blocksize);
+		gen = btrfs_node_ptr_generation(node, i);
+		ret = readahead_tree_block(root, bytenr, blocksize, gen);
 		if (ret)
 			break;
 	}
@@ -101,10 +103,11 @@
 				path->slots[*level]++;
 				continue;
 			}
-			btrfs_verify_block_csum(root, next);
 		} else {
 			next = read_tree_block(root, bytenr,
-				       btrfs_level_size(root, *level - 1));
+				       btrfs_level_size(root, *level - 1),
+				       btrfs_node_ptr_generation(cur,
+							 path->slots[*level]));
 		}
 		ret = btrfs_cow_block(trans, root, next, path->nodes[*level],
 				      path->slots[*level], &next);