[Crash-utility] [PATCH] kmem: Show a page's _mapcount value in dump_mem_map()

Aaron Tomlin atomlin at redhat.com
Thu Apr 9 20:22:18 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.

For kernels where the page data structure includes the _mapcount field,
this patch is an enhancement to the "kmem -p" option to include a given
page's _mapcount value to be appended to the traditional output of the
command.

For example:

 crash> kmem -p
       PAGE        PHYSICAL      MAPPING        INDEX  COUNT MAPCOUNT FLAGS
 ffffea0000000000         0                0        0      0        0 0
 ffffea0000000040      1000                0        0      1       -1 1ffff800000400 reserved
 ffffea0000000080      2000                0        0      1       -1 1ffff800000400 reserved
 ffffea00000000c0      3000                0        0      1       -1 1ffff800000400 reserved
 ffffea0000000100      4000                0        0      1       -1 1ffff800000400 reserved
 ...

Please note that a given page's _mapcount value (much like the index field)
is always displayed by default regardless. The relevant kernel sources
should be consulted for the meaning of the hexadecimal bit value.

Signed-off-by: Aaron Tomlin <atomlin at redhat.com>
---
 defs.h   |  1 +
 memory.c | 60 ++++++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/defs.h b/defs.h
index f285622..c2d7a14 100644
--- a/defs.h
+++ b/defs.h
@@ -1323,6 +1323,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long page_inode;
 	long page_offset;
 	long page_count;
+	long page_mapcount;
 	long page_flags;
 	long page_mapping;
 	long page_index;
diff --git a/memory.c b/memory.c
index aacf929..7970be0 100644
--- a/memory.c
+++ b/memory.c
@@ -424,6 +424,10 @@ vm_init(void)
 		if (INVALID_MEMBER(page_count))
 			ANON_MEMBER_OFFSET_INIT(page_count, "page", "_count");
 	}
+	MEMBER_OFFSET_INIT(page_mapcount, "page", "_mapcount");
+	if (INVALID_MEMBER(page_mapcount)) {
+		ANON_MEMBER_OFFSET_INIT(page_mapcount, "page", "_mapcount");
+	}
 	MEMBER_OFFSET_INIT(page_flags, "page", "flags");
 	MEMBER_SIZE_INIT(page_flags, "page", "flags");
         MEMBER_OFFSET_INIT(page_mapping, "page", "mapping");
@@ -431,8 +435,8 @@ vm_init(void)
 		ANON_MEMBER_OFFSET_INIT(page_mapping, "page", "mapping");
 	if (INVALID_MEMBER(page_mapping) && 
 	    (THIS_KERNEL_VERSION < LINUX(2,6,17)) &&
-	    MEMBER_EXISTS("page", "_mapcount"))
-		ASSIGN_OFFSET(page_mapping) = MEMBER_OFFSET("page", "_mapcount") +
+	    VALID_MEMBER(page_mapcount))
+		ASSIGN_OFFSET(page_mapping) = OFFSET(page_mapcount) +
 			STRUCT_SIZE("atomic_t") + sizeof(ulong);
         MEMBER_OFFSET_INIT(page_index, "page", "index");
 	if (INVALID_MEMBER(page_index))
@@ -4950,14 +4954,14 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 {
 	ulong i;
 	long total_pages;
-	int others, page_not_mapped, phys_not_mapped, page_mapping;
+	int others, page_not_mapped, phys_not_mapped, page_mapping, page_mapcount;
 	ulong pp, ppend;
 	physaddr_t phys, physend;
 	ulong tmp, reserved, shared, slabs;
         ulong PG_reserved_flag;
 	long buffers;
 	ulong inode, offset, flags, mapping, index;
-	uint count;
+	uint count, mapcount;
 	int print_hdr, pg_spec, phys_spec, done;
 	int v22;
 	char hdr[BUFSIZE];
@@ -4996,7 +5000,7 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 			space(MINSPACE),
 			mkstring(buf4, 8, CENTER|RJUST, " "),
 			" ");
-	sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
+	sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%6d ",
 			VADDR_PRLEN,
 			space(MINSPACE),
 			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
@@ -5004,7 +5008,7 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 			mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
 			space(MINSPACE),
 			mkstring(buf4, 8, CENTER|RJUST, "-----"));
-	sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
+	sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%6d ",
 			VADDR_PRLEN,
 			space(MINSPACE),
 			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
@@ -5013,9 +5017,10 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 			space(MINSPACE));
 
 	v22 = VALID_MEMBER(page_inode);  /* page.inode vs. page.mapping */
+	page_mapcount = VALID_MEMBER(page_mapcount);
 
         if (v22) {
-		sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
+		sprintf(hdr, "%s%s%s%s%s%s%s%sCOUNT FLAGS\n",
 		    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
 		    space(MINSPACE),               
                     mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
@@ -5026,7 +5031,7 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 		    mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
 		    space(MINSPACE-1));
         } else {
-		sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
+		sprintf(hdr, "%s%s%s%s%s%s%sCOUNT%sFLAGS\n",
 		    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
 		    space(MINSPACE),             
                     mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
@@ -5034,7 +5039,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 		    space(MINSPACE),             
 		    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
 		    space(MINSPACE),               
-		    mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
+		    mkstring(buf4, 10, CENTER|RJUST, "INDEX"),
+		    (page_mapcount ? " MAPCOUNT " : " "));
         }
 
 	mapping = index = 0;
@@ -5279,10 +5285,18 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
 				else if (!page_mapping)
 					bufferindex += sprintf(outputbuffer+bufferindex,
 							(char *)&style3, pp, phys, count);
-				else
+				else {
 					bufferindex += sprintf(outputbuffer+bufferindex,
 							(char *)&style4, pp, phys,
 							mapping, index, count);
+					if (page_mapcount) {
+						mapcount = UINT(pcache +
+							OFFSET(page_mapcount));
+
+						bufferindex += sprintf(outputbuffer+bufferindex,
+								"%8d ", mapcount);
+					}
+				}
 			}
 	
 			others = 0;
@@ -5420,7 +5434,7 @@ dump_mem_map(struct meminfo *mi)
 {
 	long i, n;
 	long total_pages;
-	int others, page_not_mapped, phys_not_mapped, page_mapping;
+	int others, page_not_mapped, phys_not_mapped, page_mapping, page_mapcount;
 	ulong pp, ppend;
 	physaddr_t phys, physend;
 	ulong tmp, reserved, shared, slabs;
@@ -5428,7 +5442,7 @@ dump_mem_map(struct meminfo *mi)
 	long buffers;
 	ulong inode, offset, flags, mapping, index;
 	ulong node_size;
-	uint count;
+	uint count, mapcount;
 	int print_hdr, pg_spec, phys_spec, done;
 	int v22;
 	struct node_table *nt;
@@ -5472,7 +5486,7 @@ dump_mem_map(struct meminfo *mi)
 			space(MINSPACE),
 			mkstring(buf4, 8, CENTER|RJUST, " "),
 			" ");
-	sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
+	sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%6d ",
 			VADDR_PRLEN,
 			space(MINSPACE),
 			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
@@ -5480,7 +5494,7 @@ dump_mem_map(struct meminfo *mi)
 			mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
 			space(MINSPACE),
 			mkstring(buf4, 8, CENTER|RJUST, "-----"));
-	sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
+	sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%6d ",
 			VADDR_PRLEN,
 			space(MINSPACE),
 			(int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
@@ -5489,9 +5503,10 @@ dump_mem_map(struct meminfo *mi)
 			space(MINSPACE));
 
 	v22 = VALID_MEMBER(page_inode);  /* page.inode vs. page.mapping */
+	page_mapcount = VALID_MEMBER(page_mapcount);
 
         if (v22) {
-		sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
+		sprintf(hdr, "%s%s%s%s%s%s%s%sCOUNT FLAGS\n",
 		    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
 		    space(MINSPACE),               
                     mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
@@ -5502,7 +5517,7 @@ dump_mem_map(struct meminfo *mi)
 		    mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
 		    space(MINSPACE-1));
         } else {
-		sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
+		sprintf(hdr, "%s%s%s%s%s%s%sCOUNT%sFLAGS\n",
 		    mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"), 
 		    space(MINSPACE),             
                     mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
@@ -5510,7 +5525,8 @@ dump_mem_map(struct meminfo *mi)
 		    space(MINSPACE),             
 		    mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
 		    space(MINSPACE),               
-		    mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
+		    mkstring(buf4, 8, CENTER|RJUST, "INDEX"),
+		    (page_mapcount ? " MAPCOUNT " : " "));
         }
 
 	mapping = index = 0;
@@ -5717,10 +5733,18 @@ dump_mem_map(struct meminfo *mi)
 				else if (!page_mapping)
 					bufferindex += sprintf(outputbuffer+bufferindex,
 							(char *)&style3, pp, phys, count);
-				else
+				else {
 					bufferindex += sprintf(outputbuffer+bufferindex,
 							(char *)&style4, pp, phys,
 							mapping, index, count);
+					if (page_mapcount) {
+						mapcount = UINT(pcache +
+							OFFSET(page_mapcount));
+
+						bufferindex += sprintf(outputbuffer+bufferindex,
+								"%8d ", mapcount);
+					}
+				}
 			}
 	
 			others = 0;
-- 
1.9.3




More information about the Crash-utility mailing list