[Crash-utility] [RFC PATCH 1/2] crash: Show memory overcommit data in dump_kmeminfo()

Dave Anderson anderson at redhat.com
Fri Nov 21 17:06:03 UTC 2014


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




More information about the Crash-utility mailing list