[Crash-utility] [PATCH] kmem: introduce -m option

Aaron Tomlin atomlin at redhat.com
Fri Apr 24 18:18:38 UTC 2015


The dump_mem_map() function displays basic data about each entry in the
mem_map[] array, or if an address is specified, just the mem_map[] entry
for that address. This patch introduces the -m option to be used with
'kmem -p' exclusively. When used with -p, a comma-separated list of one or
more struct page members may be specified to generate a custom, formatted
display. For example:

  crash> kmem -p -m mapping,index,_mapcount.counter,_count.counter
  ffffea0000000000	0x0	0	0	0
  ffffea0000000040	0x0	0	-1	1
  ffffea0000000080	0x0	0	-1	1
  ffffea00000000c0	0x0	0	-1	1
  ffffea0000000100	0x0	0	-1	1
  ffffea0000000140	0x0	0	-1	1
  ffffea0000000180	0x0	0	-1	1
  ffffea00000001c0	0x0	0	-1	1
  ffffea0000000200	0x0	0	-1	1
  ffffea0000000240	0x0	0	-1	1
  ...

Signed-off-by: Aaron Tomlin <atomlin at redhat.com>
---
 help.c   |   19 +-
 memory.c | 1074 ++++++++++++++++++++++++++++++++++++--------------------------
 2 files changed, 649 insertions(+), 444 deletions(-)

diff --git a/help.c b/help.c
index b2f4d21..76b640a 100644
--- a/help.c
+++ b/help.c
@@ -5530,7 +5530,7 @@ char *help_kmem[] = {
 "kmem",
 "kernel memory",
 "[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-z|-o|-h] [slab] [[-P] address]\n"
-"       [-g [flags]] [-I slab[,slab]]",
+"       [-g [flags]] [-I slab[,slab]] [-m member[,member]]",
 "  This command displays information about the use of kernel memory.\n",
 "        -f  displays the contents of the system free memory headers.",
 "            also verifies that the page count equals nr_free_pages.",
@@ -5565,6 +5565,9 @@ char *help_kmem[] = {
 "            all slab cache names and addresses are listed.",
 "   -I slab  when used with -s or -S, one or more slab cache names in a",
 "            comma-separated list may be specified as slab caches to ignore.",
+" -m member  when used with -p, a comma-separated list of one or more",
+"            struct page members may be specified to generate a custom",
+"            formatted display.",
 "        -P  declares that the following address argument is a physical address.",
 "   address  when used without any flag, the address can be a kernel virtual,",
 "            or physical address; a search is made through the symbol table,",
@@ -5717,6 +5720,20 @@ char *help_kmem[] = {
 "    f5c51440     22000         0         0  1 80 slab",
 "    ...",
 "    ",
+"  Dump the mem_map[] array but select desired fields:\n",
+"    %s> kmem -p -m mapping,index,_mapcount.counter",
+"    ffffea0000000000	0x0	0	0",
+"    ffffea0000000040	0x0	0	-1",
+"    ffffea0000000080	0x0	0	-1",
+"    ffffea00000000c0	0x0	0	-1",
+"    ffffea0000000100	0x0	0	-1",
+"    ffffea0000000140	0x0	0	-1",
+"    ffffea0000000180	0x0	0	-1",
+"    ffffea00000001c0	0x0	0	-1",
+"    ffffea0000000200	0x0	0	-1",
+"    ffffea0000000240	0x0	0	-1",
+"    ...",
+"    ",
 "  Use the commands above with a page pointer or a physical address argument:\n",
 "    %s> kmem -f c40425b0",
 "    NODE ",
diff --git a/memory.c b/memory.c
index aacf929..d4114c2 100644
--- a/memory.c
+++ b/memory.c
@@ -55,6 +55,7 @@ struct meminfo {           /* general purpose memory information structure */
 	ulong found;
 	ulong retval;
 	char *ignore;
+	char *include;
 	int errors;
 	int calls;
 	int cpu;
@@ -4425,7 +4426,7 @@ cmd_kmem(void)
 	BZERO(&meminfo, sizeof(struct meminfo));
 	BZERO(&value[0], sizeof(ulonglong)*MAXARGS);
 
-        while ((c = getopt(argcnt, args, "gI:sSFfpvczCinl:L:PVoh")) != EOF) {
+        while ((c = getopt(argcnt, args, "gI:sSFfm:pvczCinl:L:PVoh")) != EOF) {
                 switch(c)
 		{
 		case 'V':
@@ -4480,6 +4481,10 @@ cmd_kmem(void)
 			pflag = 1;
 			break;
 
+		case 'm':
+			meminfo.include = optarg;
+			break;
+
 		case 'I':
 			meminfo.ignore = optarg;
 			break;	
@@ -4948,7 +4953,7 @@ PG_slab_flag_init(void)
 static void
 dump_mem_map_SPARSEMEM(struct meminfo *mi)
 {
-	ulong i;
+	ulong i, j;
 	long total_pages;
 	int others, page_not_mapped, phys_not_mapped, page_mapping;
 	ulong pp, ppend;
@@ -4967,7 +4972,11 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 	char buf4[BUFSIZE];
 	char *page_cache;
 	char *pcache;
-	ulong section, section_nr, nr_mem_sections, section_size;
+	char *members = NULL;
+	char *memberlist[MAXARGS];
+	struct struct_member_data *member_data[MAXARGS];
+	int nr_members, populated;
+	ulong tmpvalue, section, section_nr, nr_mem_sections, section_size;
 	long buffersize;
 	char *outputbuffer;
 	int bufferindex;
@@ -4980,66 +4989,81 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 	char style3[100];
 	char style4[100];
 
-	sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
-			space(MINSPACE),
-			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			space(MINSPACE),
-			VADDR_PRLEN,
-			space(MINSPACE),
-			space(MINSPACE));
-	sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
-			VADDR_PRLEN,
-			space(MINSPACE),
-			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			space(MINSPACE),
-			mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
-			space(MINSPACE),
-			mkstring(buf4, 8, CENTER|RJUST, " "),
-			" ");
-	sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
-			VADDR_PRLEN,
-			space(MINSPACE),
-			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			space(MINSPACE),
-			mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
-			space(MINSPACE),
-			mkstring(buf4, 8, CENTER|RJUST, "-----"));
-	sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
-			VADDR_PRLEN,
-			space(MINSPACE),
-			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			space(MINSPACE),
-			VADDR_PRLEN,
-			space(MINSPACE));
+	nr_members = mapping = index = 0;
+	reserved = shared = slabs = buffers = inode = offset = 0;
+	pg_spec = phys_spec = print_hdr = FALSE;
 
 	v22 = VALID_MEMBER(page_inode);  /* page.inode vs. page.mapping */
 
-        if (v22) {
-		sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
-		    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
-		    space(MINSPACE),               
-                    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			RJUST, "PHYSICAL"),		    
-		    space(MINSPACE),               
-		    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"), 
-		    space(MINSPACE),               
-		    mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
-		    space(MINSPACE-1));
-        } else {
-		sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
-		    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
-		    space(MINSPACE),             
-                    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-                        RJUST, "PHYSICAL"),
-		    space(MINSPACE),             
-		    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
-		    space(MINSPACE),               
-		    mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
-        }
+	if (!mi->include) {
+		sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
+				space(MINSPACE),
+				(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				space(MINSPACE),
+				VADDR_PRLEN,
+				space(MINSPACE),
+				space(MINSPACE));
+		sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
+				VADDR_PRLEN,
+				space(MINSPACE),
+				(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				space(MINSPACE),
+				mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
+				space(MINSPACE),
+				mkstring(buf4, 8, CENTER|RJUST, " "),
+				" ");
+		sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
+				VADDR_PRLEN,
+				space(MINSPACE),
+				(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				space(MINSPACE),
+				mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
+				space(MINSPACE),
+				mkstring(buf4, 8, CENTER|RJUST, "-----"));
+		sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
+				VADDR_PRLEN,
+				space(MINSPACE),
+				(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				space(MINSPACE),
+				VADDR_PRLEN,
+				space(MINSPACE));
+
+		if (v22) {
+			sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
+			    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
+			    space(MINSPACE),               
+			    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				RJUST, "PHYSICAL"),		    
+			    space(MINSPACE),               
+			    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"), 
+			    space(MINSPACE),               
+			    mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
+			    space(MINSPACE-1));
+		} else {
+			sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
+			    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
+			    space(MINSPACE),             
+			    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				RJUST, "PHYSICAL"),
+			    space(MINSPACE),             
+			    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
+			    space(MINSPACE),               
+			    mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
+		}
+	} else {
+		if (count_chars(mi->include, ',') > MAXARGS)
+			error(FATAL, "too many members in comma-separated list!\n");
 
-	mapping = index = 0;
-	reserved = shared = slabs = buffers = inode = offset = 0;
-	pg_spec = phys_spec = print_hdr = FALSE;
+		if ((LASTCHAR(mi->include) == ',') || (LASTCHAR(mi->include) == '.'))
+			error(FATAL, "invalid format: %s\n", mi->include);
+
+		members = GETBUF(strlen(mi->include)+1);
+		strcpy(members, mi->include);
+		replace_string(members, ",", ' ');
+		nr_members = parse_line(members, memberlist);
+		populated = FALSE;
+
+	}
 
 	switch (mi->flags)
 	{
@@ -5065,7 +5089,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 			error(FATAL, "dump_mem_map: no memtype specified\n");
 			break;
 		}
-		print_hdr = TRUE;
+		if (!mi->include)
+			print_hdr = TRUE;
 		break;
 
 	case GET_ALL:
@@ -5092,7 +5117,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 		break;
 
 	default:
-		print_hdr = TRUE;
+		if (!mi->include)
+			print_hdr = TRUE;
 		break;
 	}
 
@@ -5188,187 +5214,251 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 
 			if (!done && (pg_spec || phys_spec))
 				continue;
-			
-			flags = ULONG(pcache + OFFSET(page_flags));
-			if (SIZE(page_flags) == 4)
-				flags &= 0xffffffff;
-			count = UINT(pcache + OFFSET(page_count));
 
-	                switch (mi->flags)
-			{
-			case GET_ALL:
-			case GET_BUFFERS_PAGES:
-				if (VALID_MEMBER(page_buffers)) {
-					tmp = ULONG(pcache + 
-						OFFSET(page_buffers));
-					if (tmp)
-						buffers++;
-				} else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
-	                                if ((flags >> v26_PG_private) & 1) 
-						buffers++;
-				} else
-					error(FATAL, 
-			       "cannot determine whether pages have buffers\n");
+			if (mi->include) {
+				if (!populated) {
 
-				if (mi->flags != GET_ALL)
-					continue;
+					j = 0;
+					do {
+						if (!(member_data[j] = malloc(sizeof(struct struct_member_data)))) {
+							error(WARNING, "cannot malloc member_data space.\n");
+							nr_members = j += 1;
+							goto failed_member_data;
+						}
 
-				/* FALLTHROUGH */
+						member_data[j]->structure = "page";
+						member_data[j]->member = memberlist[j];
+						if (!(fill_struct_member_data(member_data[j]))) {
+							error(WARNING, "Failed to populate member_data: "
+								"%s.%s does not exist.\n",
+								member_data[j]->structure, member_data[j]->member);
+							nr_members = j += 1;
+							goto failed_member_data;
+						}
 
-			case GET_SLAB_PAGES:
-				if (v22) {
-	                                if ((flags >> v22_PG_Slab) & 1) 
-						slabs++;
-				} else if (vt->PG_slab) {
-	                                if ((flags >> vt->PG_slab) & 1) 
-						slabs++;
-				} else {
-	                                if ((flags >> v24_PG_slab) & 1) 
-						slabs++;
+					} while (++j < nr_members);
+					populated = TRUE;
 				}
-				if (mi->flags != GET_ALL)
-					continue;
 
-				/* FALLTHROUGH */
 
-			case GET_SHARED_PAGES:
-			case GET_TOTALRAM_PAGES:
-                                if (vt->PG_reserved)
-					PG_reserved_flag = vt->PG_reserved;
-				else
-                                        PG_reserved_flag = v22 ?
-                                                1 << v22_PG_reserved :
-                                                1 << v24_PG_reserved;
+				bufferindex += sprintf(outputbuffer + bufferindex,
+					"%lx\t", pp);
 
-	                        if (flags & PG_reserved_flag) {
-	                                reserved++;
-				} else {
-					if ((int)count > 
-					    (vt->flags & PGCNT_ADJ ? 0 : 1))
-						shared++;
-				}
-	                        continue;
-	                }
-			page_mapping = VALID_MEMBER(page_mapping);
-	
-			if (v22) {
-				inode = ULONG(pcache + OFFSET(page_inode));
-				offset = ULONG(pcache + OFFSET(page_offset));
-			} else if (page_mapping) { 
-				mapping = ULONG(pcache + 
-					OFFSET(page_mapping));
-				index = ULONG(pcache + OFFSET(page_index));
-			}
-	
-			page_not_mapped = phys_not_mapped = FALSE;
+				j = 0;
+				do {
+					switch (member_data[j]->type)
+					{
+					case TYPE_CODE_PTR:
+						readmem(pp + member_data[j]->offset, KVADDR, &tmpvalue,
+							member_data[j]->length, "tmpvalue", FAULT_ON_ERROR);
+						bufferindex += sprintf(outputbuffer + bufferindex, "0x%lx\t",
+							tmpvalue);
+						break;
+					case TYPE_CODE_INT:
+						readmem(pp + member_data[j]->offset, KVADDR, &tmpvalue,
+							member_data[j]->length, "tmpvalue", FAULT_ON_ERROR);
+						if (member_data[j]->unsigned_type ||
+							member_data[j]->length == sizeof(ulonglong))
+							bufferindex += sprintf(outputbuffer + bufferindex,
+								"%lu\t", tmpvalue);
+						else
+							bufferindex += sprintf(outputbuffer + bufferindex,
+								"%d\t",	(int)tmpvalue);
+						break;
+					default:
+						error(WARNING, "invalid data structure reference %s.%s\n",
+							member_data[j]->structure, member_data[j]->member);
+						nr_members = j += 1;
+						goto failed_member_data;
+						break;
+					}
+				} while (++j < nr_members);
+
+				bufferindex += sprintf(outputbuffer+bufferindex, "\n");
 
-			if (v22) {
-				bufferindex += sprintf(outputbuffer+bufferindex,
-						(char *)&style1, pp, phys, inode,
-						offset, count);
 			} else {
-				if ((vt->flags & V_MEM_MAP)) {
-				    	if (!machdep->verify_paddr(phys)) 
-						phys_not_mapped = TRUE;
-					if (!kvtop(NULL, pp, NULL, 0))
-						page_not_mapped = TRUE;
+
+				flags = ULONG(pcache + OFFSET(page_flags));
+				if (SIZE(page_flags) == 4)
+					flags &= 0xffffffff;
+				count = UINT(pcache + OFFSET(page_count));
+
+				switch (mi->flags)
+				{
+				case GET_ALL:
+				case GET_BUFFERS_PAGES:
+					if (VALID_MEMBER(page_buffers)) {
+						tmp = ULONG(pcache + 
+							OFFSET(page_buffers));
+						if (tmp)
+							buffers++;
+					} else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
+						if ((flags >> v26_PG_private) & 1) 
+							buffers++;
+					} else
+						error(FATAL, 
+				       "cannot determine whether pages have buffers\n");
+
+					if (mi->flags != GET_ALL)
+						continue;
+
+					/* FALLTHROUGH */
+
+				case GET_SLAB_PAGES:
+					if (v22) {
+						if ((flags >> v22_PG_Slab) & 1) 
+							slabs++;
+					} else if (vt->PG_slab) {
+						if ((flags >> vt->PG_slab) & 1) 
+							slabs++;
+					} else {
+						if ((flags >> v24_PG_slab) & 1) 
+							slabs++;
+					}
+					if (mi->flags != GET_ALL)
+						continue;
+
+					/* FALLTHROUGH */
+
+				case GET_SHARED_PAGES:
+				case GET_TOTALRAM_PAGES:
+					if (vt->PG_reserved)
+						PG_reserved_flag = vt->PG_reserved;
+					else
+						PG_reserved_flag = v22 ?
+							1 << v22_PG_reserved :
+							1 << v24_PG_reserved;
+
+					if (flags & PG_reserved_flag) {
+						reserved++;
+					} else {
+						if ((int)count > 
+						    (vt->flags & PGCNT_ADJ ? 0 : 1))
+							shared++;
+					}
+					continue;
 				}
-				if (page_not_mapped)
-					bufferindex += sprintf(outputbuffer+bufferindex,
-							(char *)&style2, pp, phys);
-				else if (!page_mapping)
-					bufferindex += sprintf(outputbuffer+bufferindex,
-							(char *)&style3, pp, phys, count);
-				else
+				page_mapping = VALID_MEMBER(page_mapping);
+		
+				if (v22) {
+					inode = ULONG(pcache + OFFSET(page_inode));
+					offset = ULONG(pcache + OFFSET(page_offset));
+				} else if (page_mapping) { 
+					mapping = ULONG(pcache + 
+						OFFSET(page_mapping));
+					index = ULONG(pcache + OFFSET(page_index));
+				}
+		
+				page_not_mapped = phys_not_mapped = FALSE;
+
+				if (v22) {
 					bufferindex += sprintf(outputbuffer+bufferindex,
-							(char *)&style4, pp, phys,
-							mapping, index, count);
-			}
-	
-			others = 0;
-	
+							(char *)&style1, pp, phys, inode,
+							offset, count);
+				} else {
+					if ((vt->flags & V_MEM_MAP)) {
+						if (!machdep->verify_paddr(phys)) 
+							phys_not_mapped = TRUE;
+						if (!kvtop(NULL, pp, NULL, 0))
+							page_not_mapped = TRUE;
+					}
+					if (page_not_mapped)
+						bufferindex += sprintf(outputbuffer+bufferindex,
+								(char *)&style2, pp, phys);
+					else if (!page_mapping)
+						bufferindex += sprintf(outputbuffer+bufferindex,
+								(char *)&style3, pp, phys, count);
+					else
+						bufferindex += sprintf(outputbuffer+bufferindex,
+								(char *)&style4, pp, phys,
+								mapping, index, count);
+				}
+		
+				others = 0;
+		
 #define sprintflag(X) sprintf(outputbuffer + bufferindex, X, others++ ? "," : "")
 
-			if (v22) {
-		                if ((flags >> v22_PG_DMA) & 1)
-					bufferindex += sprintflag("%sDMA");
-				if ((flags >> v22_PG_locked) & 1)
-					bufferindex += sprintflag("%slocked");
-				if ((flags >> v22_PG_error) & 1)
-					bufferindex += sprintflag("%serror");
-				if ((flags >> v22_PG_referenced) & 1)
-					bufferindex += sprintflag("%sreferenced");
-				if ((flags >> v22_PG_dirty) & 1)
-					bufferindex += sprintflag("%sdirty");
-				if ((flags >> v22_PG_uptodate) & 1)
-					bufferindex += sprintflag("%suptodate");
-				if ((flags >> v22_PG_free_after) & 1)
-					bufferindex += sprintflag("%sfree_after");
-				if ((flags >> v22_PG_decr_after) & 1)
-					bufferindex += sprintflag("%sdecr_after");
-				if ((flags >> v22_PG_swap_unlock_after) & 1)
-					bufferindex += sprintflag("%sswap_unlock_after");
-				if ((flags >> v22_PG_Slab) & 1)
-					bufferindex += sprintflag("%sslab");
-				if ((flags >> v22_PG_swap_cache) & 1)
-					bufferindex += sprintflag("%sswap_cache");
-				if ((flags >> v22_PG_skip) & 1)
-					bufferindex += sprintflag("%sskip");
-	                        if ((flags >> v22_PG_reserved) & 1)
-					bufferindex += sprintflag("%sreserved");
-				bufferindex += sprintf(outputbuffer+bufferindex, "\n");
-			} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
-				if (vt->flags & PAGEFLAGS)
-					bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
-				else
-					bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
-			} else {
-	
-		                if ((flags >> v24_PG_locked) & 1)
-					bufferindex += sprintflag("%slocked");
-				if ((flags >> v24_PG_error) & 1)
-					bufferindex += sprintflag("%serror");
-				if ((flags >> v24_PG_referenced) & 1)
-					bufferindex += sprintflag("%sreferenced");
-				if ((flags >> v24_PG_uptodate) & 1)
-					bufferindex += sprintflag("%suptodate");
-                                if ((flags >> v24_PG_dirty) & 1)
-					bufferindex += sprintflag("%sdirty");
-				if ((flags >> v24_PG_decr_after) & 1)
-					bufferindex += sprintflag("%sdecr_after");
-                                if ((flags >> v24_PG_active) & 1)
-					bufferindex += sprintflag("%sactive");
-                                if ((flags >> v24_PG_inactive_dirty) & 1)
-					bufferindex += sprintflag("%sinactive_dirty");
-				if ((flags >> v24_PG_slab) & 1)
-					bufferindex += sprintflag("%sslab");
-				if ((flags >> v24_PG_swap_cache) & 1)
-					bufferindex += sprintflag("%sswap_cache");
-				if ((flags >> v24_PG_skip) & 1)
-					bufferindex += sprintflag("%sskip");
-				if ((flags >> v24_PG_inactive_clean) & 1)
-					bufferindex += sprintflag("%sinactive_clean");
-				if ((flags >> v24_PG_highmem) & 1)
-					bufferindex += sprintflag("%shighmem");
-				if ((flags >> v24_PG_checked) & 1)
-					bufferindex += sprintflag("%schecked");
-				if ((flags >> v24_PG_bigpage) & 1)
-					bufferindex += sprintflag("%sbigpage");
-                                if ((flags >> v24_PG_arch_1) & 1)
-					bufferindex += sprintflag("%sarch_1");
-				if ((flags >> v24_PG_reserved) & 1)
-					bufferindex += sprintflag("%sreserved");
-				if (phys_not_mapped)
-					bufferindex += sprintflag("%s[NOT MAPPED]");
-
-				bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+				if (v22) {
+					if ((flags >> v22_PG_DMA) & 1)
+						bufferindex += sprintflag("%sDMA");
+					if ((flags >> v22_PG_locked) & 1)
+						bufferindex += sprintflag("%slocked");
+					if ((flags >> v22_PG_error) & 1)
+						bufferindex += sprintflag("%serror");
+					if ((flags >> v22_PG_referenced) & 1)
+						bufferindex += sprintflag("%sreferenced");
+					if ((flags >> v22_PG_dirty) & 1)
+						bufferindex += sprintflag("%sdirty");
+					if ((flags >> v22_PG_uptodate) & 1)
+						bufferindex += sprintflag("%suptodate");
+					if ((flags >> v22_PG_free_after) & 1)
+						bufferindex += sprintflag("%sfree_after");
+					if ((flags >> v22_PG_decr_after) & 1)
+						bufferindex += sprintflag("%sdecr_after");
+					if ((flags >> v22_PG_swap_unlock_after) & 1)
+						bufferindex += sprintflag("%sswap_unlock_after");
+					if ((flags >> v22_PG_Slab) & 1)
+						bufferindex += sprintflag("%sslab");
+					if ((flags >> v22_PG_swap_cache) & 1)
+						bufferindex += sprintflag("%sswap_cache");
+					if ((flags >> v22_PG_skip) & 1)
+						bufferindex += sprintflag("%sskip");
+					if ((flags >> v22_PG_reserved) & 1)
+						bufferindex += sprintflag("%sreserved");
+					bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+				} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
+					if (vt->flags & PAGEFLAGS)
+						bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
+					else
+						bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
+				} else {
+		
+					if ((flags >> v24_PG_locked) & 1)
+						bufferindex += sprintflag("%slocked");
+					if ((flags >> v24_PG_error) & 1)
+						bufferindex += sprintflag("%serror");
+					if ((flags >> v24_PG_referenced) & 1)
+						bufferindex += sprintflag("%sreferenced");
+					if ((flags >> v24_PG_uptodate) & 1)
+						bufferindex += sprintflag("%suptodate");
+					if ((flags >> v24_PG_dirty) & 1)
+						bufferindex += sprintflag("%sdirty");
+					if ((flags >> v24_PG_decr_after) & 1)
+						bufferindex += sprintflag("%sdecr_after");
+					if ((flags >> v24_PG_active) & 1)
+						bufferindex += sprintflag("%sactive");
+					if ((flags >> v24_PG_inactive_dirty) & 1)
+						bufferindex += sprintflag("%sinactive_dirty");
+					if ((flags >> v24_PG_slab) & 1)
+						bufferindex += sprintflag("%sslab");
+					if ((flags >> v24_PG_swap_cache) & 1)
+						bufferindex += sprintflag("%sswap_cache");
+					if ((flags >> v24_PG_skip) & 1)
+						bufferindex += sprintflag("%sskip");
+					if ((flags >> v24_PG_inactive_clean) & 1)
+						bufferindex += sprintflag("%sinactive_clean");
+					if ((flags >> v24_PG_highmem) & 1)
+						bufferindex += sprintflag("%shighmem");
+					if ((flags >> v24_PG_checked) & 1)
+						bufferindex += sprintflag("%schecked");
+					if ((flags >> v24_PG_bigpage) & 1)
+						bufferindex += sprintflag("%sbigpage");
+					if ((flags >> v24_PG_arch_1) & 1)
+						bufferindex += sprintflag("%sarch_1");
+					if ((flags >> v24_PG_reserved) & 1)
+						bufferindex += sprintflag("%sreserved");
+					if (phys_not_mapped)
+						bufferindex += sprintflag("%s[NOT MAPPED]");
+
+					bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+				}
 			}
 
 			if (bufferindex > buffersize) {
 				fprintf(fp, "%s", outputbuffer);
 				bufferindex = 0;
 			}
-	
+
 			if (done)
 				break;
 		}
@@ -5413,12 +5503,18 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 
 	FREEBUF(outputbuffer);
 	FREEBUF(page_cache);
+failed_member_data:
+	if (mi->include) {
+		FREEBUF(members);
+		for (i = 0; i < nr_members; i++)
+			free(member_data[i]);
+	}
 }
 
 static void
 dump_mem_map(struct meminfo *mi)
 {
-	long i, n;
+	ulong i, n, j;
 	long total_pages;
 	int others, page_not_mapped, phys_not_mapped, page_mapping;
 	ulong pp, ppend;
@@ -5439,6 +5535,11 @@ dump_mem_map(struct meminfo *mi)
 	char buf4[BUFSIZE];
 	char *page_cache;
 	char *pcache;
+	char *members = NULL;
+	char *memberlist[MAXARGS];
+	struct struct_member_data *member_data[MAXARGS];
+	int nr_members, populated;
+	ulong tmpvalue;
 	long buffersize;
 	char *outputbuffer;
 	int bufferindex;
@@ -5456,67 +5557,82 @@ dump_mem_map(struct meminfo *mi)
 		return;
 	}
 
-	sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
-			space(MINSPACE),
-			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			space(MINSPACE),
-			VADDR_PRLEN,
-			space(MINSPACE),
-			space(MINSPACE));
-	sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
-			VADDR_PRLEN,
-			space(MINSPACE),
-			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			space(MINSPACE),
-			mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
-			space(MINSPACE),
-			mkstring(buf4, 8, CENTER|RJUST, " "),
-			" ");
-	sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
-			VADDR_PRLEN,
-			space(MINSPACE),
-			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			space(MINSPACE),
-			mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
-			space(MINSPACE),
-			mkstring(buf4, 8, CENTER|RJUST, "-----"));
-	sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
-			VADDR_PRLEN,
-			space(MINSPACE),
-			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			space(MINSPACE),
-			VADDR_PRLEN,
-			space(MINSPACE));
+	nr_members = mapping = index = 0;
+	reserved = shared = slabs = buffers = inode = offset = 0;
+	pg_spec = phys_spec = print_hdr = FALSE;
 
 	v22 = VALID_MEMBER(page_inode);  /* page.inode vs. page.mapping */
 
-        if (v22) {
-		sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
-		    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
-		    space(MINSPACE),               
-                    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-			RJUST, "PHYSICAL"),		    
-		    space(MINSPACE),               
-		    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"), 
-		    space(MINSPACE),               
-		    mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
-		    space(MINSPACE-1));
-        } else {
-		sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
-		    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
-		    space(MINSPACE),             
-                    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
-                        RJUST, "PHYSICAL"),
-		    space(MINSPACE),             
-		    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
-		    space(MINSPACE),               
-		    mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
-        }
+	if (!mi->include) {
+		sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
+				space(MINSPACE),
+				(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				space(MINSPACE),
+				VADDR_PRLEN,
+				space(MINSPACE),
+				space(MINSPACE));
+		sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
+				VADDR_PRLEN,
+				space(MINSPACE),
+				(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				space(MINSPACE),
+				mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
+				space(MINSPACE),
+				mkstring(buf4, 8, CENTER|RJUST, " "),
+				" ");
+		sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
+				VADDR_PRLEN,
+				space(MINSPACE),
+				(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				space(MINSPACE),
+				mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
+				space(MINSPACE),
+				mkstring(buf4, 8, CENTER|RJUST, "-----"));
+		sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
+				VADDR_PRLEN,
+				space(MINSPACE),
+				(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				space(MINSPACE),
+				VADDR_PRLEN,
+				space(MINSPACE));
+
+		if (v22) {
+			sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
+			    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
+			    space(MINSPACE),               
+			    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				RJUST, "PHYSICAL"),		    
+			    space(MINSPACE),               
+			    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"), 
+			    space(MINSPACE),               
+			    mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
+			    space(MINSPACE-1));
+		} else {
+			sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
+			    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
+			    space(MINSPACE),             
+			    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+				RJUST, "PHYSICAL"),
+			    space(MINSPACE),             
+			    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
+			    space(MINSPACE),               
+			    mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
+		}
+	} else {
+		if (count_chars(mi->include, ',') > MAXARGS)
+			error(FATAL, "too many members in comma-separated list!\n");
+
+		if ((LASTCHAR(mi->include) == ',') || (LASTCHAR(mi->include) == '.'))
+			error(FATAL, "invalid format: %s\n", mi->include);
+
+		members = GETBUF(strlen(mi->include)+1);
+		strcpy(members, mi->include);
+		replace_string(members, ",", ' ');
+		nr_members = parse_line(members, memberlist);
+		populated = FALSE;
+
+	}
 
-	mapping = index = 0;
-	reserved = shared = slabs = buffers = inode = offset = 0;
-	pg_spec = phys_spec = print_hdr = FALSE;
-	
 	switch (mi->flags)
 	{
 	case ADDRESS_SPECIFIED: 
@@ -5541,7 +5657,8 @@ dump_mem_map(struct meminfo *mi)
 			error(FATAL, "dump_mem_map: no memtype specified\n");
 			break;
 		}
-		print_hdr = TRUE;
+		if (!mi->include)
+			print_hdr = TRUE;
 		break;
 
 	case GET_ALL:
@@ -5568,7 +5685,8 @@ dump_mem_map(struct meminfo *mi)
 		break;
 
 	default:
-		print_hdr = TRUE;
+		if (!mi->include)
+			print_hdr = TRUE;
 		break;
 	}
 
@@ -5625,181 +5743,245 @@ dump_mem_map(struct meminfo *mi)
 
 			if (!done && (pg_spec || phys_spec))
 				continue;
-			
-			flags = ULONG(pcache + OFFSET(page_flags));
-			if (SIZE(page_flags) == 4)
-				flags &= 0xffffffff;
-			count = UINT(pcache + OFFSET(page_count));
 
-	                switch (mi->flags)
-			{
-			case GET_ALL:
-			case GET_BUFFERS_PAGES:
-				if (VALID_MEMBER(page_buffers)) {
-					tmp = ULONG(pcache + 
-						OFFSET(page_buffers));
-					if (tmp)
-						buffers++;
-				} else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
-	                                if ((flags >> v26_PG_private) & 1) 
-						buffers++;
-				} else
-					error(FATAL, 
-			       "cannot determine whether pages have buffers\n");
+			if (mi->include) {
+				if (!populated) {
 
-				if (mi->flags != GET_ALL)
-					continue;
+					j = 0;
+					do {
+						if (!(member_data[j] = malloc(sizeof(struct struct_member_data)))) {
+							error(WARNING, "cannot malloc member_data space.\n");
+							nr_members = j += 1;
+							goto failed_member_data;
+						}
 
-				/* FALLTHROUGH */
+						member_data[j]->structure = "page";
+						member_data[j]->member = memberlist[j];
+						if (!(fill_struct_member_data(member_data[j]))) {
+							error(WARNING, "Failed to populate member_data: "
+								"%s.%s does not exist.\n",
+								member_data[j]->structure, member_data[j]->member);
+							nr_members = j += 1;
+							goto failed_member_data;
+						}
 
-			case GET_SLAB_PAGES:
-				if (v22) {
-	                                if ((flags >> v22_PG_Slab) & 1) 
-						slabs++;
-				} else if (vt->PG_slab) {
-	                                if ((flags >> vt->PG_slab) & 1) 
-						slabs++;
-				} else {
-	                                if ((flags >> v24_PG_slab) & 1) 
-						slabs++;
+					} while (++j < nr_members);
+					populated = TRUE;
 				}
-				if (mi->flags != GET_ALL)
-					continue;
 
-				/* FALLTHROUGH */
 
-			case GET_SHARED_PAGES:
-			case GET_TOTALRAM_PAGES:
-                                if (vt->PG_reserved)
-					PG_reserved_flag = vt->PG_reserved;
-				else
-                                        PG_reserved_flag = v22 ?
-                                                1 << v22_PG_reserved :
-                                                1 << v24_PG_reserved;
+				bufferindex += sprintf(outputbuffer + bufferindex,
+					"%lx\t", pp);
 
-	                        if (flags & PG_reserved_flag) {
-	                                reserved++;
-				} else {
-					if ((int)count >
-					    (vt->flags & PGCNT_ADJ ? 0 : 1))
-						shared++;
-				}
-	                        continue;
-	                }
-	
-			page_mapping = VALID_MEMBER(page_mapping);
-
-			if (v22) {
-				inode = ULONG(pcache + OFFSET(page_inode));
-				offset = ULONG(pcache + OFFSET(page_offset));
-			} else if (page_mapping) {
-				mapping = ULONG(pcache + 
-					OFFSET(page_mapping));
-				index = ULONG(pcache + OFFSET(page_index));
-			}
-	
-			page_not_mapped = phys_not_mapped = FALSE;
+				j = 0;
+				do {
+					switch (member_data[j]->type)
+					{
+					case TYPE_CODE_PTR:
+						readmem(pp + member_data[j]->offset, KVADDR, &tmpvalue,
+							member_data[j]->length, "tmpvalue", FAULT_ON_ERROR);
+						bufferindex += sprintf(outputbuffer + bufferindex, "0x%lx\t",
+							tmpvalue);
+						break;
+					case TYPE_CODE_INT:
+						readmem(pp + member_data[j]->offset, KVADDR, &tmpvalue,
+							member_data[j]->length, "tmpvalue", FAULT_ON_ERROR);
+						if (member_data[j]->unsigned_type ||
+							member_data[j]->length == sizeof(ulonglong))
+							bufferindex += sprintf(outputbuffer + bufferindex,
+								"%lu\t", tmpvalue);
+						else
+							bufferindex += sprintf(outputbuffer + bufferindex,
+								"%d\t",	(int)tmpvalue);
+						break;
+					default:
+						error(WARNING, "invalid data structure reference %s.%s\n",
+							member_data[j]->structure, member_data[j]->member);
+						nr_members = j += 1;
+						goto failed_member_data;
+						break;
+					}
+				} while (++j < nr_members);
+
+				bufferindex += sprintf(outputbuffer+bufferindex, "\n");
 
-			if (v22) {
-				bufferindex += sprintf(outputbuffer+bufferindex,
-						(char *)&style1, pp, phys, inode,
-						offset, count);
 			} else {
-				if ((vt->flags & V_MEM_MAP)) {
-				    	if (!machdep->verify_paddr(phys)) 
-						phys_not_mapped = TRUE;
-					if (!kvtop(NULL, pp, NULL, 0))
-						page_not_mapped = TRUE;
+
+				flags = ULONG(pcache + OFFSET(page_flags));
+				if (SIZE(page_flags) == 4)
+					flags &= 0xffffffff;
+				count = UINT(pcache + OFFSET(page_count));
+
+				switch (mi->flags)
+				{
+				case GET_ALL:
+				case GET_BUFFERS_PAGES:
+					if (VALID_MEMBER(page_buffers)) {
+						tmp = ULONG(pcache + 
+							OFFSET(page_buffers));
+						if (tmp)
+							buffers++;
+					} else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
+						if ((flags >> v26_PG_private) & 1) 
+							buffers++;
+					} else
+						error(FATAL, 
+				       "cannot determine whether pages have buffers\n");
+
+					if (mi->flags != GET_ALL)
+						continue;
+
+					/* FALLTHROUGH */
+
+				case GET_SLAB_PAGES:
+					if (v22) {
+						if ((flags >> v22_PG_Slab) & 1) 
+							slabs++;
+					} else if (vt->PG_slab) {
+						if ((flags >> vt->PG_slab) & 1) 
+							slabs++;
+					} else {
+						if ((flags >> v24_PG_slab) & 1) 
+							slabs++;
+					}
+					if (mi->flags != GET_ALL)
+						continue;
+
+					/* FALLTHROUGH */
+
+				case GET_SHARED_PAGES:
+				case GET_TOTALRAM_PAGES:
+					if (vt->PG_reserved)
+						PG_reserved_flag = vt->PG_reserved;
+					else
+						PG_reserved_flag = v22 ?
+							1 << v22_PG_reserved :
+							1 << v24_PG_reserved;
+
+					if (flags & PG_reserved_flag) {
+						reserved++;
+					} else {
+						if ((int)count >
+						    (vt->flags & PGCNT_ADJ ? 0 : 1))
+							shared++;
+					}
+					continue;
 				}
-				if (page_not_mapped)
-					bufferindex += sprintf(outputbuffer+bufferindex,
-							(char *)&style2, pp, phys);
-				else if (!page_mapping)
-					bufferindex += sprintf(outputbuffer+bufferindex,
-							(char *)&style3, pp, phys, count);
-				else
+		
+				page_mapping = VALID_MEMBER(page_mapping);
+
+				if (v22) {
+					inode = ULONG(pcache + OFFSET(page_inode));
+					offset = ULONG(pcache + OFFSET(page_offset));
+				} else if (page_mapping) {
+					mapping = ULONG(pcache + 
+						OFFSET(page_mapping));
+					index = ULONG(pcache + OFFSET(page_index));
+				}
+		
+				page_not_mapped = phys_not_mapped = FALSE;
+
+				if (v22) {
 					bufferindex += sprintf(outputbuffer+bufferindex,
-							(char *)&style4, pp, phys,
-							mapping, index, count);
-			}
-	
-			others = 0;
-	
+							(char *)&style1, pp, phys, inode,
+							offset, count);
+				} else {
+					if ((vt->flags & V_MEM_MAP)) {
+						if (!machdep->verify_paddr(phys)) 
+							phys_not_mapped = TRUE;
+						if (!kvtop(NULL, pp, NULL, 0))
+							page_not_mapped = TRUE;
+					}
+					if (page_not_mapped)
+						bufferindex += sprintf(outputbuffer+bufferindex,
+								(char *)&style2, pp, phys);
+					else if (!page_mapping)
+						bufferindex += sprintf(outputbuffer+bufferindex,
+								(char *)&style3, pp, phys, count);
+					else
+						bufferindex += sprintf(outputbuffer+bufferindex,
+								(char *)&style4, pp, phys,
+								mapping, index, count);
+				}
+		
+				others = 0;
+		
 #define sprintflag(X) sprintf(outputbuffer + bufferindex, X, others++ ? "," : "")
 
-			if (v22) {
-		                if ((flags >> v22_PG_DMA) & 1)
-					bufferindex += sprintflag("%sDMA");
-				if ((flags >> v22_PG_locked) & 1)
-					bufferindex += sprintflag("%slocked");
-				if ((flags >> v22_PG_error) & 1)
-					bufferindex += sprintflag("%serror");
-				if ((flags >> v22_PG_referenced) & 1)
-					bufferindex += sprintflag("%sreferenced");
-				if ((flags >> v22_PG_dirty) & 1)
-					bufferindex += sprintflag("%sdirty");
-				if ((flags >> v22_PG_uptodate) & 1)
-					bufferindex += sprintflag("%suptodate");
-				if ((flags >> v22_PG_free_after) & 1)
-					bufferindex += sprintflag("%sfree_after");
-				if ((flags >> v22_PG_decr_after) & 1)
-					bufferindex += sprintflag("%sdecr_after");
-				if ((flags >> v22_PG_swap_unlock_after) & 1)
-					bufferindex += sprintflag("%sswap_unlock_after");
-				if ((flags >> v22_PG_Slab) & 1)
-					bufferindex += sprintflag("%sslab");
-				if ((flags >> v22_PG_swap_cache) & 1)
-					bufferindex += sprintflag("%sswap_cache");
-				if ((flags >> v22_PG_skip) & 1)
-					bufferindex += sprintflag("%sskip");
-	                        if ((flags >> v22_PG_reserved) & 1)
-					bufferindex += sprintflag("%sreserved");
-				bufferindex += sprintf(outputbuffer+bufferindex, "\n");
-			} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
-				if (vt->flags & PAGEFLAGS)
-					bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
-				else
-					bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
-			} else {
-	
-		                if ((flags >> v24_PG_locked) & 1)
-					bufferindex += sprintflag("%slocked");
-				if ((flags >> v24_PG_error) & 1)
-					bufferindex += sprintflag("%serror");
-				if ((flags >> v24_PG_referenced) & 1)
-					bufferindex += sprintflag("%sreferenced");
-				if ((flags >> v24_PG_uptodate) & 1)
-					bufferindex += sprintflag("%suptodate");
-                                if ((flags >> v24_PG_dirty) & 1)
-					bufferindex += sprintflag("%sdirty");
-				if ((flags >> v24_PG_decr_after) & 1)
-					bufferindex += sprintflag("%sdecr_after");
-                                if ((flags >> v24_PG_active) & 1)
-					bufferindex += sprintflag("%sactive");
-                                if ((flags >> v24_PG_inactive_dirty) & 1)
-					bufferindex += sprintflag("%sinactive_dirty");
-				if ((flags >> v24_PG_slab) & 1)
-					bufferindex += sprintflag("%sslab");
-				if ((flags >> v24_PG_swap_cache) & 1)
-					bufferindex += sprintflag("%sswap_cache");
-				if ((flags >> v24_PG_skip) & 1)
-					bufferindex += sprintflag("%sskip");
-				if ((flags >> v24_PG_inactive_clean) & 1)
-					bufferindex += sprintflag("%sinactive_clean");
-				if ((flags >> v24_PG_highmem) & 1)
-					bufferindex += sprintflag("%shighmem");
-				if ((flags >> v24_PG_checked) & 1)
-					bufferindex += sprintflag("%schecked");
-				if ((flags >> v24_PG_bigpage) & 1)
-					bufferindex += sprintflag("%sbigpage");
-                                if ((flags >> v24_PG_arch_1) & 1)
-					bufferindex += sprintflag("%sarch_1");
-				if ((flags >> v24_PG_reserved) & 1)
-					bufferindex += sprintflag("%sreserved");
-				if (phys_not_mapped)
-					bufferindex += sprintflag("%s[NOT MAPPED]");
-
-				bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+				if (v22) {
+					if ((flags >> v22_PG_DMA) & 1)
+						bufferindex += sprintflag("%sDMA");
+					if ((flags >> v22_PG_locked) & 1)
+						bufferindex += sprintflag("%slocked");
+					if ((flags >> v22_PG_error) & 1)
+						bufferindex += sprintflag("%serror");
+					if ((flags >> v22_PG_referenced) & 1)
+						bufferindex += sprintflag("%sreferenced");
+					if ((flags >> v22_PG_dirty) & 1)
+						bufferindex += sprintflag("%sdirty");
+					if ((flags >> v22_PG_uptodate) & 1)
+						bufferindex += sprintflag("%suptodate");
+					if ((flags >> v22_PG_free_after) & 1)
+						bufferindex += sprintflag("%sfree_after");
+					if ((flags >> v22_PG_decr_after) & 1)
+						bufferindex += sprintflag("%sdecr_after");
+					if ((flags >> v22_PG_swap_unlock_after) & 1)
+						bufferindex += sprintflag("%sswap_unlock_after");
+					if ((flags >> v22_PG_Slab) & 1)
+						bufferindex += sprintflag("%sslab");
+					if ((flags >> v22_PG_swap_cache) & 1)
+						bufferindex += sprintflag("%sswap_cache");
+					if ((flags >> v22_PG_skip) & 1)
+						bufferindex += sprintflag("%sskip");
+					if ((flags >> v22_PG_reserved) & 1)
+						bufferindex += sprintflag("%sreserved");
+					bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+				} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
+					if (vt->flags & PAGEFLAGS)
+						bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
+					else
+						bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
+				} else {
+		
+					if ((flags >> v24_PG_locked) & 1)
+						bufferindex += sprintflag("%slocked");
+					if ((flags >> v24_PG_error) & 1)
+						bufferindex += sprintflag("%serror");
+					if ((flags >> v24_PG_referenced) & 1)
+						bufferindex += sprintflag("%sreferenced");
+					if ((flags >> v24_PG_uptodate) & 1)
+						bufferindex += sprintflag("%suptodate");
+					if ((flags >> v24_PG_dirty) & 1)
+						bufferindex += sprintflag("%sdirty");
+					if ((flags >> v24_PG_decr_after) & 1)
+						bufferindex += sprintflag("%sdecr_after");
+					if ((flags >> v24_PG_active) & 1)
+						bufferindex += sprintflag("%sactive");
+					if ((flags >> v24_PG_inactive_dirty) & 1)
+						bufferindex += sprintflag("%sinactive_dirty");
+					if ((flags >> v24_PG_slab) & 1)
+						bufferindex += sprintflag("%sslab");
+					if ((flags >> v24_PG_swap_cache) & 1)
+						bufferindex += sprintflag("%sswap_cache");
+					if ((flags >> v24_PG_skip) & 1)
+						bufferindex += sprintflag("%sskip");
+					if ((flags >> v24_PG_inactive_clean) & 1)
+						bufferindex += sprintflag("%sinactive_clean");
+					if ((flags >> v24_PG_highmem) & 1)
+						bufferindex += sprintflag("%shighmem");
+					if ((flags >> v24_PG_checked) & 1)
+						bufferindex += sprintflag("%schecked");
+					if ((flags >> v24_PG_bigpage) & 1)
+						bufferindex += sprintflag("%sbigpage");
+					if ((flags >> v24_PG_arch_1) & 1)
+						bufferindex += sprintflag("%sarch_1");
+					if ((flags >> v24_PG_reserved) & 1)
+						bufferindex += sprintflag("%sreserved");
+					if (phys_not_mapped)
+						bufferindex += sprintflag("%s[NOT MAPPED]");
+
+					bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+				}
 			}
 	
 			if (bufferindex > buffersize) {
@@ -5851,6 +6033,12 @@ dump_mem_map(struct meminfo *mi)
 
 	FREEBUF(outputbuffer);
 	FREEBUF(page_cache);
+failed_member_data:
+	if (mi->include) {
+		FREEBUF(members);
+		for (i = 0; i < nr_members; i++)
+			free(member_data[i]);
+	}
 }
 
 /*
-- 
1.9.3




More information about the Crash-utility mailing list