From 885f275a68f6702fb2f309fa925681419ab45a13 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 23 Apr 2007 17:00:26 -0400 Subject: fsck checks against extent map, small fixes --- btrfsck.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- extent-tree.c | 2 ++ mkfs.c | 2 ++ 3 files changed, 76 insertions(+), 9 deletions(-) diff --git a/btrfsck.c b/btrfsck.c index 8cd2348b..d1560c60 100644 --- 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; } diff --git a/extent-tree.c b/extent-tree.c index a0fc1772..b9d401c7 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -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 b307470f..0097d538 100644 --- 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)); -- cgit v1.2.3