Re: Adding a new command rbtree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Modified. I remain the "-N" option. But for radix tree on RHEL5 or below, the height does not exist. So "-N" is not supported for radix tree on these version.

At 2012-5-30 3:56, Dave Anderson wrote:


----- Original Message -----


----- Original Message -----

As it turns out, the radix tree problem I reported seems to be an issue
associated with the kernel version.

But when I try the same thing on a RHEL5 kernel, it always fails like
this:

crash>  tree -t radix -r address_space.page_tree ffff81012eab2e00
radix_tree_node at ffff81011f9932e8
struct radix_tree_node {
   count = 0x6,
   slots = {0xffff810103c06490, 0xffff810103c1c760,
   0xffff810103c58580, 0xffff810103bfb750, 0xffff810103e84cd8,
   0xffff810103bf8b5
8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   tags = {{0x0}, {0x0}}
}
tree: height 1536 is greater than height_to_maxindex[]
                  index 12
crash>

The reason that the command fails on RHEL5 is due to this part of
your patch:

    3766 void rdtree_iteration(ulong node_p, struct tree_data *td, char * ppos, ulong indexnum)
    3767 {
    3768         uint height;
    3769         ulong slot;
    3770         int index;
    3771         int i;
    3772         char pos[BUFSIZE];
    3773
    3774         if (indexnum != -1)
    3775                 sprintf(pos, "%s/%ld", ppos, indexnum);
    3776         else
    3777                 sprintf(pos, "%s", ppos);
    3778
    3779         readmem(node_p + MEMBER_OFFSET("radix_tree_node", "height"), KVADDR,
    3780&height, sizeof(uint), "radix_tree_node height", FAULT_ON_ERROR);
    3781
    3782         if (height>  ARRAY_LENGTH(height_to_maxindex)) {
    3783                 fprintf(fp, "radix_tree_node at %lx\n", node_p);
    3784                 dump_struct("radix_tree_node", node_p, RADIX(16));
    3785                 error(FATAL, "height %d is greater than height_to_maxindex[] \
    3786                         index %ld\n", height, ARRAY_LENGTH(height_to_maxindex));
    3787         }

In line 3779, you calculate "height" using: MEMBER_OFFSET("radix_tree_node", "height")
which returns -1, because RHEL5's radix_tree_node does not have a "height" member:

   crash>  radix_tree_node
   struct radix_tree_node {
       unsigned int count;
       void *slots[64];
       long unsigned int tags[2][1];
   }
   SIZE: 536
   crash>

In RHEL6, a radix_tree_node structure does have a "height" member:

   crash>  radix_tree_node
   struct radix_tree_node {
       unsigned int height;
       unsigned int count;
       struct rcu_head rcu_head;
       void *slots[64];
       long unsigned int tags[3][1];
   }
   SIZE: 560
   crash>

In any case, I now see that your patch uses MEMBER_OFFSET(...) in 4 places:

$ grep MEMBER_OFFSET 0001-add-a-new-command-tree.patch
+       readmem(node_p + MEMBER_OFFSET("radix_tree_node", "height"), KVADDR,
+               readmem(td->start + MEMBER_OFFSET("rb_root", "rb_node"), KVADDR,
+       readmem(node_p+MEMBER_OFFSET("rb_node", "rb_left"), KVADDR,&left_p,
+       readmem(node_p+MEMBER_OFFSET("rb_node", "rb_right"), KVADDR,&right_p,
$

which is not acceptable, because it hides these kinds of programming errors.

For each of the 4 structure members above, add them to the offset_table[] array,
initialize them with MEMBER_OFFSET_INIT(), and use OFFSET(...) instead of
MEMBER_OFFSET().  Then if your code is incorrect as above, it will fail
immediately and show a meaningful error message.

Dave



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




--
--
Regards
Qiao Nuohan


>From b2ff168c0e5320e6181d4fd21a0d046fce1ffc3d Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@xxxxxxxxxxxxxx>
Date: Wed, 30 May 2012 19:36:57 +0800
Subject: [PATCH] add a new command tree

---
 defs.h        |   22 +++
 filesys.c     |    8 +
 global_data.c |    1 +
 help.c        |  105 +++++++++++++++
 symbols.c     |    9 ++
 tools.c       |  399 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 544 insertions(+), 0 deletions(-)

diff --git a/defs.h b/defs.h
index 77a623d..a61d33b 100755
--- a/defs.h
+++ b/defs.h
@@ -1649,6 +1649,10 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long module_init_size;
 	long module_percpu;
 	long radix_tree_node_slots;
+	long radix_tree_node_height;
+	long rb_root_rb_node;
+	long rb_node_rb_left;
+	long rb_node_rb_right;
 	long s390_stack_frame_back_chain;
 	long s390_stack_frame_r14;
 	long user_regs_struct_eip;
@@ -2075,6 +2079,20 @@ struct list_data {             /* generic structure used by do_list() to walk */
 #define RETURN_ON_DUPLICATE  (VERBOSE << 5)
 #define RETURN_ON_LIST_ERROR (VERBOSE << 6)
 
+struct tree_data {
+	ulong flags;
+	ulong start;
+	long member_offset;  // indicate the offset of the memberi(tree node)
+	char **structname;
+	int structname_args;
+};
+
+#define TREE_ROOT_OFFSET_ENTERED  (VERBOSE << 1)
+#define TREE_OFFSET_ENTERED       (VERBOSE << 2)
+#define TREE_START_ENTERED        (VERBOSE << 3)
+#define TREE_NODE_POINTER         (VERBOSE << 4)
+#define TREE_POSITION_DISPLAY     (VERBOSE << 5)
+
 #define ALIAS_RUNTIME  (1)
 #define ALIAS_RCLOCAL  (2)
 #define ALIAS_RCHOME   (3)
@@ -3654,6 +3672,7 @@ void cmd_ascii(void);        /* tools.c */
 void cmd_set(void);          /* tools.c */
 void cmd_eval(void);         /* tools.c */
 void cmd_list(void);         /* tools.c */
+void cmd_tree(void);         /* tools.c */
 void cmd_template(void);     /* tools.c */
 void cmd_alias(void);        /* cmdline.c */
 void cmd_repeat(void);       /* cmdline.c */
@@ -3829,6 +3848,8 @@ char *shift_string_right(char *, int);
 int bracketed(char *, char *, int);
 void backspace(int);
 int do_list(struct list_data *);
+void do_rdtree(struct tree_data *);
+void do_rbtree(struct tree_data *);
 int retrieve_list(ulong *, int);
 long power(long, int);
 long long ll_power(long long, long long);
@@ -4145,6 +4166,7 @@ extern char *help_help[];
 extern char *help_irq[];
 extern char *help_kmem[];
 extern char *help__list[];
+extern char *help_tree[];
 extern char *help_log[];
 extern char *help_mach[];
 extern char *help_mod[];
diff --git a/filesys.c b/filesys.c
index 5c45a8f..f1ad224 100755
--- a/filesys.c
+++ b/filesys.c
@@ -2024,7 +2024,15 @@ vfs_init(void)
 			"radix_tree_root","rnode");
 		MEMBER_OFFSET_INIT(radix_tree_node_slots, 
 			"radix_tree_node","slots");
-	}
+		MEMBER_OFFSET_INIT(radix_tree_node_height, 
+			"radix_tree_node","height");
+	}
+	MEMBER_OFFSET_INIT(rb_root_rb_node, 
+		"rb_root","rb_node");
+	MEMBER_OFFSET_INIT(rb_node_rb_left, 
+		"rb_node","rb_left");
+	MEMBER_OFFSET_INIT(rb_node_rb_right, 
+		"rb_node","rb_right");
 }
 
 void
diff --git a/global_data.c b/global_data.c
index 98a5a79..e2e60de 100755
--- a/global_data.c
+++ b/global_data.c
@@ -99,6 +99,7 @@ struct command_table_entry linux_command_table[] = {
 	{"ptob",    cmd_ptob,    help_ptob,    0},
 	{"ptov",    cmd_ptov,    help_ptov,    0},
         {"q",       cmd_quit,    help_quit,    0},
+        {"tree",    cmd_tree,    help_tree,    0},
         {"rd",      cmd_rd,      help_rd,      0},
 	{"repeat",  cmd_repeat,  help_repeat,  0},
 	{"runq",    cmd_runq,    help_runq,    REFRESH_TASK_TABLE},
diff --git a/help.c b/help.c
index 8ce8247..b2970c7 100755
--- a/help.c
+++ b/help.c
@@ -4445,6 +4445,111 @@ char *help__list[] = {
 NULL               
 };
 
+char *help_tree[] = {
+"tree",
+"display tree",
+"-t [radix|radixtree] [-r offset] [-s struct[.member[,member]]] [-p] [-N] start\n"
+"-t [rb|rbtree] [-r offset] [-o offset] [-s struct[.member[,member]]] [-p] [-N] start",
+"  This command dumps the contents of radix tree or red-black tree.",
+" ",
+"  The arguments are as follows:\n",
+"      -t type  It indicates the type of tree which is going to be dumped. The",
+"               argument \"type\" can be one of radix, radixtree, rb and rbtree(",
+"               radix and radixtree means radix tree, rb and rbtree means red-black",
+"               tree).",
+"    -r offset  The offset of radix_tree_root(radix tree) or rb_root(red-black",
+"               tree), default is 0.If non-zero, the offset may be entered in",
+"               either of two manners:\n",
+"               1. \"structure.member\" format", 
+"               2. A number.\n",
+"    -o offset  The offset of rb_node(red-black tree). Its format is same as \"-r",
+"               offset\"",
+"    -s struct  For each leaves' address of radix tree, format and print as this",
+"               type of structure; use the \"struct.member\" format in order to",
+"               display a particular member of the structure.  To display multiple",
+"               members of a structure, use a comma-separated list of members.",
+"           -p  Display the node's position information which indicates the",
+"               relationship between it and the root. The root means the node with",
+"               the biggest height offered by command's options. The information,",
+"               such as \"root/l/r\" indicates the node is the right child of the",
+"               left child of the root node.",
+" ",
+"  The meaning of the \"start\" argument, which can be expressed either",
+"  symbolically or in hexadecimal format, depends upon whether the -N option",
+"  is pre-pended or not:",
+" ",
+"        start  The address of the structure where radix_tree_root(radix tree)",
+"               or rb_node(red-black tree)",
+"     -N start  The address of the structure radix_tree_node(radix tree) or",
+"               rb_node(red-black tree)",
+"\nEXAMPLES",
+"  Display radix tree's address and position information only:\n",
+"    %s> tree -t radix -r address_space.page_tree -p ffff880047875de0",
+"    ffffea0000071298",
+"    position: root/0/0",
+"    ffffea0000065a30",
+"    position: root/0/1",
+"    ffffea00000664e8",
+"    position: root/0/2",
+"    ...",
+"    ffffea0000072f40",
+"    position: root/5/46",
+"    ffffea0000072f78",
+"    position: root/5/47",
+"    ffffea0000072990",
+"    position: root/5/48",
+"    ...",
+" ",
+"  Display radix tree, offering radix_tree_node's address:\n",
+"    %s> tree -t radix -p -N 0xffff8800478734b1 -s page.flag",
+"    ffffea0000071298",
+"    position: root/0/0",
+"      flags = 9007199254872172",
+"    ffffea0000065a30",
+"    position: root/0/1",
+"    ...",
+"    ffffea000004a4b0",
+"    position: root/1/61",
+"      flags = 9007199254872172",
+"    ffffea000004a4e8",
+"    position: root/1/62",
+"      flags = 9007199254872172",
+"    ...",
+" ",
+"  Display red-black tree:\n",
+"    %s> tree -t rb -r mm_struct.mm_rb -o vm_area_struct.vm_rb -p 0xffff880037b3ed00 -s vm_area_struct.vm_rb",
+"    ffff88004816a2d8",
+"    position: root",
+"      vm_rb = {",
+"        rb_parent_color = 1, ",
+"        rb_right = 0xffff88004816aae0, ",
+"        rb_left = 0xffff88004816ff08",
+"      }",
+"    ffff88004816fed0",
+"    position: root/l",
+"      vm_rb = {",
+"        rb_parent_color = 18446612133523661584, ",
+"        rb_right = 0xffff88004816fd78, ",
+"        rb_left = 0xffff88004816a6f8",
+"      }",
+"    ...",
+"    ffff88004816fbb0",
+"    position: root/r/l/l/r",
+"      vm_rb = {",
+"        rb_parent_color = 18446612133523661384, ",
+"        rb_right = 0x0, ",
+"        rb_left = 0x0",
+"      }",
+"    ffff88004816a5f8",
+"    position: root/r/l/r",
+"      vm_rb = {",
+"        rb_parent_color = 18446612133523662185, ",
+"        rb_right = 0xffff88004816a4a0, ",
+"        rb_left = 0x0",
+"      }",
+"    ...",
+NULL
+};
 
 char *help_ptob[] = {
 "ptob",
diff --git a/symbols.c b/symbols.c
index a98df87..9f9a9a7 100755
--- a/symbols.c
+++ b/symbols.c
@@ -8535,6 +8535,15 @@ dump_offset_table(char *spec, ulong makestruct)
                 OFFSET(radix_tree_root_rnode));
         fprintf(fp, "         radix_tree_node_slots: %ld\n",
                 OFFSET(radix_tree_node_slots));
+        fprintf(fp, "        radix_tree_node_height: %ld\n",
+                OFFSET(radix_tree_node_height));
+
+        fprintf(fp, "               rb_root_rb_node: %ld\n",
+                OFFSET(rb_root_rb_node));
+        fprintf(fp, "               rb_node_rb_left: %ld\n",
+                OFFSET(rb_node_rb_left));
+        fprintf(fp, "              rb_node_rb_right: %ld\n",
+                OFFSET(rb_node_rb_right));
 
 	fprintf(fp, "            x8664_pda_pcurrent: %ld\n",
 		OFFSET(x8664_pda_pcurrent));
diff --git a/tools.c b/tools.c
index 7cc580a..48d1823 100755
--- a/tools.c
+++ b/tools.c
@@ -24,6 +24,16 @@ struct hq_entry;
 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 rdtree_iteration(ulong, struct tree_data *, char *, ulong, uint);
+static void dump_struct_members_for_tree(struct tree_data *, int, ulong);
+
+#define RADIXTREE_REQUEST (0x1)
+#define RBTREE_REQUEST    (0x2)
+
+static ulong RADIX_TREE_MAP_SHIFT = UNINITIALIZED;
+static ulong RADIX_TREE_MAP_SIZE = UNINITIALIZED;
+static ulong RADIX_TREE_MAP_MASK = UNINITIALIZED;
 
 /*
  *  General purpose error reporting routine.  Type INFO prints the message
@@ -3507,6 +3517,395 @@ dump_struct_members(struct list_data *ld, int idx, ulong next)
 	FREEBUF(members);
 }
 
+void
+cmd_tree()
+{
+	int c;
+	int type_flag;
+	long root_offset;
+	struct tree_data tree_data, *td;
+	struct datatype_member struct_member, *sm;
+	struct syment *sp;
+	ulong value;
+
+	type_flag = 0;
+	root_offset = 0;
+	sm = &struct_member;
+	td = &tree_data;
+	BZERO(td, sizeof(struct tree_data));
+
+	while ((c = getopt(argcnt, args, "t:r:o:s:pN")) != EOF) {
+		switch (c)
+		{
+		case 't':
+			if (type_flag & (RADIXTREE_REQUEST|RBTREE_REQUEST)) {
+				error(INFO, "multiple type format not support\n");
+				cmd_usage(pc->curcmd, SYNOPSIS);
+			}
+
+			if (STREQ(optarg, "radix") || STREQ(optarg, "radixtree"))
+				type_flag = RADIXTREE_REQUEST;
+			else if (STREQ(optarg, "rb") || STREQ(optarg, "rbtree"))
+				type_flag = RBTREE_REQUEST;
+			else {
+				error(INFO, "invalid type %s\n", optarg);
+				cmd_usage(pc->curcmd, SYNOPSIS);
+			}
+				
+			break;
+
+		case 'r':
+			if (td->flags & TREE_ROOT_OFFSET_ENTERED) 
+                               error(FATAL,
+                                "root offset value %d (0x%lx) already entered\n",
+                                        td->member_offset, td->member_offset);
+			else if (IS_A_NUMBER(optarg)) 
+				root_offset = stol(optarg, FAULT_ON_ERROR, NULL);
+			else if (arg_to_datatype(optarg, sm, RETURN_ON_ERROR) > 1) 
+				root_offset = sm->member_offset;
+			else
+				error(FATAL, "invalid -r argument: %s\n",
+					optarg);
+
+			td->flags |= TREE_ROOT_OFFSET_ENTERED; 
+			break;
+
+		case 'o':
+			if (td->flags & TREE_OFFSET_ENTERED) 
+                               error(FATAL,
+                                "offset value %d (0x%lx) already entered\n",
+                                        td->member_offset, td->member_offset);
+			else if (IS_A_NUMBER(optarg)) 
+				td->member_offset = stol(optarg, 
+					FAULT_ON_ERROR, NULL);
+			else if (arg_to_datatype(optarg, sm, RETURN_ON_ERROR) > 1) 
+				td->member_offset = sm->member_offset;
+			else
+				error(FATAL, "invalid -o argument: %s\n",
+					optarg);
+
+			td->flags |= TREE_OFFSET_ENTERED; 
+			break;
+
+		case 's':
+			if (td->structname_args++ == 0) 
+				hq_open();
+			hq_enter((ulong)optarg);
+			break;
+
+		case 'p':
+			td->flags |= TREE_POSITION_DISPLAY;
+			break;
+
+		case 'N':
+			td->flags |= TREE_NODE_POINTER;
+			break;
+
+		default:
+			argerrs++;
+			break;
+		}
+	}
+
+	if (argerrs)
+		cmd_usage(pc->curcmd, SYNOPSIS);
+
+	if ((type_flag & RADIXTREE_REQUEST) && (td->flags & TREE_OFFSET_ENTERED))
+		error(FATAL, "\"-o offset\" is not supported for radix tree\n");
+
+	if ((td->flags & TREE_ROOT_OFFSET_ENTERED) &&
+		(td->flags |= TREE_NODE_POINTER))
+		error(INFO, "\"-r offset\" is useless when specified \"-N\"");
+
+	if (!args[optind]) {
+		error(INFO, "starting address required\n");
+		cmd_usage(pc->curcmd, SYNOPSIS);
+	}
+
+	if ((sp = symbol_search(args[optind]))) {
+		td->start = sp->value;
+		goto next_arg;
+	}
+
+	if (!IS_A_NUMBER(args[optind])) {	
+		if (can_eval(args[optind])) {
+			value = eval(args[optind], FAULT_ON_ERROR, NULL);
+			if (IS_KVADDR(value)) {
+				td->start = value;
+				goto next_arg;
+			}
+		}
+		error(FATAL, "invalid argument: %s\n", args[optind]);
+	} 
+
+	if (hexadecimal_only(args[optind], 0)) {
+		value = htol(args[optind], FAULT_ON_ERROR, NULL);
+		if (IS_KVADDR(value)) {
+			td->start = value;
+			goto next_arg;
+		}
+	}
+	 
+	error(FATAL, "invalid argument: %s\n", args[optind]);
+
+next_arg:
+	if (args[optind+1]) {
+		error(INFO, "too many arguments\n");
+		cmd_usage(pc->curcmd, SYNOPSIS);
+	}
+
+	if (td->structname_args) {
+		td->structname = (char **)GETBUF(sizeof(char *) *
+				td->structname_args);
+		retrieve_list((ulong *)td->structname, td->structname_args); 
+		hq_close();
+	}
+
+	if (!(td->flags & TREE_NODE_POINTER)) {
+		td->start = td->start + root_offset;
+	}
+
+	td->flags &= ~(TREE_OFFSET_ENTERED|TREE_START_ENTERED);
+	td->flags |= VERBOSE;
+
+	if (CRASHDEBUG(1)) {
+		console("           type: %s\n",
+			type_flag & RADIXTREE_REQUEST ? "radix" : "rb");
+		console("   node pointer: %s\n",
+			td->flags & TREE_NODE_POINTER ? "yes" : "no");
+		console("          start: %lx\n", td->start);
+		console("  member_offset: %ld\n", td->member_offset);
+		console("structname_args: %d\n", td->structname_args);
+	}
+
+	hq_open();
+	if (type_flag & RADIXTREE_REQUEST)
+		do_rdtree(td);
+	else
+		do_rbtree(td);
+	hq_close();
+
+        if (td->structname_args)
+		FREEBUF(td->structname);
+}
+
+void
+do_rdtree(struct tree_data *td)
+{
+	long nlen;
+	ulong node_p;
+	uint height;
+	char pos[BUFSIZE];
+
+	if (!VALID_STRUCT(radix_tree_root) || !VALID_STRUCT(radix_tree_node) ||
+		!VALID_MEMBER(radix_tree_root_height) ||
+		!VALID_MEMBER(radix_tree_root_rnode) ||
+		!VALID_MEMBER(radix_tree_node_slots) ||
+		!ARRAY_LENGTH(height_to_maxindex)) 
+		error(FATAL, "radix trees do not exist (or have changed "
+			"their format)\n");
+
+	if (RADIX_TREE_MAP_SHIFT == UNINITIALIZED) {
+		if (!(nlen = datatype_info("radix_tree_node", "slots", 
+		    MEMBER_SIZE_REQUEST)))
+			error(FATAL, "cannot determine length of " 
+				     "radix_tree_node.slots[] array\n");
+		nlen /= sizeof(void *);
+		RADIX_TREE_MAP_SHIFT = ffsl(nlen) - 1;
+		RADIX_TREE_MAP_SIZE = (1UL << RADIX_TREE_MAP_SHIFT);
+		RADIX_TREE_MAP_MASK = (RADIX_TREE_MAP_SIZE-1);
+	}
+
+	if (td->flags & TREE_NODE_POINTER) {
+		node_p = td->start;
+		if (!VALID_MEMBER(radix_tree_node_height)) {
+			readmem(node_p + OFFSET(radix_tree_node_height), KVADDR,
+				&height, sizeof(uint), "radix_tree_node height",
+				FAULT_ON_ERROR);
+
+			if (height > ARRAY_LENGTH(height_to_maxindex)) {
+				fprintf(fp, "radix_tree_node at %lx\n", node_p);
+				dump_struct("radix_tree_node", node_p, RADIX(16));
+				error(FATAL, "height %d is greater than "
+					"height_to_maxindex[] index %ld\n",
+					height, ARRAY_LENGTH(height_to_maxindex));
+			}
+		} else {
+			error(FATAL, "\"-N\" option is not supported or applicable"
+				" for radix tree on this architecture or kernel\n");
+		}
+	} else {
+		readmem(td->start + OFFSET(radix_tree_root_height), KVADDR, &height,
+			sizeof(uint), "radix_tree_root height", FAULT_ON_ERROR);
+
+		if (height > ARRAY_LENGTH(height_to_maxindex)) {
+			fprintf(fp, "radix_tree_root at %lx\n", td->start);
+			dump_struct("radix_tree_root", (ulong)td->start, RADIX(16));
+			error(FATAL, "height %d is greater than "
+				"height_to_maxindex[] index %ld\n",
+				height, ARRAY_LENGTH(height_to_maxindex));
+		}
+
+		readmem(td->start + OFFSET(radix_tree_root_rnode), KVADDR, &node_p,
+			sizeof(void *), "radix_tree_root rnode", FAULT_ON_ERROR);
+	}
+
+	if (node_p & 1)
+		node_p &= ~1;
+
+	sprintf(pos, "root");
+	rdtree_iteration(node_p, td, pos, -1, height);
+}
+
+void rdtree_iteration(ulong node_p, struct tree_data *td, char * ppos, ulong indexnum, uint height)
+{
+	ulong slot;
+	int index;
+	int i;
+	char pos[BUFSIZE];
+	
+	if (indexnum != -1)
+		sprintf(pos, "%s/%ld", ppos, indexnum);
+	else
+		sprintf(pos, "%s", ppos);
+
+	for (index = 0;index < RADIX_TREE_MAP_SIZE;index++) {
+		readmem((ulong)node_p + OFFSET(radix_tree_node_slots) +
+			sizeof(void *) * index, KVADDR, &slot, sizeof(void *),
+			"radix_tree_node.slot[index]", FAULT_ON_ERROR);
+		if (!slot)
+			continue;
+		if (height == 1) {
+			fprintf(fp, "%lx\n",slot);
+			
+			if (td->flags & TREE_POSITION_DISPLAY)
+				fprintf(fp, "position: %s/%d\n", pos, index);
+
+			if (td->structname) {
+				for (i = 0; i < td->structname_args; i++) {
+					switch(count_chars(td->structname[i], '.'))
+					{
+					case 0:
+						dump_struct(td->structname[i],
+							slot, 0);
+						break;
+					case 1:
+						dump_struct_members_for_tree(td, i,
+							slot);
+						break;
+					default:
+						error(FATAL,
+						  "invalid struct reference: %s\n",
+							td->structname[i]);
+					}
+				}
+			}
+		} else {
+			rdtree_iteration(slot, td, pos, index, height-1);
+		}
+	}
+}
+
+void
+do_rbtree(struct tree_data *td)
+{
+	if (!VALID_MEMBER(rb_root_rb_node) || !VALID_MEMBER(rb_node_rb_left) ||
+		!VALID_MEMBER(rb_node_rb_right))
+		error(FATAL, "red-black trees do not exist (or have changed "
+			"their format)\n");
+
+	ulong start;
+	char pos[BUFSIZE];
+	sprintf(pos, "root");
+
+	if (td->flags & TREE_NODE_POINTER)
+		start = td->start;
+	else {
+		readmem(td->start + OFFSET(rb_root_rb_node), KVADDR,
+			&start, sizeof(void *), "rb_root rb_node", FAULT_ON_ERROR);
+	}
+
+	rbtree_iteration(start, td, pos);
+}
+
+void
+rbtree_iteration(ulong node_p, struct tree_data *td, char *pos)
+{
+	int i;
+	ulong struct_p, left_p, right_p;
+	char left_pos[BUFSIZE], right_pos[BUFSIZE];
+
+	if (!node_p)
+		return;
+
+	if (node_p && !hq_enter(node_p))
+		error(FATAL, "\nduplicate tree entry: %lx\n", node_p);
+
+	struct_p = node_p - td->member_offset;
+
+
+	fprintf(fp, "%lx\n", struct_p);
+	
+	if (td->flags & TREE_POSITION_DISPLAY)
+		fprintf(fp, "position: %s\n", pos);
+
+	if (td->structname) {
+		for (i = 0; i < td->structname_args; i++) {
+			switch(count_chars(td->structname[i], '.'))
+			{
+			case 0:
+				dump_struct(td->structname[i], struct_p, 0);
+				break;
+			case 1:
+				dump_struct_members_for_tree(td, i, struct_p);
+				break;
+			default:
+				error(FATAL, "invalid struct reference: %s\n",
+					td->structname[i]);
+			}
+		}
+	}
+
+	readmem(node_p+OFFSET(rb_node_rb_left), KVADDR, &left_p,
+		sizeof(void *), "rb_node rb_left", FAULT_ON_ERROR);
+	readmem(node_p+OFFSET(rb_node_rb_right), KVADDR, &right_p,
+		sizeof(void *), "rb_node rb_right", FAULT_ON_ERROR);
+
+	sprintf(left_pos, "%s/l", pos);
+	sprintf(right_pos, "%s/r", pos);
+
+	rbtree_iteration(left_p, td, left_pos);
+	rbtree_iteration(right_p, td, right_pos);		
+}
+
+void
+dump_struct_members_for_tree(struct tree_data *td, int idx, ulong struct_p)
+{
+	int i, argc;
+	char *p1;
+	char *structname, *members;
+	char *arglist[MAXARGS];
+
+	structname = GETBUF(strlen(td->structname[idx])+1);
+	members = GETBUF(strlen(td->structname[idx])+1);
+
+	strcpy(structname, td->structname[idx]);
+	p1 = strstr(structname, ".") + 1;
+
+	strcpy(members, p1);
+	replace_string(members, ",", ' ');
+	argc = parse_line(members, arglist);
+
+	for (i = 0; i <argc; i++) {
+		*p1 = NULLCHAR;
+		strcat(structname, arglist[i]);
+		dump_struct_member(structname, struct_p, 0);
+	}
+
+	FREEBUF(structname);
+	FREEBUF(members);
+}
+
 /*
  *  The next set of functions are a general purpose hashing tool used to
  *  identify duplicate entries in a set of passed-in data, and if found, 
-- 
1.7.1

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

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux