-----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@xxxxxxxxxx> > --- > 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 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility