From db7212b1c7d9e61bb3cac1e24f7201dbf20245e2 Mon Sep 17 00:00:00 2001 From: Tomohiro Kusumi Date: Sat, 26 Mar 2016 12:19:11 +0900 Subject: [PATCH] sbin/hammer: Add depth indentation option to hammer show Print tab(s) based on the current depth in B-Tree. This makes hammer show output look like below instead of having everything without indentation. Depth indentation uses tabs instead of whitespaces because using 0x20s greatly increases the size of hammer show output. This option can be specifed by (-vvv are optional) # hammer -vvvf /dev/da1:/dev/da2:/dev/da3 show none indent With obfuscate option, it would be like # hammer -vvvf /dev/da1:/dev/da2:/dev/da3 show none indent,obfuscate With B-Tree search directive, it would be like # hammer -vvvf /dev/da1:/dev/da2:/dev/da3 show 1:00000001020bc6f7:... indent # hammer -vvvf /dev/da1:/dev/da2:/dev/da3 show 1:00000001020bc6f7:... obfuscate,indent With filter/nofilter option, it would be like # hammer -vvvf /dev/da1:/dev/da2:/dev/da3 show 1:00000001020bc6f7:... indent,filter # hammer -vvvf /dev/da1:/dev/da2:/dev/da3 show 1:00000001020bc6f7:... nofilter,indent # hammer -vvvf /dev/da1:/dev/da2:/dev/da3 show 1:00000001020bc6f7:... indent,filter,obfuscate Note that this commit also changes hammer show's suboption format mentioned above. Above examples are examples of the new format. The format used to be as follows, hammer [getopt options] show [search directives] ["filter"/"nofilter"] ["obfuscate"] but now it's hammer [getopt options] show [search directives] [comma separated suboptions] The format mentioned in 337ec5f is obsolete. This was necessary to keep simplicity of suboption format after search directives. The comma separated suboptions (filter,nofilter,obfuscate,indent) are not mentioned in hammer(8) manpage which means this change doesn't impact anyone (aside from real users almost never use this command in the first place). Having these suboptions just makes easier to debug or examine the structure in certain cases. -- NODE aaa parent=0 depth=0 ELM 0 ELM 1 ... ELM N NODE bbb parent=aaa depth=1 ELM 0 ELM 1 ... ELM N NODE ccc parent=aaa depth=1 ELM 0 ELM 1 ... ELM N NODE ddd parent=ccc depth=2 ELM 0 ELM 1 ... ELM N ... ... --- sbin/hammer/cmd_show.c | 96 ++++++++++++++++++++++++++---------------- sbin/hammer/hammer.c | 26 ++++++++---- sbin/hammer/hammer.h | 2 +- 3 files changed, 78 insertions(+), 46 deletions(-) diff --git a/sbin/hammer/cmd_show.c b/sbin/hammer/cmd_show.c index a3ebd62afb..28ad8d508a 100644 --- a/sbin/hammer/cmd_show.c +++ b/sbin/hammer/cmd_show.c @@ -47,13 +47,14 @@ struct { int limit; /* # of fields to test */ int filter; /* filter type (default -1) */ int obfuscate; /* obfuscate direntry name */ + int indent; /* use depth indentation */ struct zone_stat *stats; } opt; static __inline void print_btree(hammer_off_t node_offset); -static __inline void print_subtree(hammer_btree_elm_t elm, int depth); +static __inline void print_subtree(hammer_btree_elm_t elm); static void print_btree_node(hammer_off_t node_offset, - int depth, hammer_tid_t mirror_tid, + hammer_tid_t mirror_tid, hammer_base_elm_t left_bound, hammer_base_elm_t right_bound); static void print_btree_elm(hammer_node_ondisk_t node, hammer_off_t node_offset, @@ -83,15 +84,38 @@ static void hexdump_record(const void *ptr, int length, const char *hdr); static int num_bad_node = 0; static int num_bad_elm = 0; static int num_bad_rec = 0; +static int depth; + +#define _X "\t" +static const char* _indents[] = { + "", + _X, + _X _X, + _X _X _X, + _X _X _X _X, + _X _X _X _X _X, + _X _X _X _X _X _X, + _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X _X _X _X _X _X _X _X, + _X _X _X _X _X _X _X _X _X _X _X _X _X _X _X _X, + /* deep enough */ +}; +#define INDENT _indents[opt.indent ? depth : 0] void -hammer_cmd_show(const char *arg, int filter, int obfuscate) +hammer_cmd_show(const char *arg, int filter, int obfuscate, int indent) { struct volume_info *volume; struct hammer_volume_ondisk *ondisk; struct hammer_blockmap *blockmap; struct zone_stat *stats = NULL; - hammer_off_t node_offset; int zone; AssertOnFailure = (DebugOpt != 0); @@ -101,7 +125,6 @@ hammer_cmd_show(const char *arg, int filter, int obfuscate) volume = get_root_volume(); ondisk = volume->ondisk; - node_offset = ondisk->vol0_btree_root; if (QuietOpt < 3) { printf("Volume header\trecords=%jd next_tid=%016jx\n", (intmax_t)ondisk->vol0_stat_records, @@ -116,17 +139,16 @@ hammer_cmd_show(const char *arg, int filter, int obfuscate) } rel_volume(volume); - printf("show node=%016jx depth=%d arg=\"%s\"\n", - (uintmax_t)node_offset, 0, arg ? arg : ""); - bzero(&opt, sizeof(opt)); opt.filter = filter; opt.obfuscate = obfuscate; + opt.indent = indent; opt.stats = stats; if (init_btree_search(arg) > 0) { + printf("arg=\"%s\"", arg); if (opt.limit > 0) - printf(" search lo=%08x", opt.base.localization); + printf(" lo=%08x", opt.base.localization); if (opt.limit > 1) printf(" obj=%016jx", (uintmax_t)opt.base.obj_id); if (opt.limit > 2) @@ -137,7 +159,7 @@ hammer_cmd_show(const char *arg, int filter, int obfuscate) printf(" tid=%016jx", (uintmax_t)opt.base.create_tid); printf("\n"); } - print_btree(node_offset); + print_btree(ondisk->vol0_btree_root); if (VerboseOpt) { hammer_print_zone_stat(stats); @@ -159,21 +181,23 @@ static __inline void print_btree(hammer_off_t node_offset) { - print_btree_node(node_offset, 0, HAMMER_MAX_TID, NULL, NULL); + depth = -1; + print_btree_node(node_offset, HAMMER_MAX_TID, NULL, NULL); + assert(depth == -1); } static __inline void -print_subtree(hammer_btree_elm_t elm, int depth) +print_subtree(hammer_btree_elm_t elm) { - print_btree_node(elm->internal.subtree_offset, depth, + print_btree_node(elm->internal.subtree_offset, elm->internal.mirror_tid, &elm[0].base, &elm[1].base); } static void print_btree_node(hammer_off_t node_offset, - int depth, hammer_tid_t mirror_tid, - hammer_base_elm_t left_bound, hammer_base_elm_t right_bound) + hammer_tid_t mirror_tid, + hammer_base_elm_t left_bound, hammer_base_elm_t right_bound) { struct buffer_info *buffer = NULL; hammer_node_ondisk_t node; @@ -184,6 +208,7 @@ print_btree_node(hammer_off_t node_offset, char badm = ' '; /* good */ const char *ext; + depth++; node = get_node(node_offset, &buffer); if (node == NULL) { @@ -209,13 +234,8 @@ print_btree_node(hammer_off_t node_offset, if (badm != ' ' || badc != ' ') /* not good */ ++num_bad_node; - printf("%c%c NODE %016jx ", badc, badm, (uintmax_t)node_offset); - if (node == NULL) { - printf("(IO ERROR)\n"); - rel_buffer(buffer); - return; - } - + printf("%s%c%c NODE %016jx ", + INDENT, badc, badm, (uintmax_t)node_offset); printf("cnt=%02d p=%016jx type=%c depth=%d mirror=%016jx", node->count, (uintmax_t)node->parent, @@ -255,7 +275,7 @@ print_btree_node(hammer_off_t node_offset, print_btree_elm(node, node_offset, elm, left_bound, right_bound, NULL); } - printf(" }\n"); + printf("%s }\n", INDENT); if (node->type == HAMMER_BTREE_TYPE_INTERNAL) { for (i = 0; i < node->count; ++i) { @@ -265,7 +285,7 @@ print_btree_node(hammer_off_t node_offset, continue; } if (elm->internal.subtree_offset) { - print_subtree(elm, depth + 1); + print_subtree(elm); /* * Cause show to do normal iteration after * seeking to the lo:objid:rectype:key:tid @@ -277,6 +297,7 @@ print_btree_node(hammer_off_t node_offset, } } rel_buffer(buffer); + depth--; } static __inline @@ -365,14 +386,16 @@ print_btree_elm(hammer_node_ondisk_t node, hammer_off_t node_offset, else label = "ELM"; - printf("%s %s %2d %c ", flagstr, label, i, hammer_elm_btype(elm)); + printf("%s%s %s %2d %c ", + INDENT, flagstr, label, i, hammer_elm_btype(elm)); printf("lo=%08x obj=%016jx rt=%02x key=%016jx tid=%016jx\n", elm->base.localization, (uintmax_t)elm->base.obj_id, elm->base.rec_type, (uintmax_t)elm->base.key, (uintmax_t)elm->base.create_tid); - printf(" %c del=%016jx ot=%02x", + printf("%s %c del=%016jx ot=%02x", + INDENT, (rootelm == ' ' ? deleted : rootelm), (uintmax_t)elm->base.delete_tid, elm->base.obj_type); @@ -627,14 +650,15 @@ print_config(char *cfgtxt) { char *token; - printf("\n%17s", ""); + printf("\n%s%17s", INDENT, ""); printf("config text=\"\n"); if (cfgtxt != NULL) { while((token = strsep(&cfgtxt, "\r\n")) != NULL) if (strlen(token)) - printf("%17s %s\n", "", token); + printf("%s%17s %s\n", + INDENT, "", token); } - printf("%17s \"", ""); + printf("%s%17s \"", INDENT, ""); } static @@ -660,11 +684,11 @@ print_record(hammer_btree_elm_t elm) switch(elm->leaf.base.rec_type) { case HAMMER_RECTYPE_UNKNOWN: - printf("\n%17s", ""); + printf("\n%s%17s", INDENT, ""); printf("unknown"); break; case HAMMER_RECTYPE_INODE: - printf("\n%17s", ""); + printf("\n%s%17s", INDENT, ""); printf("inode size=%jd nlinks=%jd", (intmax_t)data->inode.size, (intmax_t)data->inode.nlinks); @@ -676,7 +700,7 @@ print_record(hammer_btree_elm_t elm) printf(" pobjid=%016jx ot=%02x\n", (uintmax_t)data->inode.parent_obj_id, data->inode.obj_type); - printf("%17s", ""); + printf("%s%17s", INDENT, ""); printf(" ctime=%016jx mtime=%016jx atime=%016jx", (uintmax_t)data->inode.ctime, (uintmax_t)data->inode.mtime, @@ -688,7 +712,7 @@ print_record(hammer_btree_elm_t elm) break; case HAMMER_RECTYPE_DIRENTRY: data_len -= HAMMER_ENTRY_NAME_OFF; - printf("\n%17s", ""); + printf("\n%s%17s", INDENT, ""); printf("dir-entry ino=%016jx lo=%08x", (uintmax_t)data->entry.obj_id, data->entry.localization); @@ -700,14 +724,14 @@ print_record(hammer_btree_elm_t elm) switch(elm->leaf.base.key) { case HAMMER_FIXKEY_SYMLINK: data_len -= HAMMER_SYMLINK_NAME_OFF; - printf("\n%17s", ""); + printf("\n%s%17s", INDENT, ""); printf("fix-symlink name=\"%*.*s\"", data_len, data_len, data->symlink.name); break; } break; case HAMMER_RECTYPE_PFS: - printf("\n%17s", ""); + printf("\n%s%17s", INDENT, ""); printf("pfs sync_beg_tid=%016jx sync_end_tid=%016jx\n", (intmax_t)data->pfsd.sync_beg_tid, (intmax_t)data->pfsd.sync_end_tid); @@ -726,7 +750,7 @@ print_record(hammer_btree_elm_t elm) free(str2); break; case HAMMER_RECTYPE_SNAPSHOT: - printf("\n%17s", ""); + printf("\n%s%17s", INDENT, ""); printf("snapshot tid=%016jx label=\"%s\"", (intmax_t)data->snap.tid, data->snap.label); break; diff --git a/sbin/hammer/hammer.c b/sbin/hammer/hammer.c index 04d1225240..793ec0df1e 100644 --- a/sbin/hammer/hammer.c +++ b/sbin/hammer/hammer.c @@ -531,21 +531,29 @@ main(int ac, char **av) const char *arg = NULL; int filter = -1; int obfuscate = 0; + int indent = 0; hammer_parsedevs(blkdevs); + if (ac > 3) + errx(1, "Too many options specified"); if (ac > 1) arg = av[1]; if (ac > 2) { - if (strcmp(av[2], "filter") == 0) - filter = 1; - else if (strcmp(av[2], "nofilter") == 0) - filter = 0; - } - if (ac > 3) { - if (strcmp(av[3], "obfuscate") == 0) - obfuscate = 1; + char *p, *buf = strdup(av[2]); + while((p = strsep(&buf, ",")) != NULL) { + if (strcmp(p, "filter") == 0) { + filter = 1; + } else if (strcmp(p, "nofilter") == 0) { + filter = 0; + } else if (strcmp(p, "obfuscate") == 0) { + obfuscate = 1; + } else if (strcmp(p, "indent") == 0) { + indent = 1; + } + } + free(buf); } - hammer_cmd_show(arg, filter, obfuscate); + hammer_cmd_show(arg, filter, obfuscate, indent); exit(0); } if (strcmp(av[0], "show-undo") == 0) { diff --git a/sbin/hammer/hammer.h b/sbin/hammer/hammer.h index 2d71fa04de..3679b90bc9 100644 --- a/sbin/hammer/hammer.h +++ b/sbin/hammer/hammer.h @@ -83,7 +83,7 @@ extern uint64_t MemoryLimit; extern const char *SplitupOptStr; extern const char *CyclePath; -void hammer_cmd_show(const char *arg, int filter, int obfuscate); +void hammer_cmd_show(const char *arg, int filter, int obfuscate, int indent); void hammer_cmd_show_undo(void); void hammer_cmd_sshremote(const char *cmd, const char *target); void hammer_cmd_recover(const char *target_dir); -- 2.41.0