diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-03-03 19:55:16 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2008-03-03 19:55:16 -0500 |
commit | 79599947bf7ab8720a127a90d731048189678f83 (patch) | |
tree | 4d334b8c22282f1dffc2dc5b28dd37bebbd07800 /debug-tree.c | |
parent | 6dfdeac7ec99b557e2ceace0d81f9067fcb28cbf (diff) |
Add debug-tree -e to print all allocated extents, and show-blocks to graph them
Diffstat (limited to 'debug-tree.c')
-rw-r--r-- | debug-tree.c | 133 |
1 files changed, 117 insertions, 16 deletions
diff --git a/debug-tree.c b/debug-tree.c index 368b8fb3..7a2d0d06 100644 --- a/debug-tree.c +++ b/debug-tree.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include <uuid/uuid.h> #include "kerncompat.h" #include "radix-tree.h" @@ -26,7 +27,79 @@ #include "print-tree.h" #include "transaction.h" -int main(int ac, char **av) { +static int print_usage(void) +{ + fprintf(stderr, "usage: debug-tree [ -e ] device\n"); + exit(1); +} + +static void print_extent_leaf(struct btrfs_root *root, struct extent_buffer *l) +{ + int i; + struct btrfs_item *item; + struct btrfs_extent_ref *ref; + struct btrfs_key key; + static u64 last = 0; + static u64 last_len = 0; + u32 nr = btrfs_header_nritems(l); + u32 type; + + for (i = 0 ; i < nr ; i++) { + item = btrfs_item_nr(l, i); + btrfs_item_key_to_cpu(l, &key, i); + type = btrfs_key_type(&key); + switch (type) { + case BTRFS_EXTENT_ITEM_KEY: + last_len = key.offset; + last = key.objectid; + break; + case BTRFS_EXTENT_REF_KEY: + ref = btrfs_item_ptr(l, i, struct btrfs_extent_ref); + printf("%llu %llu extent back ref root %llu gen %llu " + "owner %llu offset %llu\n", + (unsigned long long)last, + (unsigned long long)last_len, + (unsigned long long)btrfs_ref_root(l, ref), + (unsigned long long)btrfs_ref_generation(l, ref), + (unsigned long long)btrfs_ref_objectid(l, ref), + (unsigned long long)btrfs_ref_offset(l, ref)); + break; + }; + fflush(stdout); + } +} + +static void print_extents(struct btrfs_root *root, struct extent_buffer *eb) +{ + int i; + u32 nr; + u32 size; + + if (!eb) + return; + if (btrfs_is_leaf(eb)) { + print_extent_leaf(root, eb); + return; + } + size = btrfs_level_size(root, btrfs_header_level(eb) - 1); + nr = btrfs_header_nritems(eb); + for (i = 0; i < nr; i++) { + struct extent_buffer *next = read_tree_block(root, + btrfs_node_blockptr(eb, i), + size); + if (btrfs_is_leaf(next) && + btrfs_header_level(eb) != 1) + BUG(); + if (btrfs_header_level(next) != + btrfs_header_level(eb) - 1) + BUG(); + print_extents(root, next); + free_extent_buffer(next); + } +} + +int main(int ac, char **av) +{ struct btrfs_root *root; struct btrfs_path path; struct btrfs_key key; @@ -36,20 +109,37 @@ int main(int ac, char **av) { char uuidbuf[37]; int ret; int slot; + int extent_only = 0; - if (ac != 2) { - fprintf(stderr, "usage: %s device\n", av[0]); - exit(1); - } radix_tree_init(); - root = open_ctree(av[1], 0); + + while(1) { + int c; + c = getopt(ac, av, "e"); + if (c < 0) + break; + switch(c) { + case 'e': + extent_only = 1; + break; + default: + print_usage(); + } + } + ac = ac - optind; + if (ac != 1) + print_usage(); + + root = open_ctree(av[optind], 0); if (!root) { - fprintf(stderr, "unable to open %s\n", av[1]); + fprintf(stderr, "unable to open %s\n", av[optind]); exit(1); } - printf("root tree\n"); - btrfs_print_tree(root->fs_info->tree_root, - root->fs_info->tree_root->node); + if (!extent_only) { + printf("root tree\n"); + btrfs_print_tree(root->fs_info->tree_root, + root->fs_info->tree_root->node); + } btrfs_init_path(&path); key.offset = 0; key.objectid = 0; @@ -71,6 +161,8 @@ int main(int ac, char **av) { if (btrfs_key_type(&found_key) == BTRFS_ROOT_ITEM_KEY) { unsigned long offset; struct extent_buffer *buf; + int skip = extent_only; + offset = btrfs_item_ptr_offset(leaf, slot); read_extent_buffer(leaf, &ri, offset, sizeof(ri)); buf = read_tree_block(root->fs_info->tree_root, @@ -81,18 +173,27 @@ int main(int ac, char **av) { printf("root "); break; case BTRFS_EXTENT_TREE_OBJECTID: - printf("extent tree "); + skip = 0; + if (!extent_only) + printf("extent tree "); break; } - printf("tree %llu %u %llu\n", - (unsigned long long)found_key.objectid, - found_key.type, - (unsigned long long)found_key.offset); - btrfs_print_tree(root, buf); + if (!skip && !extent_only) { + printf("tree %llu %u %llu\n", + (unsigned long long)found_key.objectid, + found_key.type, + (unsigned long long)found_key.offset); + btrfs_print_tree(root, buf); + } else if (extent_only && !skip) { + print_extents(root, buf); + } } path.slots[0]++; } btrfs_release_path(root, &path); + if (extent_only) + return 0; + printf("total bytes %llu\n", (unsigned long long)btrfs_super_total_bytes(&root->fs_info->super_copy)); printf("bytes used %llu\n", |