Aaron,
I like the addition. But I've got a few nits regarding the patch.
Given that "kmem -i" is so commonly-used, I prefer not to introduce something
that could conceivably generate a command-killing "invalid structure member
offset" error. And that could happen in your hugetlb_total_pages() function
because of the hstate structure dependencies. (See dump_hstates() for example)
Also, in dump_kmeminfo() you use MEMBER_OFFSET(), which should be avoided
because it will quietly return -1 if the structure member doesn't exist,
leading to bogus output. That's the whole purpose behind using OFFSET(),
or at least storing/validating the MEMBER_OFFSET() return value before
blindly using it.
It may seem pedantic, but if history has shown us anything, it's that
kernel developers cannot stop themselves from changing structure/member
names.
So if you could just adjust those kinds of issues, this patch would be
a nice addition.
Thanks,
Dave
----- Original Message -----
This patch changes dump_kmeminfo() to report overcommit information
similar
to that displayed under the proc/meminfo file. It may be useful to indicate
memory over commitment abuse, for example with forced vmcores from system
hangs due to shortage of memory. The intended output is as follows:
crash> kmem -i
PAGES TOTAL PERCENTAGE
TOTAL MEM 1965332 7.5 GB ----
FREE 78080 305 MB 3% of TOTAL MEM
USED 1887252 7.2 GB 96% of TOTAL MEM
SHARED 789954 3 GB 40% of TOTAL MEM
BUFFERS 110606 432.1 MB 5% of TOTAL MEM
CACHED 1212645 4.6 GB 61% of TOTAL MEM
SLAB 146563 572.5 MB 7% of TOTAL MEM
TOTAL SWAP 1970175 7.5 GB ----
SWAP USED 5 20 KB 0% of TOTAL SWAP
SWAP FREE 1970170 7.5 GB 99% of TOTAL SWAP
COMMIT LIMIT 2952841 11.3 GB ----
COMMITTED 1150595 4.4 GB 38% of TOTAL LIMIT
Tested under 3.16.4-200.fc20.x86_64 only.
Though this should work under RHEL5 (2.6.18) and above.
Signed-off-by: Aaron Tomlin <atomlin(a)redhat.com>
Suggested-by: Alexis Solanas <alexis(a)redhat.com>
---
help.c | 33 ++++++++--------
memory.c | 132
+++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 134 insertions(+), 31 deletions(-)
diff --git a/help.c b/help.c
index 6aa3e20..bedd7c3 100644
--- a/help.c
+++ b/help.c
@@ -5587,23 +5587,26 @@ char *help_kmem[] = {
"\nEXAMPLES",
" Display memory usage information:\n",
" %s> kmem -i",
-" PAGES TOTAL PERCENTAGE",
-" TOTAL MEM 63602 248.4 MB ----",
-" FREE 993 3.9 MB 1% of TOTAL MEM",
-" USED 62609 244.6 MB 98% of TOTAL MEM",
-" SHARED 34035 132.9 MB 53% of TOTAL MEM",
-" BUFFERS 10928 42.7 MB 17% of TOTAL MEM",
-" CACHED 35249 137.7 MB 55% of TOTAL MEM",
-" SLAB 2823 11 MB 4% of TOTAL MEM",
+" PAGES TOTAL PERCENTAGE",
+" TOTAL MEM 63602 248.4 MB ----",
+" FREE 993 3.9 MB 1% of TOTAL MEM",
+" USED 62609 244.6 MB 98% of TOTAL MEM",
+" SHARED 34035 132.9 MB 53% of TOTAL MEM",
+" BUFFERS 10928 42.7 MB 17% of TOTAL MEM",
+" CACHED 35249 137.7 MB 55% of TOTAL MEM",
+" SLAB 2823 11 MB 4% of TOTAL MEM",
" ",
-" TOTAL HIGH 0 0 0% of TOTAL MEM",
-" FREE HIGH 0 0 0% of TOTAL HIGH",
-" TOTAL LOW 63602 248.4 MB 100% of TOTAL MEM",
-" FREE LOW 993 3.9 MB 1% of TOTAL LOW",
+" TOTAL HIGH 0 0 0% of TOTAL MEM",
+" FREE HIGH 0 0 0% of TOTAL HIGH",
+" TOTAL LOW 63602 248.4 MB 100% of TOTAL MEM",
+" FREE LOW 993 3.9 MB 1% of TOTAL LOW",
" ",
-" TOTAL SWAP 129792 507 MB ----",
-" SWAP USED 14727 57.5 MB 11% of TOTAL SWAP",
-" SWAP FREE 115065 449.5 MB 88% of TOTAL SWAP",
+" TOTAL SWAP 129792 507 MB ----",
+" SWAP USED 14727 57.5 MB 11% of TOTAL SWAP",
+" SWAP FREE 115065 449.5 MB 88% of TOTAL SWAP",
+" ",
+" COMMIT LIMIT 2952841 11.3 GB ----",
+" COMMITTED 1158600 4.4 GB 39% of TOTAL LIMIT",
" ",
" ZONE NAME FREE ACTIVE INACTIVE_DIRTY INACTIVE_CLEAN
MIN/LOW/HIGH",
" 0 DMA 240 1166 7 161
128/256/384 ",
diff --git a/memory.c b/memory.c
index 3ac928d..823ec75 100644
--- a/memory.c
+++ b/memory.c
@@ -227,6 +227,7 @@ static int vm_area_page_dump(ulong, ulong, ulong, ulong,
ulong,
struct reference *);
static void rss_page_types_init(void);
static int dump_swap_info(ulong, ulong *, ulong *);
+static ulong hugetlb_total_pages(void);
static void swap_info_init(void);
static char *get_swapdev(ulong, char *);
static void fill_swap_info(ulong);
@@ -4627,7 +4628,7 @@ cmd_kmem(void)
}
- if (iflag == 1)
+ if (iflag)
dump_kmeminfo();
if (pflag == 1)
@@ -7653,7 +7654,7 @@ bailout:
* by /proc/meminfo, and then some...
*/
-char *kmeminfo_hdr = " PAGES TOTAL PERCENTAGE\n";
+char *kmeminfo_hdr = " PAGES TOTAL
PERCENTAGE\n";
static void
dump_kmeminfo(void)
@@ -7670,6 +7671,10 @@ dump_kmeminfo(void)
ulong freehighmem_pages;
ulong totallowmem_pages;
ulong freelowmem_pages;
+ ulong allowed;
+ long committed;
+ ulong overcommit_kbytes;
+ int overcommit_ratio;
long nr_file_pages, nr_slab;
ulong swapper_space_nrpages;
ulong pct;
@@ -7720,7 +7725,7 @@ dump_kmeminfo(void)
} else
totalram_pages = get_totalram;
- fprintf(fp, "%10s %7ld %11s ----\n", "TOTAL MEM",
+ fprintf(fp, "%13s %7ld %11s ----\n", "TOTAL MEM",
totalram_pages, pages_to_size(totalram_pages, buf));
/*
@@ -7731,12 +7736,12 @@ dump_kmeminfo(void)
vt->dump_free_pages(&meminfo);
freeram_pages = meminfo.retval;
pct = (freeram_pages * 100)/totalram_pages;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL MEM\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n",
"FREE", freeram_pages, pages_to_size(freeram_pages, buf), pct);
used_pages = totalram_pages - freeram_pages;
pct = (used_pages * 100)/totalram_pages;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL MEM\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n",
"USED", used_pages, pages_to_size(used_pages, buf), pct);
/*
@@ -7745,7 +7750,7 @@ dump_kmeminfo(void)
* pages that have a count of greater than 1.
*/
pct = (shared_pages * 100)/totalram_pages;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL MEM\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n",
"SHARED", shared_pages, pages_to_size(shared_pages, buf), pct);
subtract_buffer_pages = 0;
@@ -7762,7 +7767,7 @@ dump_kmeminfo(void)
buffer_pages = 0;
pct = (buffer_pages * 100)/totalram_pages;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL MEM\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n",
"BUFFERS", buffer_pages, pages_to_size(buffer_pages, buf), pct);
if (CRASHDEBUG(1))
@@ -7816,7 +7821,7 @@ dump_kmeminfo(void)
pct = (page_cache_size * 100)/totalram_pages;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL MEM\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n",
"CACHED", page_cache_size,
pages_to_size(page_cache_size, buf), pct);
@@ -7826,7 +7831,7 @@ dump_kmeminfo(void)
*/
pct = (get_slabs * 100)/totalram_pages;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL MEM\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n",
"SLAB", get_slabs, pages_to_size(get_slabs, buf), pct);
if (symbol_exists("totalhigh_pages")) {
@@ -7851,7 +7856,7 @@ dump_kmeminfo(void)
pct = totalhigh_pages ?
(totalhigh_pages * 100)/totalram_pages : 0;
- fprintf(fp, "\n%10s %7ld %11s %3ld%% of TOTAL MEM\n",
+ fprintf(fp, "\n%13s %7ld %11s %3ld%% of TOTAL MEM\n",
"TOTAL HIGH", totalhigh_pages,
pages_to_size(totalhigh_pages, buf), pct);
@@ -7860,19 +7865,19 @@ dump_kmeminfo(void)
freehighmem_pages = meminfo.retval;
pct = freehighmem_pages ?
(freehighmem_pages * 100)/totalhigh_pages : 0;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL HIGH\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL HIGH\n",
"FREE HIGH", freehighmem_pages,
pages_to_size(freehighmem_pages, buf), pct);
totallowmem_pages = totalram_pages - totalhigh_pages;
pct = (totallowmem_pages * 100)/totalram_pages;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL MEM\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n",
"TOTAL LOW", totallowmem_pages,
pages_to_size(totallowmem_pages, buf), pct);
freelowmem_pages = freeram_pages - freehighmem_pages;
pct = (freelowmem_pages * 100)/totallowmem_pages;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL LOW\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL LOW\n",
"FREE LOW", freelowmem_pages,
pages_to_size(freelowmem_pages, buf), pct);
}
@@ -7884,18 +7889,18 @@ dump_kmeminfo(void)
if (symbol_exists("swapper_space") ||
symbol_exists("swapper_spaces")) {
if (dump_swap_info(RETURN_ON_ERROR, &totalswap_pages,
&totalused_pages)) {
- fprintf(fp, "%10s %7ld %11s ----\n",
+ fprintf(fp, "%13s %7ld %11s ----\n",
"TOTAL SWAP", totalswap_pages,
pages_to_size(totalswap_pages, buf));
pct = totalswap_pages ? (totalused_pages * 100) /
totalswap_pages : 100;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL SWAP\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL SWAP\n",
"SWAP USED", totalused_pages,
pages_to_size(totalused_pages, buf), pct);
pct = totalswap_pages ?
((totalswap_pages - totalused_pages) *
100) / totalswap_pages : 0;
- fprintf(fp, "%10s %7ld %11s %3ld%% of TOTAL SWAP\n",
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL SWAP\n",
"SWAP FREE",
totalswap_pages - totalused_pages,
pages_to_size(totalswap_pages - totalused_pages,
@@ -7905,6 +7910,56 @@ dump_kmeminfo(void)
"swap_info[%ld].swap_map at %lx is inaccessible\n",
totalused_pages, totalswap_pages);
}
+ /*
+ * Show committed memory
+ */
+ if (kernel_symbol_exists("sysctl_overcommit_memory")) {
+ fprintf(fp, "\n");
+ if (kernel_symbol_exists("sysctl_overcommit_kbytes")) {
+ get_symbol_data("sysctl_overcommit_kbytes",
+ sizeof(ulong), &overcommit_kbytes);
+ if (overcommit_kbytes)
+ allowed = overcommit_kbytes >>
+ (machdep->pageshift - 10);
+ else {
+ get_symbol_data("sysctl_overcommit_ratio",
+ sizeof(int),
+ &overcommit_ratio);
+ allowed = ((totalram_pages - hugetlb_total_pages())
+ * overcommit_ratio / 100);
+ }
+ }
+ if (symbol_exists("vm_committed_as")) {
+ readmem(symbol_value("vm_committed_as") +
+ MEMBER_OFFSET("percpu_counter",
+ "count"), KVADDR,
+ &committed,
+ sizeof(long),
+ "percpu_counter count",
+ FAULT_ON_ERROR);
+
+ /* Ensure always positive */
+ if (committed < 0)
+ committed = 0;
+ } else {
+ readmem(symbol_value("vm_committed_space") +
+ MEMBER_OFFSET("atomic_t",
+ "counter"), KVADDR,
+ &committed, sizeof(int),
+ "atomic_t counter",
+ FAULT_ON_ERROR);
+ }
+ allowed += totalswap_pages;
+ fprintf(fp, "%13s %7ld %11s ----\n",
+ "COMMIT LIMIT", allowed,
+ pages_to_size(allowed, buf));
+
+ pct = committed ? ((committed * 100)
+ / allowed) : 0;
+ fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL LIMIT\n",
+ "COMMITTED", committed,
+ pages_to_size(committed, buf), pct);
+ }
dump_zone_page_usage();
}
@@ -14734,6 +14789,51 @@ next_physpage(ulonglong paddr, ulonglong *nextpaddr)
return FALSE;
}
+ulong
+hugetlb_total_pages(void)
+{
+ ulong hstate_p;
+ int i, len;
+ ulong nr_total_pages = 0;
+ ulong nr_huge_pages;
+ uint horder;
+
+ if (kernel_symbol_exists("hstates")) {
+ STRUCT_SIZE_INIT(hstate, "hstate");
+ MEMBER_OFFSET_INIT(hstate_order, "hstate", "order");
+ MEMBER_OFFSET_INIT(hstate_nr_huge_pages, "hstate",
"nr_huge_pages");
+
+ len = get_array_length("hstates", NULL, 0);
+ hstate_p = symbol_value("hstates");
+
+ for (i = 0; i < len; i++) {
+ hstate_p = hstate_p + (SIZE(hstate) * i);
+
+ readmem(hstate_p + OFFSET(hstate_order), KVADDR,
+ &horder, sizeof(uint),
+ "hstate_order",
+ FAULT_ON_ERROR);
+
+ readmem(hstate_p + OFFSET(hstate_nr_huge_pages), KVADDR,
+ &nr_huge_pages, sizeof(ulong),
+ "hstate_nr_huge_pages",
+ FAULT_ON_ERROR);
+
+ nr_total_pages += nr_huge_pages * (1 << horder);
+ }
+ } else if (kernel_symbol_exists("nr_huge_pages")) {
+ unsigned long hpage_shift = 21;
+
+ if ((machine_type("X86") && !(machdep->flags & PAE)))
+ hpage_shift = 22;
+ get_symbol_data("nr_huge_pages",
+ sizeof(ulong), &nr_huge_pages);
+ nr_total_pages = nr_huge_pages * ((1 << hpage_shift) /
+ machdep->pagesize);
+ }
+ return nr_total_pages;
+}
+
/*
* Display swap statistics.
*/
--
1.9.3
--
Crash-utility mailing list
Crash-utility(a)redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility