Verify parent generation number on btree reads
authorChris Mason <chris.mason@oracle.com>
Tue, 13 May 2008 17:48:58 +0000 (13:48 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Tue, 13 May 2008 17:48:58 +0000 (13:48 -0400)
btrfs-vol.c
convert.c
ctree.c
disk-io.c
disk-io.h
extent-tree.c
extent_io.c
extent_io.h

index 9eddd78..8069778 100644 (file)
@@ -105,7 +105,10 @@ int main(int ac, char **av)
                print_usage();
        mnt = av[optind];
 
-       if (device) {
+       if (device && strcmp(device, "missing") == 0 &&
+           cmd == BTRFS_IOC_RM_DEV) {
+               fprintf(stderr, "removing missing devices from %s\n", mnt);
+       } else if (device) {
                devfd = open(device, O_RDWR);
                if (!devfd) {
                        fprintf(stderr, "Unable to open device %s\n", device);
index 219f849..3c00544 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -1094,7 +1094,7 @@ static int create_image_file_range(struct btrfs_trans_handle *trans,
        u32 blocksize = ext2_fs->blocksize;
        u32 block = start_byte / blocksize;
        u32 last_block = (end_byte + blocksize - 1) / blocksize;
-       int ret;
+       int ret = 0;
        struct blk_iterate_data data = {
                .trans          = trans,
                .root           = root,
diff --git a/ctree.c b/ctree.c
index 87574d9..881c115 100644 (file)
--- a/ctree.c
+++ b/ctree.c
@@ -378,7 +378,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 
                cur = btrfs_find_tree_block(root, blocknr, blocksize);
                if (cur)
-                       uptodate = btrfs_buffer_uptodate(cur);
+                       uptodate = btrfs_buffer_uptodate(cur, gen);
                else
                        uptodate = 0;
                if (!cur || !uptodate) {
index 687cc61..f2cbd4a 100644 (file)
--- 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)
index ffb4114..098f9e3 100644 (file)
--- a/disk-io.h
+++ b/disk-io.h
@@ -46,7 +46,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
                                      struct btrfs_key *location);
 int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
 void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
-int btrfs_buffer_uptodate(struct extent_buffer *buf);
+int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
 int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
 int wait_on_tree_block_writeback(struct btrfs_root *root,
                                 struct extent_buffer *buf);
index 545884a..767867f 100644 (file)
@@ -1253,7 +1253,7 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes,
        if (!pending) {
                buf = btrfs_find_tree_block(root, bytenr, num_bytes);
                if (buf) {
-                       if (btrfs_buffer_uptodate(buf)) {
+                       if (btrfs_buffer_uptodate(buf, 0)) {
                                u64 transid =
                                    root->fs_info->running_transaction->transid;
                                if (btrfs_header_generation(buf) ==
@@ -1967,7 +1967,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
                        continue;
                }
                next = btrfs_find_tree_block(root, bytenr, blocksize);
-               if (!next || !btrfs_buffer_uptodate(next)) {
+               if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
                        free_extent_buffer(next);
                        reada_walk_down(root, cur, path->slots[*level]);
                        mutex_unlock(&root->fs_info->fs_mutex);
index ef888d9..4920b29 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2007 Oracle.  All rights reserved.
  *
@@ -688,6 +689,13 @@ int set_extent_buffer_uptodate(struct extent_buffer *eb)
        return 0;
 }
 
+int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
+                               struct extent_buffer *eb)
+{
+       eb->flags &= ~EXTENT_UPTODATE;
+       return 0;
+}
+
 int extent_buffer_uptodate(struct extent_buffer *eb)
 {
        if (eb->flags & EXTENT_UPTODATE)
index 2bd4179..a5d6bf0 100644 (file)
@@ -84,6 +84,8 @@ int clear_extent_dirty(struct extent_io_tree *tree, u64 start,
                       u64 end, gfp_t mask);
 int extent_buffer_uptodate(struct extent_buffer *eb);
 int set_extent_buffer_uptodate(struct extent_buffer *eb);
+int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
+                               struct extent_buffer *eb);
 int set_state_private(struct extent_io_tree *tree, u64 start, u64 private);
 int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private);
 struct extent_buffer *find_extent_buffer(struct extent_io_tree *tree,