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@xxxxxxxxxx> --- 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 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility