[Crash-utility] [PATCH] kmem: Add support to -S option to specify a range of CPU-specific slab data

HAGIO KAZUHITO(萩尾 一仁) k-hagio-ab at nec.com
Thu Jul 8 08:54:11 UTC 2021


-----Original Message-----
> With this patch, it is now possible for one to explicitly specify a range
> of CPU-specific slab data to list. For example:

Thanks for the patch, that is useful.

> 
> Note: This is only applicable to a Linux kernel with Kconfig
>       CONFIG_SLUB enabled. The optional argument GNU extension
>       for getopt(3) is utilised; and, the CPU range must be
>       specified as expected
> 
>     crash> kmem -S=1,4 kmalloc-512
>     CACHE             OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE  NAME
>     ffff8d3f07c06c00      512       1916      3680    115    16k  kmalloc-512
>     CPU 1 KMEM_CACHE_CPU:
>       ffff8d461fa6f140
>     CPU 1 SLAB:
>       SLAB              MEMORY            NODE  TOTAL  ALLOCATED  FREE
>       fffff540df7c4000  ffff8d45df100000     0     32          8    24
>       FREE / [ALLOCATED]
>        ffff8d45df100000  (cpu 1 cache)
>       [ffff8d45df100200]
>        ffff8d45df100400  (cpu 1 cache)
>       [ffff8d45df100600]
>        ffff8d45df100800  (cpu 1 cache)
>        ffff8d45df100a00  (cpu 1 cache)
>        ffff8d45df100c00  (cpu 1 cache)
>        ffff8d45df100e00  (cpu 1 cache)
>        ffff8d45df101000  (cpu 1 cache)
>       [ffff8d45df101200]
>      ...skipped ...
>     CPU 4 KMEM_CACHE_CPU:
>       ffff8d461fb2f140
>     CPU 4 SLAB:
>       SLAB              MEMORY            NODE  TOTAL  ALLOCATED  FREE
>       fffff540dfde3800  ffff8d45f78e0000     0     32          8    24
>       FREE / [ALLOCATED]
>       [ffff8d45f78e0000]
>        ffff8d45f78e0200  (cpu 4 cache)
>        ffff8d45f78e0400  (cpu 4 cache)
>       [ffff8d45f78e0600]
>        ffff8d45f78e0800  (cpu 4 cache)
>        ffff8d45f78e0a00  (cpu 4 cache)
>        ffff8d45f78e0c00  (cpu 4 cache)
>        ffff8d45f78e0e00  (cpu 4 cache)
>        ffff8d45f78e1000  (cpu 4 cache)
>        ffff8d45f78e1200  (cpu 4 cache)
>        ffff8d45f78e1400  (cpu 4 cache)
>       [ffff8d45f78e1600]
>      ...skipped ...
> 
> Signed-off-by: Aaron Tomlin <atomlin at redhat.com>
> ---
>  help.c   |  5 ++++-
>  memory.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 47 insertions(+), 5 deletions(-)
> 
> diff --git a/help.c b/help.c
> index e0c8408..8d40204 100644
> --- a/help.c
> +++ b/help.c
> @@ -6571,7 +6571,7 @@ char *help_kmem[] = {
>  "kmem",
>  "kernel memory",
>  "[-f|-F|-c|-C|-i|-v|-V|-n|-z|-o|-h] [-p | -m member[,member]]\n"
> -"       [[-s|-S|-r] [slab] [-I slab[,slab]]] [-g [flags]] [[-P] address]]",
> +"       [[-s|-S|-S=cpu[s]|-r] [slab] [-I slab[,slab]]] [-g [flags]] [[-P] address]]",
>  "  This command displays information about the use of kernel memory.\n",
>  "        -f  displays the contents of the system free memory headers.",
>  "            also verifies that the page count equals nr_free_pages.",
> @@ -6616,6 +6616,9 @@ char *help_kmem[] = {
>  "            slab data for each per-cpu slab is displayed, along with the",
>  "            address of each kmem_cache_node, its count of full and partial",
>  "            slabs, and a list of all tracked slabs.",
> +"            Note: one can specify the per-cpu slab data to be displayed;",
> +"            the cpu[s] can be given as \"1,3,5\", \"1-3\", \"1,3,5-7,10\",",
> +"            \"all\", or \"a\" (shortcut for \"all\").",
>  "        -r  displays the accumulated basic kmalloc() slab data of each",
>  "            root slab cache and its children.  The kernel must contain the",
>  "            \"slab_root_caches\" list_head. (currently only available if",
> diff --git a/memory.c b/memory.c
> index 8c6bbe4..ef7c3ec 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -47,6 +47,7 @@ struct meminfo {           /* general purpose memory information structure */
>  	int slab_offset;
>          char *reqname;
>  	char *curname;
> +	ulong *spec_cpumask;
>  	ulong *addrlist;
>  	int *kmem_bufctl;
>  	ulong *cpudata[NR_CPUS];
> @@ -4850,10 +4851,13 @@ cmd_kmem(void)
>  	struct meminfo meminfo;
>  	ulonglong value[MAXARGS];
>  	char buf[BUFSIZE];
> +	char arg_buf[BUFSIZE];
>  	char *p1;
> -	int spec_addr, escape;
> +	ulong *cpus;
> +	int spec_addr, escape, choose_cpu;
> 
> -	spec_addr = 0;
> +	cpus = NULL;
> +	spec_addr = choose_cpu = 0;
>          sflag =	Sflag = pflag = fflag = Fflag = Pflag = zflag = oflag = 0;
>  	vflag = Cflag = cflag = iflag = nflag = lflag = Lflag = Vflag = 0;
>  	gflag = hflag = rflag = 0;
> @@ -4862,7 +4866,7 @@ cmd_kmem(void)
>  	BZERO(&value[0], sizeof(ulonglong)*MAXARGS);
>  	pc->curcmd_flags &= ~HEADER_PRINTED;
> 
> -        while ((c = getopt(argcnt, args, "gI:sSrFfm:pvczCinl:L:PVoh")) != EOF) {
> +        while ((c = getopt(argcnt, args, "gI:sS::rFfm:pvczCinl:L:PVoh")) != EOF) {
>                  switch(c)
>  		{
>  		case 'V':
> @@ -4902,6 +4906,33 @@ cmd_kmem(void)
>  			break;
> 
>  		case 'S':
> +			if (choose_cpu)
> +				error(FATAL, "only one -S option allowed\n");
> +			/* Use the GNU extension with getopt(3) ... */
> +			if (optarg) {
> +				if (!(vt->flags & KMALLOC_SLUB))
> +					error(FATAL,
> +						"can only use -S=cpu(s) with a kernel \n"
> +						"that is built with CONFIG_SLUB support.\n");
> +				if (optarg[0] != '=')
> +					error(FATAL,
> +						"CPU-specific slab data to be displayed "
> +						"must be written as expected only e.g. -S=1,45.\n");
> +				/* Skip = ... */
> +				optarg++;
> +
> +				choose_cpu = 1;
> +				BZERO(arg_buf, BUFSIZE);
> +				strcpy(arg_buf, optarg);
> +
> +				cpus = get_cpumask_buf();
> +				make_cpumask(arg_buf, cpus, FAULT_ON_ERROR, NULL);
> +				meminfo.spec_cpumask = cpus;
> +

> +				for (i = 0; i < kt->cpus; i++)
> +					if (NUM_IN_BITMAP(cpus, i) && check_offline_cpu(i))
> +						error(INFO, "CPU %d is OFFLINE.\n", i);

By default, crash commands do not print this message for offline cpus,
it is printed only with the offline hide option:

crash> bt -c 15
PID: 0      TASK: ffff916041651840  CPU: 15  COMMAND: "swapper/15"
...
crash> set offline hide
      offline: hide
crash> bt -c 15
bt: CPU 15 is OFFLINE.

But ...

> +			}
>  			Sflag = 1; sflag = rflag = 0;
>  			break;
> 
> @@ -5184,6 +5215,8 @@ cmd_kmem(void)
>  			meminfo.flags = VERBOSE;
>  			vt->dump_kmem_cache(&meminfo);
>  		}
> +		if (choose_cpu)
> +			FREEBUF(cpus);
>  	}
> 
>  	if (vflag == 1)
> @@ -19079,7 +19112,13 @@ do_kmem_cache_slub(struct meminfo *si)
>  	per_cpu = (ulong *)GETBUF(sizeof(ulong) * vt->numnodes);
> 
>          for (i = 0; i < kt->cpus; i++) {
> -		if (hide_offline_cpu(i)) {
> +		if (si->spec_cpumask) {
> +			if (!(NUM_IN_BITMAP(si->spec_cpumask, i)))
> +				continue;
> +			else
> +				if (check_offline_cpu(i))
> +					continue;
> +		} else if (hide_offline_cpu(i)) {
>  			fprintf(fp, "CPU %d [OFFLINE]\n", i);
>  			continue;
>  		}

the kmem -S already follows the hide option in this way.

So would you remove the "CPU xx is OFFLINE" message above and
change this hunk like this?

        for (i = 0; i < kt->cpus; i++) {
+               if (si->spec_cpumask && !NUM_IN_BITMAP(si->spec_cpumask, i))
+                       continue;
+ 
                if (hide_offline_cpu(i)) {
                        fprintf(fp, "CPU %d [OFFLINE]\n", i);
                        continue;
                }

Thanks,
Kazu





More information about the Crash-utility mailing list