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@xxxxxxxxxx> Suggested-by: Alexis Solanas <alexis@xxxxxxxxxx> --- 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@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility