----- Original Message ----- > 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. OK, now there's two competing "kmem -m" patch requests out there -- neither of which I'm particularly interested in maintaining. Look, the crash utility could effectively mimic every file in the /proc filesystem. But that doesn't mean that it should -- somewhere that has to be a line to be drawn. Can you make it an extension module? I'll host it on the extensions web page, and if there becomes a consensus where people find that they can't live without it, then it can be reconsidered for the base crash utility. Dave > > 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 > -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility