Re: [Crash-utility] [PATCH v2 3/6] Add tree cmd support for maple tree
by lijiang
On Tue, Oct 25, 2022 at 8:39 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Tue, 25 Oct 2022 20:38:22 +0800
> From: Tao Liu <ltao(a)redhat.com>
> To: crash-utility(a)redhat.com
> Subject: [Crash-utility] [PATCH v2 3/6] Add tree cmd support for maple
> tree
> Message-ID: <20221025123825.36421-4-ltao(a)redhat.com>
> 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 0 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
> ffff9034de70041e
> index: 0 position: root
> ffff9034c01e880c
> index: 1 position: root/0
> 0
> index: 2 position: root/0/0
> ffff9035131754c0
> index: 3 position: root/0/1
> 0
> index: 4 position: root/0/2
> ....
>
> crash> tree -t maple 0xffff9034c006aec0 -p -x -s vm_area_struct.vm_start,vm_end
> ffff9034de70041e
> index: 0 position: root
> ffff9034c01e880c
> index: 1 position: root/0
> 0
> index: 2 position: root/0/0
> ffff9035131754c0
> index: 3 position: root/0/1
> vm_start = 0x5613d3c00000,
> vm_end = 0x5613d3d08000,
> 0
> index: 4 position: root/0/2
> ...
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> defs.h | 5 +
> maple_tree.c | 385 +++++++++++++++++++++++++++++++++++++++++++++++++++
> tools.c | 20 ++-
> 3 files changed, 404 insertions(+), 6 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index 2978cec..3f2453e 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2191,12 +2191,15 @@ struct offset_table { /* stash of commonly-used offsets */
> long maple_arange_64_parent;
> long maple_arange_64_pivot;
> long maple_arange_64_slot;
> + long maple_arange_64_gap;
> long maple_arange_64_meta;
> long maple_range_64_parent;
> long maple_range_64_pivot;
> long maple_range_64_slot;
> + long maple_range_64_pad;
> long maple_range_64_meta;
> long maple_metadata_end;
> + long maple_metadata_gap;
> };
They have to be appended to the end of this table.
>
> struct size_table { /* stash of commonly-used sizes */
> @@ -2705,6 +2708,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 << 9)
>
> #define ALIAS_RUNTIME (1)
> #define ALIAS_RCLOCAL (2)
> @@ -5576,6 +5580,7 @@ int same_file(char *, char *);
> int cleanup_memory_driver(void);
>
> void maple_init(void);
> +int do_mptree(struct tree_data *);
>
> /*
> * help.c
> diff --git a/maple_tree.c b/maple_tree.c
> index 058b769..33903cb 100644
> --- a/maple_tree.c
> +++ b/maple_tree.c
> @@ -34,6 +34,7 @@
>
> unsigned char *mt_slots = NULL;
> unsigned char *mt_pivots = NULL;
> +unsigned long mt_max[4] = {0};
>
> #define MAPLE_BUFSIZE 512
>
> @@ -791,6 +792,382 @@ void *mas_find(struct ma_state *mas, unsigned long max)
> return mas_next_entry(mas, max);
> }
>
> +/***************For cmd_tree********************/
> +
> +struct do_maple_tree_info {
> + ulong maxcount;
> + ulong count;
> + void *data;
> +};
> +
> +struct cmd_tree_info {
> + ulong index;
> + struct tree_data *td;
> +} cmd_tree_info;
> +
> +static const char spaces[] = " ";
> +
> +static void do_mt_range64(const struct maple_tree *, void *,
> + unsigned long, unsigned long, unsigned int, char *);
> +static void do_mt_arange64(const struct maple_tree *, void *,
> + unsigned long, unsigned long, unsigned int, char *);
> +static void do_mt_entry(void *, unsigned long, unsigned long, unsigned int,
> + unsigned int, char *);
> +static void do_mt_node(const struct maple_tree *, void *, unsigned long,
> + unsigned long, unsigned int, char *);
> +struct req_entry *fill_member_offsets(char *);
> +void dump_struct_members_fast(struct req_entry *, int, ulong);
> +void dump_struct_members_for_tree(struct tree_data *, int, ulong);
> +
> +static void mt_dump_range(unsigned long min, unsigned long max,
> + unsigned int depth)
> +{
> + if (min == max)
> + fprintf(fp, "%.*s%lu: ", depth * 2, spaces, min);
> + else
> + fprintf(fp, "%.*s%lu-%lu: ", depth * 2, spaces, min, max);
> +}
> +
> +static inline bool mt_is_reserved(const void *entry)
> +{
> + return ((unsigned long)entry < MAPLE_RESERVED_RANGE) &&
> + xa_is_internal(entry);
> +}
> +
> +static inline bool mte_is_leaf(const struct maple_enode *entry)
> +{
> + return ma_is_leaf(mte_node_type(entry));
> +}
> +
> +static unsigned int mt_height(const struct maple_tree *mt)
> +{
> + return (*(unsigned int *)(mt + OFFSET(maple_tree_ma_flags)) &
> + MT_FLAGS_HEIGHT_MASK)
> + >> MT_FLAGS_HEIGHT_OFFSET;
> +}
> +
> +static void dump_mt_range64(struct maple_range_64 *node)
> +{
> + int i;
> +
> + fprintf(fp, " contents: ");
> + for (i = 0; i < mt_slots[maple_range_64] - 1; i++)
> + fprintf(fp, "%p %lu ",
> + *((void **)((char *)node + OFFSET(maple_range_64_slot)) + i),
> + *((unsigned long *)((char *)node + OFFSET(maple_range_64_pivot)) + i));
> + fprintf(fp, "%p\n", *((void **)((char *)node + OFFSET(maple_range_64_slot)) + i));
> +}
> +
> +static void dump_mt_arange64(struct maple_arange_64 *node)
> +{
> + int i;
> +
> + fprintf(fp, " contents: ");
> + for (i = 0; i < mt_slots[maple_arange_64]; i++)
> + fprintf(fp, "%lu ",
> + *((unsigned long *)((char *)node + OFFSET(maple_arange_64_gap)) + i));
> +
> + fprintf(fp, "| %02X %02X| ",
> + *((unsigned char *)node + OFFSET(maple_arange_64_meta) + OFFSET(maple_metadata_end)),
> + *((unsigned char *)node + OFFSET(maple_arange_64_meta) + OFFSET(maple_metadata_gap)));
> +
> + for (i = 0; i < mt_slots[maple_arange_64] - 1; i++)
> + fprintf(fp, "%p %lu ",
> + *((void **)((char *)node + OFFSET(maple_arange_64_slot)) + i),
> + *((unsigned long *)((char *)node + OFFSET(maple_arange_64_pivot)) + i));
> + fprintf(fp, "%p\n",
> + *((void **)((char *)node + OFFSET(maple_arange_64_slot)) + i));
> +}
> +
> +static void dump_mt_entry(void *entry, unsigned long min, unsigned long max,
> + unsigned int depth)
> +{
> + mt_dump_range(min, max, depth);
> +
> + if (xa_is_value(entry))
> + fprintf(fp, "value %ld (0x%lx) [%p]\n", xa_to_value(entry),
> + xa_to_value(entry), entry);
> + else if (xa_is_zero(entry))
> + fprintf(fp, "zero (%ld)\n", xa_to_internal(entry));
> + else if (mt_is_reserved(entry))
> + fprintf(fp, "UNKNOWN ENTRY (%p)\n", entry);
> + else
> + fprintf(fp, "%p\n", entry);
> +}
> +
> +static void dump_mt_node(struct maple_node *node, char *node_data,
> + unsigned int type, unsigned long min, unsigned long max,
> + unsigned int depth)
> +{
> + mt_dump_range(min, max, depth);
> +
> + fprintf(fp, "node %p depth %d type %d parent %p", node, depth, type,
> + node ? *(struct maple_pnode **)(node_data + OFFSET(maple_node_parent))
> + : NULL);
> +}
> +
> +static void do_mt_range64(const struct maple_tree *mt, void *entry,
> + unsigned long min, unsigned long max,
> + unsigned int depth, char *path)
> +{
> + struct maple_node *m_node = mte_to_node(entry);
> + unsigned char tmp_node[MAPLE_BUFSIZE];
> + bool leaf = mte_is_leaf(entry);
> + unsigned long first = min, last;
> + int i;
> + int len = strlen(path);
> +
> + assert(SIZE(maple_node_struct) <= MAPLE_BUFSIZE);
> +
> + readmem((ulonglong)m_node, KVADDR, tmp_node, SIZE(maple_node_struct),
> + "mt_dump_range64 read maple_node", FAULT_ON_ERROR);
> +
> + struct maple_range_64 *node = (struct maple_range_64 *)
> + (tmp_node + OFFSET(maple_node_mr64));
> +
> + if (cmd_tree_info.td) {
> + if (cmd_tree_info.td->flags & TREE_STRUCT_VERBOSE) {
> + dump_mt_range64(node);
> + }
> + if (cmd_tree_info.td->flags & TREE_POSITION_DISPLAY)
> + fprintf(fp, "%.*s index: %ld position: %s\n",
> + depth * 2, spaces, cmd_tree_info.index++, path);
> + }
> +
> + for (i = 0; i < mt_slots[maple_range_64]; i++) {
> + last = max;
> +
> + if (i < (mt_slots[maple_range_64] - 1))
> + last = *((unsigned long *)((char *)node + OFFSET(maple_range_64_pivot)) + i);
> + else if (!*((void **)((char *)node + OFFSET(maple_range_64_slot)) + i) &&
> + max != mt_max[mte_node_type(entry)])
> + break;
> + if (last == 0 && i > 0)
> + break;
> + if (leaf)
> + do_mt_entry(mt_slot(mt, (void **)((char *)node + OFFSET(maple_range_64_slot)), i),
> + first, last, depth + 1, i, path);
> + else if (*((void **)((char *)node + OFFSET(maple_range_64_slot)) + i)) {
> + sprintf(path + len, "/%d", i);
> + do_mt_node(mt, mt_slot(mt, (void **)((char *)node + OFFSET(maple_range_64_slot)), i),
> + first, last, depth + 1, path);
> + }
> +
> + if (last == max)
> + break;
> + if (last > max) {
> + fprintf(fp, "node %p last (%lu) > max (%lu) at pivot %d!\n",
> + node, last, max, i);
> + break;
> + }
> + first = last + 1;
> + }
> +}
> +
> +static void do_mt_arange64(const struct maple_tree *mt, void *entry,
> + unsigned long min, unsigned long max, unsigned int depth,
> + char *path)
> +{
> + struct maple_node *m_node = mte_to_node(entry);
> + unsigned char tmp_node[MAPLE_BUFSIZE];
> + bool leaf = mte_is_leaf(entry);
> + unsigned long first = min, last;
> + int i;
> + int len = strlen(path);
> +
> + assert(SIZE(maple_node_struct) <= MAPLE_BUFSIZE);
> +
> + readmem((ulonglong)m_node, KVADDR, tmp_node, SIZE(maple_node_struct),
> + "mt_dump_arange64 read maple_node", FAULT_ON_ERROR);
> +
> + struct maple_arange_64 *node = (struct maple_arange_64 *)
> + (tmp_node + OFFSET(maple_node_ma64));
> +
> + if (cmd_tree_info.td) {
> + if (cmd_tree_info.td->flags & TREE_STRUCT_VERBOSE) {
> + dump_mt_arange64(node);
> + }
> + if (cmd_tree_info.td->flags & TREE_POSITION_DISPLAY)
> + fprintf(fp, "%.*s index: %ld position: %s\n",
> + depth * 2, spaces, cmd_tree_info.index++, path);
> + }
> +
> + for (i = 0; i < mt_slots[maple_arange_64]; i++) {
> + last = max;
> +
> + if (i < (mt_slots[maple_arange_64] - 1))
> + last = *((unsigned long *)((char *)node + OFFSET(maple_arange_64_pivot)) + i);
> + else if (! *((void **)((char *)node + OFFSET(maple_arange_64_slot)) + i))
> + break;
> + if (last == 0 && i > 0)
> + break;
> +
> + if (leaf)
> + do_mt_entry(mt_slot(mt, (void **)((char *)node + OFFSET(maple_arange_64_slot)), i),
> + first, last, depth + 1, i, path);
> + else if (*((void **)((char *)node + OFFSET(maple_arange_64_slot)) + i)) {
> + sprintf(path + len, "/%d", i);
> + do_mt_node(mt, mt_slot(mt, (void **)((char *)node + OFFSET(maple_arange_64_slot)), i),
> + first, last, depth + 1, path);
> + }
> +
> + if (last == max)
> + break;
> + if (last > max) {
> + fprintf(fp, "node %p last (%lu) > max (%lu) at pivot %d!\n",
> + node, last, max, i);
> + break;
> + }
> + first = last + 1;
> + }
> +}
> +
> +static void do_mt_entry(void *entry, unsigned long min, unsigned long max,
> + unsigned int depth, unsigned int index, char *path)
> +{
> + int print_radix = 0, i;
> + static struct req_entry **e = NULL;
> +
> + if (!cmd_tree_info.td)
> + return;
> +
> + if (!cmd_tree_info.td->count && cmd_tree_info.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) * cmd_tree_info.td->structname_args);
> + for (i = 0; i < cmd_tree_info.td->structname_args; i++)
> + e[i] = fill_member_offsets(cmd_tree_info.td->structname[i]);
> + }
> +
> + cmd_tree_info.td->count++;
> +
> + if (cmd_tree_info.td->flags & TREE_STRUCT_VERBOSE) {
> + dump_mt_entry(entry, min, max, depth);
> + } else if (cmd_tree_info.td->flags & VERBOSE)
> + fprintf(fp, "%.*s%lx\n", depth * 2, spaces, (ulong)entry);
> + if (cmd_tree_info.td->flags & TREE_POSITION_DISPLAY)
> + fprintf(fp, "%.*s index: %ld position: %s/%u\n",
> + depth * 2, spaces, cmd_tree_info.index++, path, index);
> +
> + if (cmd_tree_info.td->structname) {
> + if (cmd_tree_info.td->flags & TREE_STRUCT_RADIX_10)
> + print_radix = 10;
> + else if (cmd_tree_info.td->flags & TREE_STRUCT_RADIX_16)
> + print_radix = 16;
> + else
> + print_radix = 0;
> +
> + for (i = 0; i < cmd_tree_info.td->structname_args; i++) {
> + switch (count_chars(cmd_tree_info.td->structname[i], '.')) {
> + case 0:
> + dump_struct(cmd_tree_info.td->structname[i],
> + (ulong)entry, print_radix);
> + break;
> + default:
> + if (cmd_tree_info.td->flags & TREE_PARSE_MEMBER)
> + dump_struct_members_for_tree(cmd_tree_info.td, i, (ulong)entry);
> + else if (cmd_tree_info.td->flags & TREE_READ_MEMBER)
> + dump_struct_members_fast(e[i], print_radix, (ulong)entry);
> + break;
> + }
> + }
> + }
> +}
> +
> +static void do_mt_node(const struct maple_tree *mt, void *entry,
> + unsigned long min, unsigned long max, unsigned int depth,
> + char *path)
> +{
> + struct maple_node *node = mte_to_node(entry);
> + unsigned int type = mte_node_type(entry);
> + unsigned int i;
> + char tmp_node[MAPLE_BUFSIZE];
> +
> + assert(SIZE(maple_node_struct) <= MAPLE_BUFSIZE);
> +
> + readmem((ulonglong)node, KVADDR, tmp_node, SIZE(maple_node_struct),
> + "mt_dump_node read maple_node", FAULT_ON_ERROR);
> +
> + if (cmd_tree_info.td) {
> + if (cmd_tree_info.td->flags & TREE_STRUCT_VERBOSE) {
> + dump_mt_node(node, tmp_node, type, min, max, depth);
> + } else if (cmd_tree_info.td->flags & VERBOSE)
> + fprintf(fp, "%.*s%lx\n", depth * 2, spaces, (ulong)entry);
> + }
> +
> + switch (type) {
> + case maple_dense:
> + if (cmd_tree_info.td &&
> + cmd_tree_info.td->flags & TREE_POSITION_DISPLAY)
> + fprintf(fp, "%.*s index: %ld position: %s\n",
> + depth * 2, spaces, cmd_tree_info.index++, path);
> + for (i = 0; i < mt_slots[maple_dense]; i++) {
> + if (min + i > max)
> + fprintf(fp, "OUT OF RANGE: ");
> + do_mt_entry(mt_slot(mt, (void **)(tmp_node + OFFSET(maple_node_slot)), i),
> + min + i, min + i, depth, i, path);
> + }
> + break;
> + case maple_leaf_64:
> + case maple_range_64:
> + do_mt_range64(mt, entry, min, max, depth, path);
> + break;
> + case maple_arange_64:
> + do_mt_arange64(mt, entry, min, max, depth, path);
> + break;
> + default:
> + fprintf(fp, " UNKNOWN TYPE\n");
> + }
> +}
> +
> +static int do_maple_tree_traverse(ulong ptr, int is_root)
> +{
> + char path[BUFSIZE] = {0};
> + unsigned char tmp_tree[MAPLE_BUFSIZE];
> + void *entry;
> +
Here, I would recommend checking if the related structures or members
are valid, just like this:
if (!VALID_STRUCT(maple_tree_struct) ||
!VALID_STRUCT(maple_node_struct) ||
!VALID_MEMBER(maple_tree_ma_root) ...)
error(FATAL,
"maple tree does not exist or has changed its
format\n");
...
Thanks.
Lianbo
> + assert(SIZE(maple_tree_struct) <= MAPLE_BUFSIZE);
> +
> + if (!is_root) {
> + strcpy(path, "direct");
> + do_mt_node(NULL, (void *)ptr, 0,
> + mt_max[mte_node_type((struct maple_enode *)ptr)], 0, path);
> + } else {
> + readmem((ulonglong)ptr, KVADDR, tmp_tree, SIZE(maple_tree_struct),
> + "mt_dump read maple_tree", FAULT_ON_ERROR);
> + entry = *(void **)(tmp_tree + OFFSET(maple_tree_ma_root));
> +
> + if (cmd_tree_info.td &&
> + cmd_tree_info.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((struct maple_tree *)tmp_tree), entry);
> + }
> +
> + if (!xa_is_node(entry))
> + do_mt_entry(entry, 0, 0, 0, 0, path);
> + else if (entry) {
> + strcpy(path, "root");
> + do_mt_node((struct maple_tree *)tmp_tree, entry, 0,
> + mt_max[mte_node_type(entry)], 0, path);
> + }
> + }
> + return 0;
> +}
> +
> +int do_mptree(struct tree_data *td)
> +{
> + int is_root = !(td->flags & TREE_NODE_POINTER);
> +
> + memset(&cmd_tree_info, 0, sizeof(cmd_tree_info));
> + cmd_tree_info.td = td;
> + do_maple_tree_traverse(td->start, is_root);
> +
> + return 0;
> +}
> +
> /***********************************************/
> void maple_init(void)
> {
> @@ -810,14 +1187,17 @@ void maple_init(void)
> MEMBER_OFFSET_INIT(maple_arange_64_parent, "maple_arange_64", "parent");
> MEMBER_OFFSET_INIT(maple_arange_64_pivot, "maple_arange_64", "pivot");
> MEMBER_OFFSET_INIT(maple_arange_64_slot, "maple_arange_64", "slot");
> + MEMBER_OFFSET_INIT(maple_arange_64_gap, "maple_arange_64", "gap");
> MEMBER_OFFSET_INIT(maple_arange_64_meta, "maple_arange_64", "meta");
>
> MEMBER_OFFSET_INIT(maple_range_64_parent, "maple_range_64", "parent");
> MEMBER_OFFSET_INIT(maple_range_64_pivot, "maple_range_64", "pivot");
> MEMBER_OFFSET_INIT(maple_range_64_slot, "maple_range_64", "slot");
> + MEMBER_OFFSET_INIT(maple_range_64_pad, "maple_range_64", "pad");
> MEMBER_OFFSET_INIT(maple_range_64_meta, "maple_range_64", "meta");
>
> MEMBER_OFFSET_INIT(maple_metadata_end, "maple_metadata", "end");
> + MEMBER_OFFSET_INIT(maple_metadata_gap, "maple_metadata", "gap");
>
> array_len = get_array_length("mt_slots", NULL, sizeof(char));
> mt_slots = calloc(array_len, sizeof(char));
> @@ -830,4 +1210,9 @@ void maple_init(void)
> readmem(symbol_value("mt_pivots"), KVADDR, mt_pivots,
> array_len * sizeof(char), "maple_init read mt_pivots",
> FAULT_ON_ERROR);
> +
> + mt_max[maple_dense] = mt_slots[maple_dense];
> + mt_max[maple_leaf_64] = ULONG_MAX;
> + mt_max[maple_range_64] = ULONG_MAX;
> + mt_max[maple_arange_64] = ULONG_MAX;
> }
> \ No newline at end of file
> diff --git a/tools.c b/tools.c
> index 39306c1..3cb93c1 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()
> @@ -4324,11 +4325,11 @@ 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);
> }
> @@ -4342,6 +4343,8 @@ cmd_tree()
> type_flag = RBTREE_REQUEST;
> else if (STRNEQ(optarg, "x"))
> type_flag = XARRAY_REQUEST;
> + else if (STRNEQ(optarg, "m"))
> + type_flag = MAPLE_REQUEST;
> else {
> error(INFO, "invalid tree type: %s\n", optarg);
> cmd_usage(pc->curcmd, SYNOPSIS);
> @@ -4417,6 +4420,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;
> @@ -4532,6 +4538,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
2 years
[PATCH V4 0/2] Support VMCOREINFO export for RISCV64
by Xianting Tian
As disscussed in below patch set, the patch of 'describe VMCOREINFO export in Documentation'
need to update according to Bagas's comments.
https://lore.kernel.org/linux-riscv/22AAF52E-8CC8-4D11-99CB-88DE4D113444@...
As others patches in above patch set already applied, so this patch set only contains below two
patches.
------
Changes:
Fix commit message in patch 2: use "Document these RISCV64 exports above" instead of
"This patch just add the description of VMCOREINFO export for RISCV64."
V1 -> V2:
Remove unnecessary overline above header text in patch 2.
V2 -> V3:
Fix commit message in patch 1,2;
Use 'space' instead of 'region' for vmemmap description in patch 2.
V3 -> V4:
Remove unnecessary kernel space export:
KASAN_SHADOW_START ~ KASAN_SHADOW_END,
ADDRESS_SPACE_END
Xianting Tian (2):
RISC-V: Add arch_crash_save_vmcoreinfo support
Documentation: kdump: describe VMCOREINFO export for RISCV64
.../admin-guide/kdump/vmcoreinfo.rst | 30 ++++++++++++++++++
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/crash_core.c | 29 +++++++++++++++++
3 files changed, 61 insertions(+)
create mode 100644 arch/riscv/kernel/crash_core.c
--
2.17.1
2 years, 1 month
Re: [Crash-utility] [PATCH] Fix segmentation fault when read_string() fails
by lijiang
On Tue, Oct 25, 2022 at 8:00 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Tue, 25 Oct 2022 05:48:25 +0000
> From: HAGIO KAZUHITO(?????) <k-hagio-ab(a)nec.com>
> To: "Discussion list for crash utility usage, maintenance and
> development" <crash-utility(a)redhat.com>, Matias Ezequiel Vara Larsen
> <matiasevara(a)gmail.com>
> Subject: Re: [Crash-utility] [PATCH] Fix segmentation fault when
> read_string() fails
> Message-ID: <a1a0ccda-4971-e7f6-a50f-492279ff4cbd(a)nec.com>
> Content-Type: text/plain; charset="utf-8"
>
> On 2022/10/24 18:35, Matias Ezequiel Vara Larsen wrote:
> > When read_string() fails, error() dereferences the name variable to print the
> > nullchar that the variable points to. However, name points to a nullchar that
> > is not in crash's memory-space thus triggering a segmentation fault. This
> > commit replaces %s in the error message with %p so the address is printed
> > instead.
>
> Thanks for the report and patch.
>
> I think that 'nullchar' means null-terminated string and it's a bit
> confusing, so I will replace it with 'string'.
>
> >
> > Signed-off-by: Matias Ezequiel Vara Larsen <matias.vara(a)vates.fr>
> > ---
> > memory.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/memory.c b/memory.c
> > index c80ef61..8a1c055 100644
> > --- a/memory.c
> > +++ b/memory.c
> > @@ -6599,7 +6599,7 @@ page_flags_init_from_pageflag_names(void)
> > }
> >
> > if (!read_string((ulong)name, namebuf, BUFSIZE-1)) {
> > - error(INFO, "failed to read pageflag_names entry (i: %d name: \"%s\" mask: %ld)\n",
> > + error(INFO, "failed to read pageflag_names entry (i: %d name: \"%p\" mask: %ld)\n",
>
> I will replace \"%p\" with %lx according to crash's convention.
>
> With the changes above,
>
> Acked-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
>
> I can fix them when merging in this case, you don't need to resend.
> Please wait for another ack.
>
This change looks good. So: Ack.
Thanks.
Lianbo
2 years, 1 month
Re: [Crash-utility] [PATCH v2 0/6] Add maple tree vma iteration support for crash
by lijiang
On Tue, Oct 25, 2022 at 8:39 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Tue, 25 Oct 2022 20:38:19 +0800
> From: Tao Liu <ltao(a)redhat.com>
> To: crash-utility(a)redhat.com
> Subject: [Crash-utility] [PATCH v2 0/6] Add maple tree vma iteration
> support for crash
> Message-ID: <20221025123825.36421-1-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> Patchset [1] introduces maple tree data structure for linux, and the
> modification on mm subsystem.
>
> The main impact on crash utility, is the modification on vm_area_struct.
> Patch [2][3] removed the rbtree and linked list iteration of
> vm_area_struct, making it impossible for crash to iterate vma
> in the traditional way. For example, we can observe the failing
> of crash cmd vm/fuser on kernel which has integrated with patchset [1].
>
> This patchset deals with the issue by porting and adapting
> kernel's maple tree vma iteration code to crash utility. It has been
> tested on linux-next-next-20220914 [4].
>
> [1]: https://lore.kernel.org/all/20220906194824.2110408-1-Liam.Howlett@oracle....
> [2]: https://github.com/oracle/linux-uek/commit/d19703645b80abe35dff1a88449d07...
> [3]: https://github.com/oracle/linux-uek/commit/91dee01f1ebb6b6587463b6ee6f7bb...
> [4]: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/snaps...
>
> v1 -> v2:
>
> 1) Move xarray.h and maple_tree_vma.h into maple.h.
> 2) Remove variable-length array for maple_tree.c.
> 3) Add tree cmd and do_maple_tree() support for maple tree.
Thank you for the update, Tao. We are getting back on the right path.
Lianbo
> 4) Other small modifications.
>
> Tao Liu (6):
> Port the maple tree data structures and main functions
> Introduce maple tree vma iteration to memory.c
> Add tree cmd support for maple tree
> Update the maple tree help info for tree cmd
> Add do_maple_tree support for maple tree
> Dump maple tree offset variables by help -o
>
> Makefile | 12 +-
> defs.h | 30 ++
> help.c | 45 +-
> maple_tree.c | 1367 ++++++++++++++++++++++++++++++++++++++++++++++++++
> maple_tree.h | 214 ++++++++
> memory.c | 319 +++++++-----
> symbols.c | 40 ++
> tools.c | 20 +-
> 8 files changed, 1885 insertions(+), 162 deletions(-)
> create mode 100644 maple_tree.c
> create mode 100644 maple_tree.h
>
> --
> 2.33.1
2 years, 2 months
[PATCH] Fix segmentation fault when read_string() fails
by Matias Ezequiel Vara Larsen
When read_string() fails, error() dereferences the name variable to print the
nullchar that the variable points to. However, name points to a nullchar that
is not in crash's memory-space thus triggering a segmentation fault. This
commit replaces %s in the error message with %p so the address is printed
instead.
Signed-off-by: Matias Ezequiel Vara Larsen <matias.vara(a)vates.fr>
---
memory.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/memory.c b/memory.c
index c80ef61..8a1c055 100644
--- a/memory.c
+++ b/memory.c
@@ -6599,7 +6599,7 @@ page_flags_init_from_pageflag_names(void)
}
if (!read_string((ulong)name, namebuf, BUFSIZE-1)) {
- error(INFO, "failed to read pageflag_names entry (i: %d name: \"%s\" mask: %ld)\n",
+ error(INFO, "failed to read pageflag_names entry (i: %d name: \"%p\" mask: %ld)\n",
i, name, mask);
goto pageflags_fail;
}
--
2.25.1
2 years, 2 months
[PATCH V3 0/2] Support VMCOREINFO export for RISCV64
by Xianting Tian
As disscussed in below patch set, the patch of 'describe VMCOREINFO export in Documentation'
need to update according to Bagas's comments.
https://lore.kernel.org/linux-riscv/22AAF52E-8CC8-4D11-99CB-88DE4D113444@...
As others patches in above patch set already applied, so this patch set only contains below two
patches.
------
Changes:
Fix commit message in patch 2: use "Document these RISCV64 exports above" instead of
"This patch just add the description of VMCOREINFO export for RISCV64."
V1 -> V2:
Remove unnecessary overline above header text in patch 2.
V2 -> V3:
Fix commit message in patch 1,2;
Use 'space' instead of 'region' for vmemmap description in patch 2.
Xianting Tian (2):
RISC-V: Add arch_crash_save_vmcoreinfo support
Documentation: kdump: describe VMCOREINFO export for RISCV64
.../admin-guide/kdump/vmcoreinfo.rst | 30 ++++++++++++++++++
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/crash_core.c | 29 +++++++++++++++++
3 files changed, 61 insertions(+)
create mode 100644 arch/riscv/kernel/crash_core.c
--
2.17.1
2 years, 2 months
[PATCH V2 0/2] Support VMCOREINFO export for RISCV64
by Xianting Tian
As disscussed in below patch set, the patch of 'describe VMCOREINFO export in Documentation'
need to update according to Bagas's comments.
https://lore.kernel.org/linux-riscv/22AAF52E-8CC8-4D11-99CB-88DE4D113444@...
As others patches in above patch set already applied, so this patch set only contains below two
patches.
------
Changes:
Fix commit message in patch 2: use "Document these RISCV64 exports above" instead of
"This patch just add the description of VMCOREINFO export for RISCV64."
V1 -> V2:
Remove unnecessary overline above header text in patch 2.
Xianting Tian (2):
RISC-V: Add arch_crash_save_vmcoreinfo support
Documentation: kdump: describe VMCOREINFO export for RISCV64
.../admin-guide/kdump/vmcoreinfo.rst | 30 ++++++++++++++++++
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/crash_core.c | 29 +++++++++++++++++
3 files changed, 61 insertions(+)
create mode 100644 arch/riscv/kernel/crash_core.c
--
2.17.1
2 years, 2 months
[PATCH 0/2] Support VMCOREINFO export for RISCV64
by Xianting Tian
As disscussed in below patch set, the patch of 'describe VMCOREINFO export in Documentation'
need to update according to Bagas's comments.
https://lore.kernel.org/linux-riscv/22AAF52E-8CC8-4D11-99CB-88DE4D113444@...
As others patches in above patch set already applied, so this patch set only contains below two
patches.
------
Changes:
Fix commit message in patch 2: use "Document these RISCV64 exports above" instead of
"This patch just add the description of VMCOREINFO export for RISCV64."
Xianting Tian (2):
RISC-V: Add arch_crash_save_vmcoreinfo support
Documentation: kdump: describe VMCOREINFO export for RISCV64
.../admin-guide/kdump/vmcoreinfo.rst | 31 +++++++++++++++++++
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/crash_core.c | 29 +++++++++++++++++
3 files changed, 61 insertions(+)
create mode 100644 arch/riscv/kernel/crash_core.c
--
2.17.1
2 years, 2 months