On Tue, Oct 25, 2022 at 8:39 PM <crash-utility-request(a)redhat.com> wrote:
 Date: Tue, 25 Oct 2022 20:38:24 +0800
 From: Tao Liu <ltao(a)redhat.com>
 To: crash-utility(a)redhat.com
 Subject: [Crash-utility] [PATCH v2 5/6] Add do_maple_tree support for
         maple tree
 Message-ID: <20221025123825.36421-6-ltao(a)redhat.com>
 Content-Type: text/plain; charset="US-ASCII"; x-default=true
 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(a)redhat.com>
 ---
  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)); 
See comments below.
         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) 
The parameter name "rtp" looks a bit weird, could you please replace
the "rtp" with the "lp" and  update the above comment?
 +{
 +       struct do_maple_tree_info info = {
 +               .count          = 0,
 +               .data           = rtp, 
Ditto.
 +       };
 +
 +       memset(&maple_tree_ops, 0, sizeof(maple_tree_ops));
 +       memset(&cmd_tree_info, 0, sizeof(cmd_tree_info));
 +       maple_tree_ops.private = &info; 
Think about it again.  It could be good to use a local variable and
eventually pass the ops parameter to do_maple_tree_traverse(). Just
like:
//filesys.c
        struct do_radix_tree_info info = {
                .count          = 0,
                .data           = rtp,
        };
        struct radix_tree_ops ops = {
                .radix          = 16,
                .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; 
The above "return" seems to be redundant.
Thanks.
Lianbo
 +               }
 +               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