fsck checks against extent map, small fixes
authorChris Mason <chris.mason@oracle.com>
Mon, 23 Apr 2007 21:00:26 +0000 (17:00 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Mon, 23 Apr 2007 21:00:26 +0000 (17:00 -0400)
btrfsck.c
extent-tree.c
mkfs.c

index 8cd2348..d1560c6 100644 (file)
--- a/btrfsck.c
+++ b/btrfsck.c
@@ -18,7 +18,7 @@ struct extent_record {
        u64 nr;
        u64 owner;
        u32 refs;
-       u32 extent_tree_refs;
+       u32 extent_item_refs;
        u8 type;
 };
 
@@ -114,7 +114,7 @@ static int check_block(struct btrfs_root *root,
 static int add_extent_rec(struct radix_tree_root *extent_radix,
                          struct btrfs_disk_key *parent_key,
                          u64 ref, u64 start, u64 nr, u64 owner, u8 type,
-                         int inc_ref)
+                         u32 extent_item_refs, int inc_ref)
 {
        struct extent_record *rec;
        int ret = 0;
@@ -123,7 +123,8 @@ static int add_extent_rec(struct radix_tree_root *extent_radix,
                if (inc_ref)
                        rec->refs++;
                if (owner != rec->owner) {
-                       fprintf(stderr, "warning, owner mismatch %Lu\n", start);
+                       fprintf(stderr, "warning, owner mismatch %Lu %Lu %Lu\n",
+                               start, owner, rec->owner);
                        ret = 1;
                }
                if (start != rec->start) {
@@ -133,20 +134,36 @@ static int add_extent_rec(struct radix_tree_root *extent_radix,
                }
                if (type != rec->type) {
                        fprintf(stderr, "type mismatch block %Lu %d %d\n",
-                               start, type, type);
+                               start, type, rec->type);
                        ret = 1;
                }
+               if (extent_item_refs)
+                       rec->extent_item_refs = extent_item_refs;
                return ret;
        }
        rec = malloc(sizeof(*rec));
+       if (start == 0)
+               extent_item_refs = 0;
        rec->start = start;
        rec->nr = nr;
        rec->owner = owner;
        rec->type = type;
+
+       if (inc_ref)
+               rec->refs = 1;
+       else
+               rec->refs = 0;
+
+       if (extent_item_refs)
+               rec->extent_item_refs = extent_item_refs;
+       else
+               rec->extent_item_refs = 0;
+
        if (parent_key)
                memcpy(&rec->parent_key, parent_key, sizeof(*parent_key));
        else
                memset(&rec->parent_key, 0, sizeof(*parent_key));
+
        ret = radix_tree_insert(extent_radix, start, rec);
        BUG_ON(ret);
        blocks_used += nr;
@@ -234,6 +251,22 @@ static int run_next_block(struct btrfs_root *root,
                leaf = &buf->leaf;
                for (i = 0; i < nritems; i++) {
                        struct btrfs_file_extent_item *fi;
+                       if (btrfs_disk_key_type(&leaf->items[i].key) ==
+                           BTRFS_EXTENT_ITEM_KEY) {
+                               struct btrfs_key found;
+                               struct btrfs_extent_item *ei;
+                               btrfs_disk_key_to_cpu(&found,
+                                                     &leaf->items[i].key);
+                               ei = btrfs_item_ptr(leaf, i,
+                                                   struct btrfs_extent_item);
+                               add_extent_rec(extent_radix, NULL, 0,
+                                              found.objectid,
+                                              found.offset,
+                                              btrfs_extent_owner(ei),
+                                              btrfs_extent_type(ei),
+                                              btrfs_extent_refs(ei), 0);
+                               continue;
+                       }
                        if (btrfs_disk_key_type(&leaf->items[i].key) !=
                            BTRFS_EXTENT_DATA_KEY)
                                continue;
@@ -246,7 +279,7 @@ static int run_next_block(struct btrfs_root *root,
                                   btrfs_file_extent_disk_blocknr(fi),
                                   btrfs_file_extent_disk_num_blocks(fi),
                                   btrfs_disk_key_objectid(&leaf->items[i].key),
-                                  BTRFS_EXTENT_FILE, 1);
+                                  BTRFS_EXTENT_FILE, 0, 1);
                        BUG_ON(ret);
                }
        } else {
@@ -259,7 +292,7 @@ static int run_next_block(struct btrfs_root *root,
                                             &node->ptrs[i].key,
                                             blocknr, ptr, 1,
                                             btrfs_header_owner(&node->header),
-                                            BTRFS_EXTENT_TREE, 1);
+                                            BTRFS_EXTENT_TREE, 0, 1);
                        BUG_ON(ret);
                        if (level > 1) {
                                add_pending(nodes, seen, ptr);
@@ -284,10 +317,39 @@ static int add_root_to_pending(struct btrfs_root *root,
        add_pending(pending, seen, root->node->blocknr);
        add_extent_rec(extent_radix, NULL, 0, root->node->blocknr, 1,
                       btrfs_header_owner(&root->node->node.header),
-                      BTRFS_EXTENT_TREE, 1);
+                      BTRFS_EXTENT_TREE, 0, 1);
        return 0;
 }
 
+int check_extent_refs(struct btrfs_root *root,
+                     struct radix_tree_root *extent_radix)
+{
+       struct extent_record *rec[64];
+       int i;
+       int ret;
+       int err = 0;
+
+       while(1) {
+               ret = radix_tree_gang_lookup(extent_radix, (void **)rec, 0,
+                                            ARRAY_SIZE(rec));
+               if (!ret)
+                       break;
+               for (i = 0; i < ret; i++) {
+                       if (rec[i]->refs != rec[i]->extent_item_refs) {
+                               fprintf(stderr, "ref mismatch on [%Lu %Lu] ",
+                                       rec[i]->start, rec[i]->nr);
+                               fprintf(stderr, "extent item %u, found %u\n",
+                                       rec[i]->extent_item_refs,
+                                       rec[i]->refs);
+                               err = 1;
+                       }
+                       radix_tree_delete(extent_radix, rec[i]->start);
+                       free(rec[i]);
+               }
+       }
+       return err;
+}
+
 int main(int ac, char **av) {
        struct btrfs_super_block super;
        struct btrfs_root *root;
@@ -333,7 +395,8 @@ int main(int ac, char **av) {
                if (ret != 0)
                        break;
        }
+       ret = check_extent_refs(root, &extent_radix);
        close_ctree(root, &super);
-       printf("found %Lu blocks used\n", blocks_used);
-       return 0;
+       printf("found %Lu blocks used err is %d\n", blocks_used, ret);
+       return ret;
 }
index a0fc177..b9d401c 100644 (file)
@@ -138,6 +138,8 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
        struct btrfs_fs_info *info = extent_root->fs_info;
 
        btrfs_set_extent_refs(&extent_item, 1);
+       btrfs_set_extent_type(&extent_item, BTRFS_EXTENT_TREE);
+       btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid);
        ins.offset = 1;
        ins.flags = 0;
        btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY);
diff --git a/mkfs.c b/mkfs.c
index b307470..0097d53 100644 (file)
--- a/mkfs.c
+++ b/mkfs.c
@@ -215,6 +215,8 @@ int mkfs(int fd, char *pathname, u64 num_blocks, u32 blocksize)
        btrfs_set_item_offset(&item, itemoff);
        btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item));
        btrfs_set_extent_refs(&extent_item, 1);
+       btrfs_set_extent_owner(&extent_item, BTRFS_ROOT_TREE_OBJECTID);
+       btrfs_set_extent_type(&extent_item, BTRFS_EXTENT_TREE);
        memcpy(empty_leaf->items, &item, sizeof(item));
        memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item),
                &extent_item, btrfs_item_size(&item));