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]>
---
Changes since v1:

  - Do not explicitly exclude an offline CPU
    as this is handled via hide_offline_cpu()
    logic (Kazu)

---
 help.c   |  5 ++++-
 memory.c | 41 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/help.c b/help.c
index 99be7cb..6c262a3 100644
--- a/help.c
+++ b/help.c
@@ -6601,7 +6601,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.",
@@ -6649,6 +6649,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 cbe90ee..d59784c 100644
--- a/memory.c
+++ b/memory.c
@@ -48,6 +48,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];
@@ -4851,10 +4852,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;
@@ -4863,7 +4867,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':
@@ -4903,6 +4907,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;
 
@@ -5185,6 +5216,8 @@ cmd_kmem(void)
                        meminfo.flags = VERBOSE;
                        vt->dump_kmem_cache(&meminfo);
                }
+               if (choose_cpu)
+                       FREEBUF(cpus);
        }
 
        if (vflag == 1)
@@ -19083,6 +19116,8 @@ do_kmem_cache_slub(struct meminfo *si)
        per_cpu = (ulong *)GETBUF(sizeof(ulong) * vt->numnodes);
 
         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;
-- 
2.31.1

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

Reply via email to