do_maple_tree() is similar to do_radix_tree() and do_xarray(), which takes the same do_maple_tree_traverse entry as tree cmd. Currently do_maple_tree() is not called by any other functions, we reserve it for future use. Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> --- defs.h | 6 +++ maple_tree.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/defs.h b/defs.h index 3f2453e..827e561 100644 --- a/defs.h +++ b/defs.h @@ -5581,6 +5581,12 @@ int cleanup_memory_driver(void); void maple_init(void); int do_mptree(struct tree_data *); +ulong do_maple_tree(ulong, int, struct list_pair *); +#define MAPLE_TREE_COUNT (1) +#define MAPLE_TREE_SEARCH (2) +#define MAPLE_TREE_DUMP (3) +#define MAPLE_TREE_GATHER (4) +#define MAPLE_TREE_DUMP_CB (5) /* * help.c diff --git a/maple_tree.c b/maple_tree.c index 33903cb..e8a287a 100644 --- a/maple_tree.c +++ b/maple_tree.c @@ -805,6 +805,13 @@ struct cmd_tree_info { struct tree_data *td; } cmd_tree_info; +struct maple_tree_ops { + void (*entry)(ulong node, ulong slot, const char *path, + ulong index, void *private); + uint radix; + void *private; +} maple_tree_ops; + static const char spaces[] = " "; static void do_mt_range64(const struct maple_tree *, void *, @@ -1028,6 +1035,10 @@ static void do_mt_entry(void *entry, unsigned long min, unsigned long max, int print_radix = 0, i; static struct req_entry **e = NULL; + if (maple_tree_ops.entry) + maple_tree_ops.entry((ulong)entry, (ulong)entry, path, max, + maple_tree_ops.private); + if (!cmd_tree_info.td) return; @@ -1162,12 +1173,150 @@ int do_mptree(struct tree_data *td) int is_root = !(td->flags & TREE_NODE_POINTER); memset(&cmd_tree_info, 0, sizeof(cmd_tree_info)); + memset(&maple_tree_ops, 0, sizeof(maple_tree_ops)); cmd_tree_info.td = td; do_maple_tree_traverse(td->start, is_root); return 0; } +/*************For do_maple_tree*****************/ +static void do_maple_tree_count(ulong node, ulong slot, const char *path, + ulong index, void *private) +{ + struct do_maple_tree_info *info = private; + info->count++; +} + +static void do_maple_tree_search(ulong node, ulong slot, const char *path, + ulong index, void *private) +{ + struct do_maple_tree_info *info = private; + struct list_pair *rtp = info->data; + + if (rtp->index == index) { + rtp->value = (void *)slot; + info->count = 1; + } +} + +static void do_maple_tree_dump(ulong node, ulong slot, const char *path, + ulong index, void *private) +{ + struct do_maple_tree_info *info = private; + fprintf(fp, "[%lu] %lx\n", index, slot); + info->count++; +} + +static void do_maple_tree_gather(ulong node, ulong slot, const char *path, + ulong index, void *private) +{ + struct do_maple_tree_info *info = private; + struct list_pair *rtp = info->data; + + if (info->maxcount) { + rtp[info->count].index = index; + rtp[info->count].value = (void *)slot; + + info->count++; + info->maxcount--; + } +} + +static void do_maple_tree_dump_cb(ulong node, ulong slot, const char *path, + ulong index, void *private) +{ + struct do_maple_tree_info *info = private; + struct list_pair *rtp = info->data; + int (*cb)(ulong) = rtp->value; + + /* Caller defined operation */ + if (!cb(slot)) { + error(FATAL, "do_maple_tree: callback " + "operation failed: entry: %ld item: %lx\n", + info->count, slot); + } + info->count++; +} + +/* + * do_maple_tree argument usage: + * + * root: Address of a maple_tree_root structure + * + * flag: MAPLE_TREE_COUNT - Return the number of entries in the tree. + * MAPLE_TREE_SEARCH - Search for an entry at rtp->index; if found, + * store the entry in rtp->value and return a count of 1; otherwise + * return a count of 0. + * MAPLE_TREE_DUMP - Dump all existing index/value pairs. + * MAPLE_TREE_GATHER - Store all existing index/value pairs in the + * passed-in array of list_pair structs starting at rtp, + * returning the count of entries stored; the caller can/should + * limit the number of returned entries by putting the array size + * (max count) in the rtp->index field of the first structure + * in the passed-in array. + * MAPLE_TREE_DUMP_CB - Similar with MAPLE_TREE_DUMP, but for each + * maple tree entry, a user defined callback at rtp->value will + * be invoked. + * + * rtp: Unused by MAPLE_TREE_COUNT and MAPLE_TREE_DUMP. + * A pointer to a list_pair structure for MAPLE_TREE_SEARCH. + * A pointer to an array of list_pair structures for + * MAPLE_TREE_GATHER; the dimension (max count) of the array may + * be stored in the index field of the first structure to avoid + * any chance of an overrun. + * For MAPLE_TREE_DUMP_CB, the rtp->value must be initialized as a + * callback function. The callback prototype must be: int (*)(ulong); + */ +ulong +do_maple_tree(ulong root, int flag, struct list_pair *rtp) +{ + struct do_maple_tree_info info = { + .count = 0, + .data = rtp, + }; + + memset(&maple_tree_ops, 0, sizeof(maple_tree_ops)); + memset(&cmd_tree_info, 0, sizeof(cmd_tree_info)); + maple_tree_ops.private = &info; + + switch (flag) + { + case MAPLE_TREE_COUNT: + maple_tree_ops.entry = do_maple_tree_count; + break; + + case MAPLE_TREE_SEARCH: + maple_tree_ops.entry = do_maple_tree_search; + break; + + case MAPLE_TREE_DUMP: + maple_tree_ops.entry = do_maple_tree_dump; + break; + + case MAPLE_TREE_GATHER: + if (!(info.maxcount = rtp->index)) + info.maxcount = (ulong)(-1); /* caller beware */ + + maple_tree_ops.entry = do_maple_tree_gather; + break; + + case MAPLE_TREE_DUMP_CB: + if (rtp->value == NULL) { + error(FATAL, "do_maple_tree: need set callback function"); + return -EINVAL; + } + maple_tree_ops.entry = do_maple_tree_dump_cb; + break; + + default: + error(FATAL, "do_maple_tree: invalid flag: %lx\n", flag); + } + + do_maple_tree_traverse(root, true); + return info.count; +} + /***********************************************/ void maple_init(void) { -- 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