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(a)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