Hi Dave,

Please share your thoughts on adding a -m option to kmem to display
the free pages per migrate type.
This is similar to /proc/pagetypeinfo.

Sample output (without formatting). Patch attached.

crash>
Free pages count per migrate type at order  [0-10]:
Node    0, zone   Normal, type    Unmovable    155    172     92
39     20      8     10     15      7      3      1
Node    0, zone  HighMem, type    Unmovable      1      2      0
0      0      0      0      0      0      0      0
Node    0, zone  Movable, type    Unmovable      0      0      0
0      0      0      0      0      0      0      0
Node    0, zone   Normal, type  Reclaimable      9      3      0
0      1      1      0      0      0      0      0
Node    0, zone  HighMem, type  Reclaimable      0      0      0
0      0      0      0      0      0      0      0
Node    0, zone  Movable, type  Reclaimable      0      0      0
0      0      0      0      0      0      0      0
Node    0, zone   Normal, type      Movable      7     68     35
253    137     38     16      4      0      0     66
Node    0, zone  HighMem, type      Movable      0      1      0
0      0      0      0      0      0      0      0
Node    0, zone  Movable, type      Movable      0      0      0
0      0      0      0      0      0      0      0
Node    0, zone   Normal, type      Reserve      0      0      0
0      0      0      0      0      0      0      1
Node    0, zone  HighMem, type      Reserve     11      7      5
1      0      0      0      0      0      0      0
Node    0, zone  Movable, type      Reserve      0      0      0
0      0      0      0      0      0      0      0
Node    0, zone   Normal, type      Isolate      0      0      0
0      0      0      0      0      0      0      0
Node    0, zone  HighMem, type      Isolate      0      0      0
0      0      0      0      0      0      0      0
Node    0, zone  Movable, type      Isolate      0      0      0
0      0      0      0      0      0      0      0


diff --git a/crash-6.0.8/help.c b/crash-6.0.8/help.c
index 6d6ac5e..9ad6c00 100755
--- a/crash-6.0.8/help.c
+++ b/crash-6.0.8/help.c
@@ -5147,7 +5147,7 @@ NULL
 char *help_kmem[] = {
 "kmem",
 "kernel memory",
-"[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-z-o] [slab] [[-P] address]\n"
+"[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-m|-z-o] [slab] [[-P] address]\n"
 "       [-g [flags]]",
 "  This command displays information about the use of kernel memory.\n",
 "        -f  displays the contents of the system free memory headers.",
@@ -5174,6 +5174,8 @@ char *help_kmem[] = {
 "            values to translate them into kernel virtual addresses.",
 "        -g  displays the enumerator value of all bits in the page
structure's",
 "            \"flags\" field.",
+"        -m  displays the number of pages per migrate type for all
orders, for all",
+"            nodes.",
 "     flags  when used with -g, translates all bits in this hexadecimal page",
 "            structure flags value into its enumerator values.",
 "      slab  when used with -s or -S, limits the command to only the
slab cache",
@@ -5605,6 +5607,24 @@ char *help_kmem[] = {
 "      PG_slab            7  0000080",
 "      PG_head           14  0004000",
 "    %s>",
+"\n  Display pages per migrate type for all orders, for all nodes:\n",
+"    %s> kmem -m",
+"    Free pages count per migrate type at order [0-10]:",
+"    Node    0, zone   Normal, type    Unmovable    155    172     92
    39     20      8     10     15      7      3      1",
+"    Node    0, zone  HighMem, type    Unmovable      1      2      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone  Movable, type    Unmovable      0      0      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone   Normal, type  Reclaimable      9      3      0
     0      1      1      0      0      0      0      0",
+"    Node    0, zone  HighMem, type  Reclaimable      0      0      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone  Movable, type  Reclaimable      0      0      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone   Normal, type      Movable      7     68     35
   253    137     38     16      4      0      0     66",
+"    Node    0, zone  HighMem, type      Movable      0      1      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone  Movable, type      Movable      0      0      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone   Normal, type      Reserve      0      0      0
     0      0      0      0      0      0      0      1",
+"    Node    0, zone  HighMem, type      Reserve     11      7      5
     1      0      0      0      0      0      0      0",
+"    Node    0, zone  Movable, type      Reserve      0      0      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone   Normal, type      Isolate      0      0      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone  HighMem, type      Isolate      0      0      0
     0      0      0      0      0      0      0      0",
+"    Node    0, zone  Movable, type      Isolate      0      0      0
     0      0      0      0      0      0      0      0",
 NULL
 };

diff --git a/crash-6.0.8/memory.c b/crash-6.0.8/memory.c
index 02a6de1..e03db84 100755
--- a/crash-6.0.8/memory.c
+++ b/crash-6.0.8/memory.c
@@ -264,6 +264,7 @@ static int verify_pfn(ulong);
 static void dump_per_cpu_offsets(void);
 static void dump_page_flags(ulonglong);
 static ulong kmem_cache_nodelists(ulong);
+static void dump_pgtype_info(void);

 /*
  *  Memory display modes specific to this file.
@@ -4044,6 +4045,8 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
  *      -c  displays the number of pages in the page_hash_table.
  *      -C  displays all entries in the page_hash_table.
  *      -i  displays informational data shown by /proc/meminfo.
+ *      -m  displays information on the number of pages per migrate type
+ *          for all orders, for all nodes.
  *
  *      -P  forces address to be defined as a physical address
  * address  when used with -f, the address can be either a page pointer
@@ -4090,7 +4093,7 @@ cmd_kmem(void)
        int i;
        int c;
        int sflag, Sflag, pflag, fflag, Fflag, vflag, zflag, oflag, gflag;
-       int nflag, cflag, Cflag, iflag, lflag, Lflag, Pflag, Vflag;
+       int nflag, cflag, Cflag, iflag, lflag, Lflag, Pflag, Vflag, mflag;
        struct meminfo meminfo;
        ulonglong value[MAXARGS];
        char buf[BUFSIZE];
@@ -4100,12 +4103,12 @@ cmd_kmem(void)
        spec_addr = 0;
         sflag =        Sflag = pflag = fflag = Fflag = Pflag = zflag = oflag = 
0;
        vflag = Cflag = cflag = iflag = nflag = lflag = Lflag = Vflag = 0;
-       gflag = 0;
+       gflag = mflag = 0;
        escape = FALSE;
        BZERO(&meminfo, sizeof(struct meminfo));
        BZERO(&value[0], sizeof(ulonglong)*MAXARGS);

-        while ((c = getopt(argcnt, args, "gI:sSFfpvczCinl:L:PVo")) != EOF) {
+        while ((c = getopt(argcnt, args, "gI:sSFfpvczCinml:L:PVo")) != EOF) {
                 switch(c)
                {
                case 'V':
@@ -4206,6 +4209,10 @@ cmd_kmem(void)
                        gflag = 1;
                        break;

+               case 'm':
+                       mflag = 1;
+                       break;
+
                default:
                        argerrs++;
                        break;
@@ -4215,8 +4222,8 @@ cmd_kmem(void)
        if (argerrs)
                cmd_usage(pc->curcmd, SYNOPSIS);

-        if ((sflag + Sflag + pflag + fflag + Fflag + Vflag + oflag +
-            vflag + Cflag + cflag + iflag + lflag + Lflag + gflag) > 1) {
+        if ((sflag + Sflag + pflag + fflag + Fflag + Vflag + oflag + vflag +
+               Cflag + cflag + iflag + lflag + Lflag + gflag + mflag) > 1) {
                error(INFO, "only one flag allowed!\n");
                cmd_usage(pc->curcmd, SYNOPSIS);
        }
@@ -4444,9 +4451,12 @@ cmd_kmem(void)
        if (gflag == 1)
                dump_page_flags(0);

+       if (mflag == 1)
+               dump_pgtype_info();
+
        if (!(sflag + Sflag + pflag + fflag + Fflag + vflag +
              Vflag + zflag + oflag + cflag + Cflag + iflag +
-             nflag + lflag + Lflag + gflag + meminfo.calls))
+             nflag + lflag + Lflag + gflag + mflag + meminfo.calls))
                cmd_usage(pc->curcmd, SYNOPSIS);

 }
@@ -7051,6 +7061,163 @@ bailout:
        return total_free;
 }

+static void dump_pgtype_info(void)
+{
+       int n, m, z, o;
+       int list_count = 0;
+       int free_cnt = 0;
+       int mtype_sym = 0;
+       int mtype_len = 0;
+       ulong *mtypes;
+       ulong node_zones;
+       ulong temp;
+       ulong freelist;
+       ulong *free_ptr;
+       char *free_list_buf;
+       char name_buf[BUFSIZE];
+       char buf[BUFSIZE];
+       struct node_table *nt;
+       struct list_data list_data;
+
+       if (!(vt->flags & (NODES|ZONES)))
+               error(FATAL,
+                       "dump_pgtype_info called without (NODES|ZONES)\n");
+
+       if (!VALID_STRUCT(zone))
+               error(FATAL,
+                       "zone struct not available in this kernel\n");
+
+       if (VALID_STRUCT(free_area)) {
+               if (SIZE(free_area) == (3 * sizeof(ulong)))
+                       error(FATAL,
+                               "free_area type not supported by command\n");
+               else
+                       list_count = MEMBER_SIZE("free_area",
+                                       "free_list")/SIZE(list_head);
+       } else
+               error(FATAL,
+                       "free_area structure not found\n");
+
+       free_list_buf = GETBUF(SIZE(list_head));
+
+       do {
+               if (symbol_exists("migratetype_names") &&
+                       (get_symbol_type("migratetype_names",
+                                        NULL, NULL) == TYPE_CODE_ARRAY)) {
+
+                       open_tmpfile();
+                       sprintf(buf, "whatis migratetype_names");
+                       if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) {
+                               close_tmpfile();
+                               break;
+                       }
+
+                       rewind(pc->tmpfile);
+                       while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+                               if (STRNEQ(buf, "type = "))
+                                       break;
+                       }
+                       close_tmpfile();
+
+                       if (!strstr(buf, "char *") ||
+                               (count_chars(buf, '[') != 1) ||
+                               (count_chars(buf, ']') != 1))
+                               break;
+
+                       mtype_len = get_array_length("migratetype_names",
+                                       NULL, 0);
+
+                       mtypes = (ulong *)GETBUF(mtype_len * sizeof(ulong));
+
+                       readmem(symbol_value("migratetype_names"),
+                                       KVADDR, mtypes,
+                                       (mtype_len * sizeof(ulong)),
+                                       NULL, FAULT_ON_ERROR);
+
+                       mtype_sym = 1;
+               }
+       } while (0);
+
+       fprintf(fp, "%-43s [%d-%d]:",
+                       "Free pages count per migrate type at order",
+                       0, vt->nr_free_areas - 1);
+
+       fprintf(fp, "\n");
+
+       for (n = 0; n < vt->numnodes; n++) {
+               nt = &vt->node_table[n];
+               node_zones = nt->pgdat + OFFSET(pglist_data_node_zones);
+
+               for (m = 0; m < list_count; m++) {
+
+                       for (z = 0; z < vt->nr_zones; z++) {
+                               readmem((node_zones + (z * SIZE(zone)))
+                                       + OFFSET(zone_name), KVADDR, &temp,
+                                       sizeof(void *), "node_zones name",
+                                       FAULT_ON_ERROR);
+                               read_string(temp, name_buf, BUFSIZE-1);
+
+                               fprintf(fp, "Node %4d, ", nt->node_id);
+                               fprintf(fp, "zone %8s, ", name_buf);
+
+                               if (mtype_sym) {
+                                       read_string(mtypes[m],
+                                               name_buf, BUFSIZE-1);
+                                       fprintf(fp, "type %12s ", name_buf);
+                               } else
+                                       fprintf(fp, "type %12d ", m);
+
+                               for (o = 0; o < vt->nr_free_areas; o++) {
+                                       freelist =
+                                       (node_zones + (z * SIZE(zone)))
+                                       + (OFFSET(zone_free_area) +
+                                       (o * SIZE(free_area))) +
+                                       (m * SIZE(list_head));
+
+                                       readmem(freelist, KVADDR, free_list_buf,
+                                               SIZE(list_head),
+                                               "free_area free_list",
+                                               FAULT_ON_ERROR);
+
+                                       free_ptr = (ulong *)free_list_buf;
+
+                                       if (!(*free_ptr) ||
+                                               (*free_ptr == freelist)) {
+                                               fprintf(fp, "%6lu ", 0);
+                                               continue;
+                                       }
+
+                                       BZERO(&list_data,
+                                               sizeof(struct list_data));
+                                       list_data.flags = RETURN_ON_DUPLICATE;
+                                       list_data.start = *free_ptr;
+                                       list_data.end = freelist;
+                                       list_data.list_head_offset =
+                                               OFFSET(page_lru) +
+                                               OFFSET(list_head_next);
+
+                                       free_cnt = do_list(&list_data);
+                                       if (free_cnt < 0) {
+                                               error(pc->curcmd_flags &
+                                               IGNORE_ERRORS ? INFO : FATAL,
+                                               "corrupted free list\n");
+                                               free_cnt = 0;
+                                       }
+
+                                       fprintf(fp, "%6lu ", free_cnt);
+                               }
+                               fprintf(fp, "\n");
+                       }
+               }
+               node_zones + OFFSET(zone_free_area);
+       }
+
+       FREEBUF(free_list_buf);
+
+       if (mtype_sym)
+               FREEBUF(mtypes);
+}
+
 /*
  *  dump_kmeminfo displays basic memory use information typically shown
  *  by /proc/meminfo, and then some...
-- 
1.7.6

Attachment: 0001-memory-adding-an-option-to-kmem-to-display-the-paget.patch
Description: Binary data

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

Reply via email to