v2: limit example to 80 columns and fill -l in synopsis as well
---
 defs.h  |  1 +
 help.c  | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 tools.c | 20 ++++++++++++++++++--
 3 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/defs.h b/defs.h
index adddb9f2748d..ec298cbd70be 100644
--- a/defs.h
+++ b/defs.h
@@ -2480,6 +2480,7 @@ struct tree_data {
 #define TREE_STRUCT_RADIX_16      (VERBOSE << 6)
 #define TREE_PARSE_MEMBER         (VERBOSE << 7)
 #define TREE_READ_MEMBER          (VERBOSE << 8)
+#define TREE_LINEAR_ORDER         (VERBOSE << 9)
 
 #define ALIAS_RUNTIME  (1)
 #define ALIAS_RCLOCAL  (2)
diff --git a/help.c b/help.c
index c5cec5365962..3f9a404ee3c0 100644
--- a/help.c
+++ b/help.c
@@ -5658,7 +5658,7 @@ NULL
 char *help_tree[] = {
 "tree",
 "display radix tree or red-black tree",
-"-t [radix|rbtree] [-r offset] [-[s|S] struct[.member[,member]] -[x|d]]\n      
    [-o offset] [-p] [-N] start",
+"-t [radix|rbtree] [-r offset] [-[s|S] struct[.member[,member]] -[x|d]]\n      
    [-o offset] [-p] [-l] [-N] start",
 "  This command dumps the contents of a radix tree or a red-black tree.",
 "  The arguments are as follows:\n",
 "    -t type  The type of tree to dump; the type string can be either ",
@@ -5698,6 +5699,8 @@ char *help_tree[] = {
 "             indicates \"root/l/r\" means that the node is the right child",
 "             of the left child of the root node.  For radix trees, the 
height",
 "             and slot index values are shown with respect to the root.",
+"         -l  Dump the tree sorted in linear order starting with the leftmost",
+"             node and progressing to the right.",
 " ",
 "  The meaning of the \"start\" argument, which can be expressed either in",
 "  hexadecimal format or symbolically, depends upon whether the -N option",
@@ -5823,6 +5826,59 @@ char *help_tree[] = {
 "    ffffea000407de58",
 "      position: root/3/28",
 "",
+"  Given the mm_struct address of 0xffff880074b5be80 list the VMA tree in 
linear",
+"  order from the leftmost node progressing to the right using the -l 
option:\n",
+"    %s> tree -ls vm_area_struct.vm_start -o vm_area_struct.vm_rb \\",
+"    -r mm_struct.mm_rb 0xffff880074b5be80 | paste - -",
+"    ffff88001f2c50e0    vm_start = 0x400000",
+"    ffff88001f2c5290    vm_start = 0xceb000",
+"    ffff880074bfc6c0    vm_start = 0xcec000",
+"    ffff88001f2c4bd0    vm_start = 0xd10000",
+"    ffff880074bfc948    vm_start = 0x1fe9000",
+"    ffff880036e54510    vm_start = 0x7ff6aa296000",
+"    ffff88001f2c5bd8    vm_start = 0x7ff6aa298000",
+"    ffff880036e54af8    vm_start = 0x7ff6aa497000",
+"    ffff880036e54f30    vm_start = 0x7ff6aa498000",
+"    ffff88000e06aa20    vm_start = 0x7ff6aa499000",
+"    ffff88000e06b368    vm_start = 0x7ff6ab95f000",
+"    ...",
+"    ffff88001f2c5e60    vm_start = 0x7ff6bc1af000",
+"    ffff88001f2c4ca8    vm_start = 0x7ff6bc1b6000",
+"    ffff88001f2c5008    vm_start = 0x7ff6bc200000",
+"    ffff88001f2c5d88    vm_start = 0x7ff6bc205000",
+"    ffff880074bfd6c8    vm_start = 0x7ff6bc206000",
+"    ffff88001f2c4288    vm_start = 0x7ff6bc207000",
+"    ffff88001f2c4510    vm_start = 0x7ffc7a5fc000",
+"    ffff88001f2c5b00    vm_start = 0x7ffc7a6d1000",
+"",
+"  Compared to the top/down root/leaves order:\n",
+"    %s> tree -s vm_area_struct.vm_start -o vm_area_struct.vm_rb \\",
+"    -r mm_struct.mm_rb 0xffff880074b5be80 | paste - -",
+"    ffff88001f2c5a28    vm_start = 0x7ff6bbbb9000",
+"    ffff88001f2c55f0    vm_start = 0x7ff6bb252000",
+"    ffff88000e06a360    vm_start = 0x7ff6ac6c3000",
+"    ffff88001f2c4bd0    vm_start = 0xd10000",
+"    ffff88001f2c5290    vm_start = 0xceb000",
+"    ffff88001f2c50e0    vm_start = 0x400000",
+"    ffff880074bfc6c0    vm_start = 0xcec000",
+"    ffff88000e06b368    vm_start = 0x7ff6ab95f000",
+"    ffff88001f2c5bd8    vm_start = 0x7ff6aa298000",
+"    ffff880074bfc948    vm_start = 0x1fe9000",
+"    ffff880036e54510    vm_start = 0x7ff6aa296000",
+"    ffff880036e54f30    vm_start = 0x7ff6aa498000",
+"    ffff880036e54af8    vm_start = 0x7ff6aa497000",
+"    ffff88000e06aa20    vm_start = 0x7ff6aa499000",
+"    ffff88000e06ae58    vm_start = 0x7ff6ac1df000",
+"    ffff88000e06ba28    vm_start = 0x7ff6abefc000",
+"    ffff88000e06a6c0    vm_start = 0x7ff6ac41b000",
+"    ffff88001f2c4000    vm_start = 0x7ff6bac75000",
+"    ffff88000e06bd88    vm_start = 0x7ff6b2d00000",
+"    ffff88000e06b440    vm_start = 0x7ff6b28de000",
+"    ...",
+"    ffff880074bfd6c8    vm_start = 0x7ff6bc206000",
+"    ffff88001f2c4510    vm_start = 0x7ffc7a5fc000",
+"    ffff88001f2c5b00    vm_start = 0x7ffc7a6d1000",
+"",
 "  Alternatively, take the address of the radix_tree_node from the",
 "  radix_tree_root structure in the address_space structure above,",
 "  and display the tree with the -N option:\n",
diff --git a/tools.c b/tools.c
index 7c7f65ac558b..b8e19e4284c5 100644
--- a/tools.c
+++ b/tools.c
@@ -3926,7 +3926,7 @@ cmd_tree()
        td = &tree_data;
        BZERO(td, sizeof(struct tree_data));
 
-       while ((c = getopt(argcnt, args, "xdt:r:o:s:S:pN")) != EOF) {
+       while ((c = getopt(argcnt, args, "xdt:r:o:s:S:plN")) != EOF) {
                switch (c)
                {
                case 't':
@@ -3993,6 +3993,10 @@ cmd_tree()
                        td->flags |= TREE_POSITION_DISPLAY;
                        break;
 
+               case 'l':
+                       td->flags |= TREE_LINEAR_ORDER;
+                       break;
+
                case 'N':
                        td->flags |= TREE_NODE_POINTER;
                        break;
@@ -4397,6 +4401,17 @@ rbtree_iteration(ulong node_p, struct tree_data *td, 
char *pos)
        else
                error(FATAL, "\nduplicate tree entry: %lx\n", node_p);
 
+       if (td->flags & TREE_LINEAR_ORDER &&
+                  readmem(node_p+OFFSET(rb_node_rb_left), KVADDR, &new_p,
+                       sizeof(void *), "rb_node rb_left", RETURN_ON_ERROR) && 
new_p)
+               if (readmem(new_p+OFFSET(rb_node_rb_left), KVADDR, &test_p,
+                       sizeof(void *), "rb_node rb_left", 
RETURN_ON_ERROR|QUIET)) {
+                       sprintf(new_pos, "%s/l", pos);
+                       rbtree_iteration(new_p, td, new_pos);
+               } else
+                       error(INFO, "rb_node: %lx: corrupted rb_left pointer: 
%lx\n",
+                                       node_p, new_p);
+
        struct_p = node_p - td->node_member_offset;
 
        if (td->flags & VERBOSE)
@@ -4430,7 +4445,8 @@ rbtree_iteration(ulong node_p, struct tree_data *td, char 
*pos)
                }
        }
 
-       if (       readmem(node_p+OFFSET(rb_node_rb_left), KVADDR, &new_p,
+       if (!(td->flags & TREE_LINEAR_ORDER) &&
+                  readmem(node_p+OFFSET(rb_node_rb_left), KVADDR, &new_p,
                        sizeof(void *), "rb_node rb_left", RETURN_ON_ERROR) && 
new_p)
                if (readmem(new_p+OFFSET(rb_node_rb_left), KVADDR, &test_p,
                        sizeof(void *), "rb_node rb_left", 
RETURN_ON_ERROR|QUIET)) {
-- 
2.17.0

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to