On Wed, Dec 14, 2022 at 4:12 PM lijiang <lijiang@xxxxxxxxxx> wrote: > > On Tue, Dec 6, 2022 at 4:40 PM <crash-utility-request@xxxxxxxxxx> wrote: > > Date: Tue, 6 Dec 2022 16:40:18 +0800 > > From: Tao Liu <ltao@xxxxxxxxxx> > > To: crash-utility@xxxxxxxxxx > > Subject: [PATCH v3 2/6] Add tree cmd support for maple > > tree > > Message-ID: <20221206084022.58693-3-ltao@xxxxxxxxxx> > > Content-Type: text/plain; charset="US-ASCII"; x-default=true > > > > Maple tree is a new data structure for crash, so cmd_tree support is > > needed for users to dump and view the content of maple tree. This patch > > achieves this by porting mt_dump() and its related functions from kernel, > > and adapting them with tree cmd. > > > > We introduced a new -v arg specifically for dumping the complete > > content of maple tree: > > > > crash> tree -t maple 0xffff9034c006aec0 -v > > > > maple_tree(ffff9034c006aec0) flags 309, height 2 root 0xffff9034de70041e > > > > 0-18446744073709551615: node 0xffff9034de700400 depth 0 type 3 parent 0xffff9034c006aec1 contents:... > > 0-140112331583487: node 0xffff9034c01e8800 depth 1 type 1 parent 0xffff9034de700406 contents:... > > 0-94643156942847: (nil) > > 94643156942848-94643158024191: 0xffff9035131754c0 > > 94643158024192-94643160117247: (nil) > > ... > > > > The old tree args can work as well: > > > > crash> tree -t maple -r mm_struct.mm_mt 0xffff9034c006aec0 -p > > ffff9035131754c0 > > index: 0 position: root/0/1 > > ffff9035131751c8 > > index: 1 position: root/0/3 > > ffff9035131757b8 > > index: 2 position: root/0/4 > > ... > > > > crash> tree -t maple 0xffff9034c006aec0 -p -x -s vm_area_struct.vm_start,vm_end > > ffff9035131754c0 > > index: 0 position: root/0/1 > > vm_start = 0x5613d3c00000, > > vm_end = 0x5613d3d08000, > > ffff9035131751c8 > > index: 1 position: root/0/3 > > vm_start = 0x5613d3f07000, > > vm_end = 0x5613d3f0b000, > > ffff9035131757b8 > > index: 2 position: root/0/4 > > vm_start = 0x5613d3f0b000, > > vm_end = 0x5613d3f14000, > > .... > > > > Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> > > --- > > defs.h | 1 + > > maple_tree.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ > > tools.c | 64 ++++++++++++++++++++++++++++++++++++++-------------- > > 3 files changed, 110 insertions(+), 17 deletions(-) > > > > diff --git a/defs.h b/defs.h > > index 792b007..cc40cba 100644 > > --- a/defs.h > > +++ b/defs.h > > @@ -2704,6 +2704,7 @@ struct tree_data { > > #define TREE_PARSE_MEMBER (VERBOSE << 7) > > #define TREE_READ_MEMBER (VERBOSE << 8) > > #define TREE_LINEAR_ORDER (VERBOSE << 9) > > +#define TREE_STRUCT_VERBOSE (VERBOSE << 10) > > > > #define ALIAS_RUNTIME (1) > > #define ALIAS_RCLOCAL (2) > > diff --git a/maple_tree.c b/maple_tree.c > > index e27369b..756dc0a 100644 > > --- a/maple_tree.c > > +++ b/maple_tree.c > > @@ -186,6 +186,10 @@ static void do_mt_range64(void *maple_tree_mt, void *entry, > > > > maple_range_64_node = tmp_node + OFFSET(maple_node_mr64); > > > > + if (td && td->flags & TREE_STRUCT_VERBOSE) { > > + dump_mt_range64(maple_range_64_node); > > + } > > + > > for (i = 0; i < mt_slots[maple_range_64]; i++) { > > last = max; > > > > @@ -246,6 +250,10 @@ static void do_mt_arange64(void *maple_tree_mt, void *entry, > > > > maple_arange_64_node = tmp_node + OFFSET(maple_node_ma64); > > > > + if (td && td->flags & TREE_STRUCT_VERBOSE) { > > + dump_mt_arange64(maple_arange_64_node); > > + } > > + > > for (i = 0; i < mt_slots[maple_arange_64]; i++) { > > last = max; > > > > @@ -294,6 +302,50 @@ static void do_mt_entry(void *entry, unsigned long min, unsigned long max, > > > > if (!td) > > return; > > + > > + if (!td->count && td->structname_args) { > > + /* > > + * Retrieve all members' info only once (count == 0) > > + * After last iteration all memory will be freed up > > + */ > > + e = (struct req_entry **)GETBUF(sizeof(*e) * td->structname_args); > > + for (i = 0; i < td->structname_args; i++) > > + e[i] = fill_member_offsets(td->structname[i]); > > + } > > + > > + td->count++; > > + > > + if (td->flags & TREE_STRUCT_VERBOSE) { > > + dump_mt_entry(entry, min, max, depth); > > + } else if (td->flags & VERBOSE && entry) > > + fprintf(fp, "%lx\n", (ulong)entry); > > + if (td->flags & TREE_POSITION_DISPLAY && entry) > > + fprintf(fp, " index: %ld position: %s/%u\n", > > + (*global_index)++, path, index); > > + > > + if (td->structname) { > > + if (td->flags & TREE_STRUCT_RADIX_10) > > + print_radix = 10; > > + else if (td->flags & TREE_STRUCT_RADIX_16) > > + print_radix = 16; > > + else > > + print_radix = 0; > > + > > + for (i = 0; i < td->structname_args; i++) { > > + switch (count_chars(td->structname[i], '.')) { > > + case 0: > > + dump_struct(td->structname[i], > > + (ulong)entry, print_radix); > > + break; > > + default: > > + if (td->flags & TREE_PARSE_MEMBER) > > + dump_struct_members_for_tree(td, i, (ulong)entry); > > + else if (td->flags & TREE_READ_MEMBER) > > + dump_struct_members_fast(e[i], print_radix, (ulong)entry); > > + break; > > Seems the above "break" is redundant. The default is at the end of the > switch, it can be dropped. Thanks, I have removed it in v4. Thanks, Tao Liu > > Thanks. > Lianbo > > > + } > > + } > > + } > > } > > > > static void do_mt_node(void *maple_tree_mt, void *entry, > > @@ -313,6 +365,10 @@ static void do_mt_node(void *maple_tree_mt, void *entry, > > readmem((ulong)maple_node, KVADDR, tmp_node, SIZE(maple_node_struct), > > "mt_dump_node read maple_node", FAULT_ON_ERROR); > > > > + if (td && td->flags & TREE_STRUCT_VERBOSE) { > > + dump_mt_node(maple_node, tmp_node, type, min, max, depth); > > + } > > + > > switch (type) { > > case maple_dense: > > for (i = 0; i < mt_slots[maple_dense]; i++) { > > @@ -359,6 +415,12 @@ static int do_maple_tree_traverse(ulong ptr, int is_root, > > "mt_dump read maple_tree", FAULT_ON_ERROR); > > entry = *(void **)(tmp_tree + OFFSET(maple_tree_ma_root)); > > > > + if (td && td->flags & TREE_STRUCT_VERBOSE) { > > + fprintf(fp, "maple_tree(%lx) flags %X, height %u root %p\n\n", > > + ptr, *(unsigned int *)(tmp_tree + OFFSET(maple_tree_ma_flags)), > > + mt_height(tmp_tree), entry); > > + } > > + > > if (!xa_is_node(entry)) > > do_mt_entry(entry, 0, 0, 0, 0, path, &global_index, ops); > > else if (entry) { > > diff --git a/tools.c b/tools.c > > index 39306c1..4e72c60 100644 > > --- a/tools.c > > +++ b/tools.c > > @@ -30,7 +30,7 @@ static void dealloc_hq_entry(struct hq_entry *); > > static void show_options(void); > > static void dump_struct_members(struct list_data *, int, ulong); > > static void rbtree_iteration(ulong, struct tree_data *, char *); > > -static void dump_struct_members_for_tree(struct tree_data *, int, ulong); > > +void dump_struct_members_for_tree(struct tree_data *, int, ulong); > > > > struct req_entry { > > char *arg, *name, **member; > > @@ -40,8 +40,8 @@ struct req_entry { > > }; > > > > static void print_value(struct req_entry *, unsigned int, ulong, unsigned int); > > -static struct req_entry *fill_member_offsets(char *); > > -static void dump_struct_members_fast(struct req_entry *, int, ulong); > > +struct req_entry *fill_member_offsets(char *); > > +void dump_struct_members_fast(struct req_entry *, int, ulong); > > > > FILE * > > set_error(char *target) > > @@ -3666,7 +3666,7 @@ dump_struct_members_fast(struct req_entry *e, int radix, ulong p) > > } > > } > > > > -static struct req_entry * > > +struct req_entry * > > fill_member_offsets(char *arg) > > { > > int j; > > @@ -4307,6 +4307,7 @@ dump_struct_members(struct list_data *ld, int idx, ulong next) > > #define RADIXTREE_REQUEST (0x1) > > #define RBTREE_REQUEST (0x2) > > #define XARRAY_REQUEST (0x4) > > +#define MAPLE_REQUEST (0x8) > > > > void > > cmd_tree() > > @@ -4317,6 +4318,7 @@ cmd_tree() > > struct datatype_member struct_member, *sm; > > struct syment *sp; > > ulong value; > > + char *type_name = NULL; > > > > type_flag = 0; > > root_offset = 0; > > @@ -4324,25 +4326,33 @@ cmd_tree() > > td = &tree_data; > > BZERO(td, sizeof(struct tree_data)); > > > > - while ((c = getopt(argcnt, args, "xdt:r:o:s:S:plN")) != EOF) { > > + while ((c = getopt(argcnt, args, "xdt:r:o:s:S:plNv")) != EOF) { > > switch (c) > > { > > case 't': > > - if (type_flag & (RADIXTREE_REQUEST|RBTREE_REQUEST|XARRAY_REQUEST)) { > > + if (type_flag & (RADIXTREE_REQUEST|RBTREE_REQUEST|XARRAY_REQUEST|MAPLE_REQUEST)) { > > error(INFO, "multiple tree types may not be entered\n"); > > cmd_usage(pc->curcmd, SYNOPSIS); > > } > > > > if (STRNEQ(optarg, "ra")) > > - if (MEMBER_EXISTS("radix_tree_root", "xa_head")) > > + if (MEMBER_EXISTS("radix_tree_root", "xa_head")) { > > type_flag = XARRAY_REQUEST; > > - else > > + type_name = "Xarrays"; > > + } else { > > type_flag = RADIXTREE_REQUEST; > > - else if (STRNEQ(optarg, "rb")) > > + type_name = "radix trees"; > > + } > > + else if (STRNEQ(optarg, "rb")) { > > type_flag = RBTREE_REQUEST; > > - else if (STRNEQ(optarg, "x")) > > + type_name = "rbtrees"; > > + } else if (STRNEQ(optarg, "x")) { > > type_flag = XARRAY_REQUEST; > > - else { > > + type_name = "Xarrays"; > > + } else if (STRNEQ(optarg, "m")) { > > + type_flag = MAPLE_REQUEST; > > + type_name = "maple trees"; > > + } else { > > error(INFO, "invalid tree type: %s\n", optarg); > > cmd_usage(pc->curcmd, SYNOPSIS); > > } > > @@ -4417,6 +4427,9 @@ cmd_tree() > > "-d and -x are mutually exclusive\n"); > > td->flags |= TREE_STRUCT_RADIX_10; > > break; > > + case 'v': > > + td->flags |= TREE_STRUCT_VERBOSE; > > + break; > > default: > > argerrs++; > > break; > > @@ -4426,13 +4439,14 @@ cmd_tree() > > if (argerrs) > > cmd_usage(pc->curcmd, SYNOPSIS); > > > > - if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST)) && (td->flags & TREE_LINEAR_ORDER)) > > - error(FATAL, "-l option is not applicable to %s\n", > > - type_flag & RADIXTREE_REQUEST ? "radix trees" : "Xarrays"); > > + if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST|MAPLE_REQUEST)) && (td->flags & TREE_LINEAR_ORDER)) > > + error(FATAL, "-l option is not applicable to %s\n", type_name); > > > > - if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST)) && (td->flags & TREE_NODE_OFFSET_ENTERED)) > > - error(FATAL, "-o option is not applicable to %s\n", > > - type_flag & RADIXTREE_REQUEST ? "radix trees" : "Xarrays"); > > + if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST|MAPLE_REQUEST)) && (td->flags & TREE_NODE_OFFSET_ENTERED)) > > + error(FATAL, "-o option is not applicable to %s\n", type_name); > > + > > + if ((type_flag & (RBTREE_REQUEST|XARRAY_REQUEST|RADIXTREE_REQUEST)) && (td->flags & TREE_STRUCT_VERBOSE)) > > + error(FATAL, "-v option is not applicable to %s\n", type_name); > > > > if ((td->flags & TREE_ROOT_OFFSET_ENTERED) && > > (td->flags & TREE_NODE_POINTER)) > > @@ -4506,12 +4520,26 @@ next_arg: > > if (td->flags & TREE_STRUCT_RADIX_16) > > fprintf(fp, "%sTREE_STRUCT_RADIX_16", > > others++ ? "|" : ""); > > + if (td->flags & TREE_PARSE_MEMBER) > > + fprintf(fp, "%sTREE_PARSE_MEMBER", > > + others++ ? "|" : ""); > > + if (td->flags & TREE_READ_MEMBER) > > + fprintf(fp, "%sTREE_READ_MEMBER", > > + others++ ? "|" : ""); > > + if (td->flags & TREE_LINEAR_ORDER) > > + fprintf(fp, "%sTREE_LINEAR_ORDER", > > + others++ ? "|" : ""); > > + if (td->flags & TREE_STRUCT_VERBOSE) > > + fprintf(fp, "%sTREE_STRUCT_VERBOSE", > > + others++ ? "|" : ""); > > fprintf(fp, ")\n"); > > fprintf(fp, " type: "); > > if (type_flag & RADIXTREE_REQUEST) > > fprintf(fp, "radix\n"); > > else if (type_flag & XARRAY_REQUEST) > > fprintf(fp, "xarray\n"); > > + else if (type_flag & MAPLE_REQUEST) > > + fprintf(fp, "maple\n"); > > else > > fprintf(fp, "red-black%s", > > type_flag & RBTREE_REQUEST ? > > @@ -4532,6 +4560,8 @@ next_arg: > > do_rdtree(td); > > else if (type_flag & XARRAY_REQUEST) > > do_xatree(td); > > + else if (type_flag & MAPLE_REQUEST) > > + do_mptree(td); > > else > > do_rbtree(td); > > hq_close(); > > -- > > 2.33.1 > -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility Contribution Guidelines: https://github.com/crash-utility/crash/wiki