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