[Crash-utility] [PATCH] kmem option to display pages per migrate type
Dave Anderson
anderson at redhat.com
Fri Mar 29 19:46:25 UTC 2013
----- 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
>
More information about the Crash-utility
mailing list