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

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 <[email protected]>
---
 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);
+                       }
                        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;
                }
-- 
2.31.1

--
Crash-utility mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/crash-utility

Reply via email to