summaryrefslogtreecommitdiff
path: root/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-05-13 13:48:58 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2008-05-13 13:48:58 -0400
commit351d17fca2cf8063f323a060cd3c4af62ef58d15 (patch)
treed91b63f25ae45260b9b89f7c70b6af7c34bede79 /disk-io.c
parent9a9bdd6047a378dbe5a65a79cb8537f797d4fd5c (diff)
Verify parent generation number on btree reads
Diffstat (limited to 'disk-io.c')
-rw-r--r--disk-io.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/disk-io.c b/disk-io.c
index 687cc61e..f2cbd4af 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -106,7 +106,7 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
struct btrfs_device *device;
eb = btrfs_find_tree_block(root, bytenr, blocksize);
- if (eb && btrfs_buffer_uptodate(eb)) {
+ if (eb && btrfs_buffer_uptodate(eb, parent_transid)) {
free_extent_buffer(eb);
return 0;
}
@@ -124,6 +124,31 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
return 0;
}
+static int verify_parent_transid(struct extent_io_tree *io_tree,
+ struct extent_buffer *eb, u64 parent_transid)
+{
+ int ret;
+
+ if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
+ return 0;
+
+ if (extent_buffer_uptodate(eb) &&
+ btrfs_header_generation(eb) == parent_transid) {
+ ret = 0;
+ goto out;
+ }
+ printk("parent transid verify failed on %llu wanted %llu found %llu\n",
+ (unsigned long long)eb->start,
+ (unsigned long long)parent_transid,
+ (unsigned long long)btrfs_header_generation(eb));
+ ret = 1;
+out:
+ clear_extent_buffer_uptodate(io_tree, eb);
+ return ret;
+
+}
+
+
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize, u64 parent_transid)
{
@@ -140,7 +165,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
if (!eb)
return NULL;
- if (btrfs_buffer_uptodate(eb))
+ if (btrfs_buffer_uptodate(eb, parent_transid))
return eb;
dev_nr = 0;
@@ -156,19 +181,18 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
kfree(multi);
ret = read_extent_from_disk(eb);
if (ret == 0 && check_tree_block(root, eb) == 0 &&
- csum_tree_block(root, eb, 1) == 0) {
+ csum_tree_block(root, eb, 1) == 0 &&
+ verify_parent_transid(eb->tree, eb, parent_transid) == 0) {
btrfs_set_buffer_uptodate(eb);
return eb;
}
num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
eb->start, eb->len);
if (num_copies == 1) {
-printk("reading %Lu failed only one copy\n", eb->start);
break;
}
mirror_num++;
if (mirror_num > num_copies) {
-printk("bailing at mirror %d of %d\n", mirror_num, num_copies);
break;
}
}
@@ -186,7 +210,7 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (check_tree_block(root, eb))
BUG();
- if (!btrfs_buffer_uptodate(eb))
+ if (!btrfs_buffer_uptodate(eb, trans->transid))
BUG();
btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
@@ -773,9 +797,16 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *eb)
set_extent_buffer_dirty(eb);
}
-int btrfs_buffer_uptodate(struct extent_buffer *eb)
+int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
{
- return extent_buffer_uptodate(eb);
+ int ret;
+
+ ret = extent_buffer_uptodate(buf);
+ if (!ret)
+ return ret;
+
+ ret = verify_parent_transid(buf->tree, buf, parent_transid);
+ return !ret;
}
int btrfs_set_buffer_uptodate(struct extent_buffer *eb)