----- Original Message -----
> The dump_mem_map() function displays basic data about each entry in the
> mem_map[] array, or if an address is specified, just the mem_map[] entry
> for that address. This patch introduces the -m option to be used with
> 'kmem -p' exclusively. When used with -p, a comma-separated list of one or
> more struct page members may be specified to generate a custom, formatted
> display. For example:
> 
>   crash> kmem -p -m mapping,index,_mapcount.counter,_count.counter
>   ffffea0000000000    0x0     0       0       0
>   ffffea0000000040    0x0     0       -1      1
>   ffffea0000000080    0x0     0       -1      1
>   ffffea00000000c0    0x0     0       -1      1
>   ffffea0000000100    0x0     0       -1      1
>   ffffea0000000140    0x0     0       -1      1
>   ffffea0000000180    0x0     0       -1      1
>   ffffea00000001c0    0x0     0       -1      1
>   ffffea0000000200    0x0     0       -1      1
>   ffffea0000000240    0x0     0       -1      1
>   ...
> 
> Signed-off-by: Aaron Tomlin <[email protected]>

Hi Aaron,

I've been waiting patiently for this patch to arrive, and it is
a good start, but this may take a couple go-arounds.

First off, it's almost impossible for me to effectively review this
patch because it does all the work inside of the already utterly-confusing
dump_mem_map_sparsemem() and dump_mem_map() functions.  I'll take the blame
for their current condition, because over the years I have patched and
re-patched, and taken in other folk's patches, many times -- all to 
the detriment of understandability/maintainability.  So please 
understand that I am reviewing my own code as much as yours.

So here are my initial suggestions.  

The -m optarg string received in cmd_kmem() should immediately be error-checked
and then handled in one place instead of duplicating the functionality in both
dump_mem_map_SPARSEMEM() and dump_mem_map() functions.

And the same thing goes w/respect to the duplication of effort when making
the calls to fill_struct_member_data().

When you posted your first patch a few weeks ago, I had tinkered with a 
proof-of-concept
of this option, which led to my creation of the fill_struct_member_data().  
Here's what
I did:

First, in cmd_kmem(), the option string was immediately vetted like so:

                case 'm':
                        collect_page_member_data(optarg);
                        break;

Second, in collect_page_member_data(), I created an array of struct_member_data 
structures:

static void
collect_page_member_data(char *optlist)
{
        int i;
        int members;
        char *opt_string;
        char *memberlist[MAXARGS];
        struct struct_member_data *page_member_cache, *pmd;

        if ((count_chars(optlist, ',')+1) > MAXARGS)
                error(FATAL, "too many members in comma-separated list\n");

        opt_string = STRDUPBUF(optlist);
        replace_string(opt_string, ",", ' ');

        if (!(members = parse_line(opt_string, memberlist)))
                error(FATAL, "invalid page struct member list format: %s\n", 
                        optlist);

        page_member_cache = (struct struct_member_data *)
                GETBUF(sizeof(struct struct_member_data) * members);

        for (i = 0, pmd = page_member_cache; i < members; i++, pmd++) {
                pmd->structure = "page";
                pmd->member = memberlist[i];
                if (!fill_struct_member_data(pmd))
                        error(FATAL, "invalid %s struct member: %s\n", 
                                pmd->structure, pmd->member);
                if (CRASHDEBUG(1)) {
                        fprintf(fp, "      structure: %s\n", pmd->structure);
                        fprintf(fp, "         member: %s\n", pmd->member);
                        fprintf(fp, "           type: %ld\n", pmd->type);
                        fprintf(fp, "  unsigned_type: %ld\n", 
pmd->unsigned_type);
                        fprintf(fp, "         length: %ld\n", pmd->length);
                        fprintf(fp, "         offset: %ld\n", pmd->offset);
                        fprintf(fp, "         bitpos: %ld\n", pmd->bitpos);
                        fprintf(fp, "        bitsize: %ld\n", pmd->bitsize);
                }
        }
}

However, that's as far as I took it.  What would also need to be done is for 
cmd_kmem()
to pass the meminfo pointer in to collect_page_member_data(), and have it store 
both
the "members" count and the "page_member_cache" pointer into new members in the 
meminfo
structure.

Then, like your meminfo->include, dump_mem_map_SPARSEMEM() and dump_mem_map() 
can key
on the existence of a non-zero meminfo "members" counter to perform the new 
functionality.

But the biggest change I'd like you to make it to move the new display 
functionality
completely out of dump_mem_map_SPARSEMEM() and dump_mem_map(), and put it in a
new common function.  Let's not make those two functions any uglier than they
already are.  

So taking dump_mem_map_SPARSEMEM() for example, it should simply require the 
addition
of a few lines to each function, i.e., something like this: 

       for (section_nr = 0; section_nr < nr_mem_sections ; section_nr++) {
 ... [ cut ] ...
                for (i = 0; i < section_size;
                     i++, pp += SIZE(page), phys += PAGESIZE()) {
 ... [ cut ] ...

                        if (!done && (pg_spec || phys_spec))
                                continue;

+                       if (mi->members_count) {
+                               bufferindex += do_your_function(pp, pcache, mi, 
outputbuffer+bufferindex);
+                               goto display_members;
+                       }

 ... [ cut ] ...
 
+ display_members:
                        if (bufferindex > buffersize) {
                                fprintf(fp, "%s", outputbuffer);
                                bufferindex = 0;
                        }

You would still need to prevent the old header from being displayed similar to 
what
you have done in your patch, but something like the above should be possible.

Then I could just review the actual functionality of your patch.  There are a 
few 
issues there I'd like to discuss, but how about we get my initial bitch-fest out
of the way first.

Agreed?  

Dave



> ---
>  help.c   |   19 +-
>  memory.c | 1074
>  ++++++++++++++++++++++++++++++++++++--------------------------
>  2 files changed, 649 insertions(+), 444 deletions(-)
> 
> diff --git a/help.c b/help.c
> index b2f4d21..76b640a 100644
> --- a/help.c
> +++ b/help.c
> @@ -5530,7 +5530,7 @@ char *help_kmem[] = {
>  "kmem",
>  "kernel memory",
>  "[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-z|-o|-h] [slab] [[-P] address]\n"
> -"       [-g [flags]] [-I slab[,slab]]",
> +"       [-g [flags]] [-I slab[,slab]] [-m member[,member]]",
>  "  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.",
> @@ -5565,6 +5565,9 @@ char *help_kmem[] = {
>  "            all slab cache names and addresses are listed.",
>  "   -I slab  when used with -s or -S, one or more slab cache names in a",
>  "            comma-separated list may be specified as slab caches to
>  ignore.",
> +" -m member  when used with -p, a comma-separated list of one or more",
> +"            struct page members may be specified to generate a custom",
> +"            formatted display.",
>  "        -P  declares that the following address argument is a physical
>  address.",
>  "   address  when used without any flag, the address can be a kernel
>  virtual,",
>  "            or physical address; a search is made through the symbol
>  table,",
> @@ -5717,6 +5720,20 @@ char *help_kmem[] = {
>  "    f5c51440     22000         0         0  1 80 slab",
>  "    ...",
>  "    ",
> +"  Dump the mem_map[] array but select desired fields:\n",
> +"    %s> kmem -p -m mapping,index,_mapcount.counter",
> +"    ffffea0000000000        0x0     0       0",
> +"    ffffea0000000040        0x0     0       -1",
> +"    ffffea0000000080        0x0     0       -1",
> +"    ffffea00000000c0        0x0     0       -1",
> +"    ffffea0000000100        0x0     0       -1",
> +"    ffffea0000000140        0x0     0       -1",
> +"    ffffea0000000180        0x0     0       -1",
> +"    ffffea00000001c0        0x0     0       -1",
> +"    ffffea0000000200        0x0     0       -1",
> +"    ffffea0000000240        0x0     0       -1",
> +"    ...",
> +"    ",
>  "  Use the commands above with a page pointer or a physical address
>  argument:\n",
>  "    %s> kmem -f c40425b0",
>  "    NODE ",
> diff --git a/memory.c b/memory.c
> index aacf929..d4114c2 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -55,6 +55,7 @@ struct meminfo {           /* general purpose memory
> information structure */
>       ulong found;
>       ulong retval;
>       char *ignore;
> +     char *include;
>       int errors;
>       int calls;
>       int cpu;
> @@ -4425,7 +4426,7 @@ cmd_kmem(void)
>       BZERO(&meminfo, sizeof(struct meminfo));
>       BZERO(&value[0], sizeof(ulonglong)*MAXARGS);
>  
> -        while ((c = getopt(argcnt, args, "gI:sSFfpvczCinl:L:PVoh")) != EOF)
> {
> +        while ((c = getopt(argcnt, args, "gI:sSFfm:pvczCinl:L:PVoh")) !=
> EOF) {
>                  switch(c)
>               {
>               case 'V':
> @@ -4480,6 +4481,10 @@ cmd_kmem(void)
>                       pflag = 1;
>                       break;
>  
> +             case 'm':
> +                     meminfo.include = optarg;
> +                     break;
> +
>               case 'I':
>                       meminfo.ignore = optarg;
>                       break;
> @@ -4948,7 +4953,7 @@ PG_slab_flag_init(void)
>  static void
>  dump_mem_map_SPARSEMEM(struct meminfo *mi)
>  {
> -     ulong i;
> +     ulong i, j;
>       long total_pages;
>       int others, page_not_mapped, phys_not_mapped, page_mapping;
>       ulong pp, ppend;
> @@ -4967,7 +4972,11 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
>       char buf4[BUFSIZE];
>       char *page_cache;
>       char *pcache;
> -     ulong section, section_nr, nr_mem_sections, section_size;
> +     char *members = NULL;
> +     char *memberlist[MAXARGS];
> +     struct struct_member_data *member_data[MAXARGS];
> +     int nr_members, populated;
> +     ulong tmpvalue, section, section_nr, nr_mem_sections, section_size;
>       long buffersize;
>       char *outputbuffer;
>       int bufferindex;
> @@ -4980,66 +4989,81 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
>       char style3[100];
>       char style4[100];
>  
> -     sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
> -                     space(MINSPACE),
> -                     (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     space(MINSPACE),
> -                     VADDR_PRLEN,
> -                     space(MINSPACE),
> -                     space(MINSPACE));
> -     sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
> -                     VADDR_PRLEN,
> -                     space(MINSPACE),
> -                     (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     space(MINSPACE),
> -                     mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
> -                     space(MINSPACE),
> -                     mkstring(buf4, 8, CENTER|RJUST, " "),
> -                     " ");
> -     sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
> -                     VADDR_PRLEN,
> -                     space(MINSPACE),
> -                     (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     space(MINSPACE),
> -                     mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
> -                     space(MINSPACE),
> -                     mkstring(buf4, 8, CENTER|RJUST, "-----"));
> -     sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
> -                     VADDR_PRLEN,
> -                     space(MINSPACE),
> -                     (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     space(MINSPACE),
> -                     VADDR_PRLEN,
> -                     space(MINSPACE));
> +     nr_members = mapping = index = 0;
> +     reserved = shared = slabs = buffers = inode = offset = 0;
> +     pg_spec = phys_spec = print_hdr = FALSE;
>  
>       v22 = VALID_MEMBER(page_inode);  /* page.inode vs. page.mapping */
>  
> -        if (v22) {
> -             sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
> -                 mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
> -                 space(MINSPACE),
> -                    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     RJUST, "PHYSICAL"),
> -                 space(MINSPACE),
> -                 mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
> -                 space(MINSPACE),
> -                 mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
> -                 space(MINSPACE-1));
> -        } else {
> -             sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
> -                 mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
> -                 space(MINSPACE),
> -                    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                        RJUST, "PHYSICAL"),
> -                 space(MINSPACE),
> -                 mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
> -                 space(MINSPACE),
> -                 mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
> -        }
> +     if (!mi->include) {
> +             sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
> +                             space(MINSPACE),
> +                             (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             space(MINSPACE),
> +                             VADDR_PRLEN,
> +                             space(MINSPACE),
> +                             space(MINSPACE));
> +             sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
> +                             VADDR_PRLEN,
> +                             space(MINSPACE),
> +                             (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             space(MINSPACE),
> +                             mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
> +                             space(MINSPACE),
> +                             mkstring(buf4, 8, CENTER|RJUST, " "),
> +                             " ");
> +             sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
> +                             VADDR_PRLEN,
> +                             space(MINSPACE),
> +                             (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             space(MINSPACE),
> +                             mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, 
> "-------"),
> +                             space(MINSPACE),
> +                             mkstring(buf4, 8, CENTER|RJUST, "-----"));
> +             sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d 
> ",
> +                             VADDR_PRLEN,
> +                             space(MINSPACE),
> +                             (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             space(MINSPACE),
> +                             VADDR_PRLEN,
> +                             space(MINSPACE));
> +
> +             if (v22) {
> +                     sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
> +                         mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
> +                         space(MINSPACE),
> +                         mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             RJUST, "PHYSICAL"),
> +                         space(MINSPACE),
> +                         mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
> +                         space(MINSPACE),
> +                         mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
> +                         space(MINSPACE-1));
> +             } else {
> +                     sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
> +                         mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
> +                         space(MINSPACE),
> +                         mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             RJUST, "PHYSICAL"),
> +                         space(MINSPACE),
> +                         mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, 
> "MAPPING"),
> +                         space(MINSPACE),
> +                         mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
> +             }
> +     } else {
> +             if (count_chars(mi->include, ',') > MAXARGS)
> +                     error(FATAL, "too many members in comma-separated 
> list!\n");
>  
> -     mapping = index = 0;
> -     reserved = shared = slabs = buffers = inode = offset = 0;
> -     pg_spec = phys_spec = print_hdr = FALSE;
> +             if ((LASTCHAR(mi->include) == ',') || (LASTCHAR(mi->include) == 
> '.'))
> +                     error(FATAL, "invalid format: %s\n", mi->include);
> +
> +             members = GETBUF(strlen(mi->include)+1);
> +             strcpy(members, mi->include);
> +             replace_string(members, ",", ' ');
> +             nr_members = parse_line(members, memberlist);
> +             populated = FALSE;
> +
> +     }
>  
>       switch (mi->flags)
>       {
> @@ -5065,7 +5089,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
>                       error(FATAL, "dump_mem_map: no memtype specified\n");
>                       break;
>               }
> -             print_hdr = TRUE;
> +             if (!mi->include)
> +                     print_hdr = TRUE;
>               break;
>  
>       case GET_ALL:
> @@ -5092,7 +5117,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
>               break;
>  
>       default:
> -             print_hdr = TRUE;
> +             if (!mi->include)
> +                     print_hdr = TRUE;
>               break;
>       }
>  
> @@ -5188,187 +5214,251 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
>  
>                       if (!done && (pg_spec || phys_spec))
>                               continue;
> -
> -                     flags = ULONG(pcache + OFFSET(page_flags));
> -                     if (SIZE(page_flags) == 4)
> -                             flags &= 0xffffffff;
> -                     count = UINT(pcache + OFFSET(page_count));
>  
> -                     switch (mi->flags)
> -                     {
> -                     case GET_ALL:
> -                     case GET_BUFFERS_PAGES:
> -                             if (VALID_MEMBER(page_buffers)) {
> -                                     tmp = ULONG(pcache +
> -                                             OFFSET(page_buffers));
> -                                     if (tmp)
> -                                             buffers++;
> -                             } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) 
> {
> -                                     if ((flags >> v26_PG_private) & 1)
> -                                             buffers++;
> -                             } else
> -                                     error(FATAL,
> -                            "cannot determine whether pages have buffers\n");
> +                     if (mi->include) {
> +                             if (!populated) {
>  
> -                             if (mi->flags != GET_ALL)
> -                                     continue;
> +                                     j = 0;
> +                                     do {
> +                                             if (!(member_data[j] = 
> malloc(sizeof(struct struct_member_data)))) {
> +                                                     error(WARNING, "cannot 
> malloc member_data space.\n");
> +                                                     nr_members = j += 1;
> +                                                     goto failed_member_data;
> +                                             }
>  
> -                             /* FALLTHROUGH */
> +                                             member_data[j]->structure = 
> "page";
> +                                             member_data[j]->member = 
> memberlist[j];
> +                                             if 
> (!(fill_struct_member_data(member_data[j]))) {
> +                                                     error(WARNING, "Failed 
> to populate member_data: "
> +                                                             "%s.%s does not 
> exist.\n",
> +                                                             
> member_data[j]->structure, member_data[j]->member);
> +                                                     nr_members = j += 1;
> +                                                     goto failed_member_data;
> +                                             }
>  
> -                     case GET_SLAB_PAGES:
> -                             if (v22) {
> -                                     if ((flags >> v22_PG_Slab) & 1)
> -                                             slabs++;
> -                             } else if (vt->PG_slab) {
> -                                     if ((flags >> vt->PG_slab) & 1)
> -                                             slabs++;
> -                             } else {
> -                                     if ((flags >> v24_PG_slab) & 1)
> -                                             slabs++;
> +                                     } while (++j < nr_members);
> +                                     populated = TRUE;
>                               }
> -                             if (mi->flags != GET_ALL)
> -                                     continue;
>  
> -                             /* FALLTHROUGH */
>  
> -                     case GET_SHARED_PAGES:
> -                     case GET_TOTALRAM_PAGES:
> -                                if (vt->PG_reserved)
> -                                     PG_reserved_flag = vt->PG_reserved;
> -                             else
> -                                        PG_reserved_flag = v22 ?
> -                                                1 << v22_PG_reserved :
> -                                                1 << v24_PG_reserved;
> +                             bufferindex += sprintf(outputbuffer + 
> bufferindex,
> +                                     "%lx\t", pp);
>  
> -                             if (flags & PG_reserved_flag) {
> -                                     reserved++;
> -                             } else {
> -                                     if ((int)count >
> -                                         (vt->flags & PGCNT_ADJ ? 0 : 1))
> -                                             shared++;
> -                             }
> -                             continue;
> -                     }
> -                     page_mapping = VALID_MEMBER(page_mapping);
> -
> -                     if (v22) {
> -                             inode = ULONG(pcache + OFFSET(page_inode));
> -                             offset = ULONG(pcache + OFFSET(page_offset));
> -                     } else if (page_mapping) {
> -                             mapping = ULONG(pcache +
> -                                     OFFSET(page_mapping));
> -                             index = ULONG(pcache + OFFSET(page_index));
> -                     }
> -
> -                     page_not_mapped = phys_not_mapped = FALSE;
> +                             j = 0;
> +                             do {
> +                                     switch (member_data[j]->type)
> +                                     {
> +                                     case TYPE_CODE_PTR:
> +                                             readmem(pp + 
> member_data[j]->offset, KVADDR, &tmpvalue,
> +                                                     member_data[j]->length, 
> "tmpvalue", FAULT_ON_ERROR);
> +                                             bufferindex += 
> sprintf(outputbuffer + bufferindex, "0x%lx\t",
> +                                                     tmpvalue);
> +                                             break;
> +                                     case TYPE_CODE_INT:
> +                                             readmem(pp + 
> member_data[j]->offset, KVADDR, &tmpvalue,
> +                                                     member_data[j]->length, 
> "tmpvalue", FAULT_ON_ERROR);
> +                                             if 
> (member_data[j]->unsigned_type ||
> +                                                     member_data[j]->length 
> == sizeof(ulonglong))
> +                                                     bufferindex += 
> sprintf(outputbuffer + bufferindex,
> +                                                             "%lu\t", 
> tmpvalue);
> +                                             else
> +                                                     bufferindex += 
> sprintf(outputbuffer + bufferindex,
> +                                                             "%d\t", 
> (int)tmpvalue);
> +                                             break;
> +                                     default:
> +                                             error(WARNING, "invalid data 
> structure reference %s.%s\n",
> +                                                     
> member_data[j]->structure, member_data[j]->member);
> +                                             nr_members = j += 1;
> +                                             goto failed_member_data;
> +                                             break;
> +                                     }
> +                             } while (++j < nr_members);
> +
> +                             bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
>  
> -                     if (v22) {
> -                             bufferindex += sprintf(outputbuffer+bufferindex,
> -                                             (char *)&style1, pp, phys, 
> inode,
> -                                             offset, count);
>                       } else {
> -                             if ((vt->flags & V_MEM_MAP)) {
> -                                     if (!machdep->verify_paddr(phys))
> -                                             phys_not_mapped = TRUE;
> -                                     if (!kvtop(NULL, pp, NULL, 0))
> -                                             page_not_mapped = TRUE;
> +
> +                             flags = ULONG(pcache + OFFSET(page_flags));
> +                             if (SIZE(page_flags) == 4)
> +                                     flags &= 0xffffffff;
> +                             count = UINT(pcache + OFFSET(page_count));
> +
> +                             switch (mi->flags)
> +                             {
> +                             case GET_ALL:
> +                             case GET_BUFFERS_PAGES:
> +                                     if (VALID_MEMBER(page_buffers)) {
> +                                             tmp = ULONG(pcache +
> +                                                     OFFSET(page_buffers));
> +                                             if (tmp)
> +                                                     buffers++;
> +                                     } else if (THIS_KERNEL_VERSION >= 
> LINUX(2,6,0)) {
> +                                             if ((flags >> v26_PG_private) & 
> 1)
> +                                                     buffers++;
> +                                     } else
> +                                             error(FATAL,
> +                                    "cannot determine whether pages have 
> buffers\n");
> +
> +                                     if (mi->flags != GET_ALL)
> +                                             continue;
> +
> +                                     /* FALLTHROUGH */
> +
> +                             case GET_SLAB_PAGES:
> +                                     if (v22) {
> +                                             if ((flags >> v22_PG_Slab) & 1)
> +                                                     slabs++;
> +                                     } else if (vt->PG_slab) {
> +                                             if ((flags >> vt->PG_slab) & 1)
> +                                                     slabs++;
> +                                     } else {
> +                                             if ((flags >> v24_PG_slab) & 1)
> +                                                     slabs++;
> +                                     }
> +                                     if (mi->flags != GET_ALL)
> +                                             continue;
> +
> +                                     /* FALLTHROUGH */
> +
> +                             case GET_SHARED_PAGES:
> +                             case GET_TOTALRAM_PAGES:
> +                                     if (vt->PG_reserved)
> +                                             PG_reserved_flag = 
> vt->PG_reserved;
> +                                     else
> +                                             PG_reserved_flag = v22 ?
> +                                                     1 << v22_PG_reserved :
> +                                                     1 << v24_PG_reserved;
> +
> +                                     if (flags & PG_reserved_flag) {
> +                                             reserved++;
> +                                     } else {
> +                                             if ((int)count >
> +                                                 (vt->flags & PGCNT_ADJ ? 0 
> : 1))
> +                                                     shared++;
> +                                     }
> +                                     continue;
>                               }
> -                             if (page_not_mapped)
> -                                     bufferindex += 
> sprintf(outputbuffer+bufferindex,
> -                                                     (char *)&style2, pp, 
> phys);
> -                             else if (!page_mapping)
> -                                     bufferindex += 
> sprintf(outputbuffer+bufferindex,
> -                                                     (char *)&style3, pp, 
> phys, count);
> -                             else
> +                             page_mapping = VALID_MEMBER(page_mapping);
> +
> +                             if (v22) {
> +                                     inode = ULONG(pcache + 
> OFFSET(page_inode));
> +                                     offset = ULONG(pcache + 
> OFFSET(page_offset));
> +                             } else if (page_mapping) {
> +                                     mapping = ULONG(pcache +
> +                                             OFFSET(page_mapping));
> +                                     index = ULONG(pcache + 
> OFFSET(page_index));
> +                             }
> +
> +                             page_not_mapped = phys_not_mapped = FALSE;
> +
> +                             if (v22) {
>                                       bufferindex += 
> sprintf(outputbuffer+bufferindex,
> -                                                     (char *)&style4, pp, 
> phys,
> -                                                     mapping, index, count);
> -                     }
> -
> -                     others = 0;
> -
> +                                                     (char *)&style1, pp, 
> phys, inode,
> +                                                     offset, count);
> +                             } else {
> +                                     if ((vt->flags & V_MEM_MAP)) {
> +                                             if 
> (!machdep->verify_paddr(phys))
> +                                                     phys_not_mapped = TRUE;
> +                                             if (!kvtop(NULL, pp, NULL, 0))
> +                                                     page_not_mapped = TRUE;
> +                                     }
> +                                     if (page_not_mapped)
> +                                             bufferindex += 
> sprintf(outputbuffer+bufferindex,
> +                                                             (char 
> *)&style2, pp, phys);
> +                                     else if (!page_mapping)
> +                                             bufferindex += 
> sprintf(outputbuffer+bufferindex,
> +                                                             (char 
> *)&style3, pp, phys, count);
> +                                     else
> +                                             bufferindex += 
> sprintf(outputbuffer+bufferindex,
> +                                                             (char 
> *)&style4, pp, phys,
> +                                                             mapping, index, 
> count);
> +                             }
> +
> +                             others = 0;
> +
>  #define sprintflag(X) sprintf(outputbuffer + bufferindex, X, others++ ? ","
>  : "")
>  
> -                     if (v22) {
> -                             if ((flags >> v22_PG_DMA) & 1)
> -                                     bufferindex += sprintflag("%sDMA");
> -                             if ((flags >> v22_PG_locked) & 1)
> -                                     bufferindex += sprintflag("%slocked");
> -                             if ((flags >> v22_PG_error) & 1)
> -                                     bufferindex += sprintflag("%serror");
> -                             if ((flags >> v22_PG_referenced) & 1)
> -                                     bufferindex += 
> sprintflag("%sreferenced");
> -                             if ((flags >> v22_PG_dirty) & 1)
> -                                     bufferindex += sprintflag("%sdirty");
> -                             if ((flags >> v22_PG_uptodate) & 1)
> -                                     bufferindex += sprintflag("%suptodate");
> -                             if ((flags >> v22_PG_free_after) & 1)
> -                                     bufferindex += 
> sprintflag("%sfree_after");
> -                             if ((flags >> v22_PG_decr_after) & 1)
> -                                     bufferindex += 
> sprintflag("%sdecr_after");
> -                             if ((flags >> v22_PG_swap_unlock_after) & 1)
> -                                     bufferindex += 
> sprintflag("%sswap_unlock_after");
> -                             if ((flags >> v22_PG_Slab) & 1)
> -                                     bufferindex += sprintflag("%sslab");
> -                             if ((flags >> v22_PG_swap_cache) & 1)
> -                                     bufferindex += 
> sprintflag("%sswap_cache");
> -                             if ((flags >> v22_PG_skip) & 1)
> -                                     bufferindex += sprintflag("%sskip");
> -                             if ((flags >> v22_PG_reserved) & 1)
> -                                     bufferindex += sprintflag("%sreserved");
> -                             bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
> -                     } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
> -                             if (vt->flags & PAGEFLAGS)
> -                                     bufferindex += 
> translate_page_flags(outputbuffer+bufferindex, flags);
> -                             else
> -                                     bufferindex += 
> sprintf(outputbuffer+bufferindex, "%lx\n", flags);
> -                     } else {
> -
> -                             if ((flags >> v24_PG_locked) & 1)
> -                                     bufferindex += sprintflag("%slocked");
> -                             if ((flags >> v24_PG_error) & 1)
> -                                     bufferindex += sprintflag("%serror");
> -                             if ((flags >> v24_PG_referenced) & 1)
> -                                     bufferindex += 
> sprintflag("%sreferenced");
> -                             if ((flags >> v24_PG_uptodate) & 1)
> -                                     bufferindex += sprintflag("%suptodate");
> -                                if ((flags >> v24_PG_dirty) & 1)
> -                                     bufferindex += sprintflag("%sdirty");
> -                             if ((flags >> v24_PG_decr_after) & 1)
> -                                     bufferindex += 
> sprintflag("%sdecr_after");
> -                                if ((flags >> v24_PG_active) & 1)
> -                                     bufferindex += sprintflag("%sactive");
> -                                if ((flags >> v24_PG_inactive_dirty) & 1)
> -                                     bufferindex += 
> sprintflag("%sinactive_dirty");
> -                             if ((flags >> v24_PG_slab) & 1)
> -                                     bufferindex += sprintflag("%sslab");
> -                             if ((flags >> v24_PG_swap_cache) & 1)
> -                                     bufferindex += 
> sprintflag("%sswap_cache");
> -                             if ((flags >> v24_PG_skip) & 1)
> -                                     bufferindex += sprintflag("%sskip");
> -                             if ((flags >> v24_PG_inactive_clean) & 1)
> -                                     bufferindex += 
> sprintflag("%sinactive_clean");
> -                             if ((flags >> v24_PG_highmem) & 1)
> -                                     bufferindex += sprintflag("%shighmem");
> -                             if ((flags >> v24_PG_checked) & 1)
> -                                     bufferindex += sprintflag("%schecked");
> -                             if ((flags >> v24_PG_bigpage) & 1)
> -                                     bufferindex += sprintflag("%sbigpage");
> -                                if ((flags >> v24_PG_arch_1) & 1)
> -                                     bufferindex += sprintflag("%sarch_1");
> -                             if ((flags >> v24_PG_reserved) & 1)
> -                                     bufferindex += sprintflag("%sreserved");
> -                             if (phys_not_mapped)
> -                                     bufferindex += sprintflag("%s[NOT 
> MAPPED]");
> -
> -                             bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
> +                             if (v22) {
> +                                     if ((flags >> v22_PG_DMA) & 1)
> +                                             bufferindex += 
> sprintflag("%sDMA");
> +                                     if ((flags >> v22_PG_locked) & 1)
> +                                             bufferindex += 
> sprintflag("%slocked");
> +                                     if ((flags >> v22_PG_error) & 1)
> +                                             bufferindex += 
> sprintflag("%serror");
> +                                     if ((flags >> v22_PG_referenced) & 1)
> +                                             bufferindex += 
> sprintflag("%sreferenced");
> +                                     if ((flags >> v22_PG_dirty) & 1)
> +                                             bufferindex += 
> sprintflag("%sdirty");
> +                                     if ((flags >> v22_PG_uptodate) & 1)
> +                                             bufferindex += 
> sprintflag("%suptodate");
> +                                     if ((flags >> v22_PG_free_after) & 1)
> +                                             bufferindex += 
> sprintflag("%sfree_after");
> +                                     if ((flags >> v22_PG_decr_after) & 1)
> +                                             bufferindex += 
> sprintflag("%sdecr_after");
> +                                     if ((flags >> v22_PG_swap_unlock_after) 
> & 1)
> +                                             bufferindex += 
> sprintflag("%sswap_unlock_after");
> +                                     if ((flags >> v22_PG_Slab) & 1)
> +                                             bufferindex += 
> sprintflag("%sslab");
> +                                     if ((flags >> v22_PG_swap_cache) & 1)
> +                                             bufferindex += 
> sprintflag("%sswap_cache");
> +                                     if ((flags >> v22_PG_skip) & 1)
> +                                             bufferindex += 
> sprintflag("%sskip");
> +                                     if ((flags >> v22_PG_reserved) & 1)
> +                                             bufferindex += 
> sprintflag("%sreserved");
> +                                     bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
> +                             } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
> +                                     if (vt->flags & PAGEFLAGS)
> +                                             bufferindex += 
> translate_page_flags(outputbuffer+bufferindex, flags);
> +                                     else
> +                                             bufferindex += 
> sprintf(outputbuffer+bufferindex, "%lx\n", flags);
> +                             } else {
> +
> +                                     if ((flags >> v24_PG_locked) & 1)
> +                                             bufferindex += 
> sprintflag("%slocked");
> +                                     if ((flags >> v24_PG_error) & 1)
> +                                             bufferindex += 
> sprintflag("%serror");
> +                                     if ((flags >> v24_PG_referenced) & 1)
> +                                             bufferindex += 
> sprintflag("%sreferenced");
> +                                     if ((flags >> v24_PG_uptodate) & 1)
> +                                             bufferindex += 
> sprintflag("%suptodate");
> +                                     if ((flags >> v24_PG_dirty) & 1)
> +                                             bufferindex += 
> sprintflag("%sdirty");
> +                                     if ((flags >> v24_PG_decr_after) & 1)
> +                                             bufferindex += 
> sprintflag("%sdecr_after");
> +                                     if ((flags >> v24_PG_active) & 1)
> +                                             bufferindex += 
> sprintflag("%sactive");
> +                                     if ((flags >> v24_PG_inactive_dirty) & 
> 1)
> +                                             bufferindex += 
> sprintflag("%sinactive_dirty");
> +                                     if ((flags >> v24_PG_slab) & 1)
> +                                             bufferindex += 
> sprintflag("%sslab");
> +                                     if ((flags >> v24_PG_swap_cache) & 1)
> +                                             bufferindex += 
> sprintflag("%sswap_cache");
> +                                     if ((flags >> v24_PG_skip) & 1)
> +                                             bufferindex += 
> sprintflag("%sskip");
> +                                     if ((flags >> v24_PG_inactive_clean) & 
> 1)
> +                                             bufferindex += 
> sprintflag("%sinactive_clean");
> +                                     if ((flags >> v24_PG_highmem) & 1)
> +                                             bufferindex += 
> sprintflag("%shighmem");
> +                                     if ((flags >> v24_PG_checked) & 1)
> +                                             bufferindex += 
> sprintflag("%schecked");
> +                                     if ((flags >> v24_PG_bigpage) & 1)
> +                                             bufferindex += 
> sprintflag("%sbigpage");
> +                                     if ((flags >> v24_PG_arch_1) & 1)
> +                                             bufferindex += 
> sprintflag("%sarch_1");
> +                                     if ((flags >> v24_PG_reserved) & 1)
> +                                             bufferindex += 
> sprintflag("%sreserved");
> +                                     if (phys_not_mapped)
> +                                             bufferindex += 
> sprintflag("%s[NOT MAPPED]");
> +
> +                                     bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
> +                             }
>                       }
>  
>                       if (bufferindex > buffersize) {
>                               fprintf(fp, "%s", outputbuffer);
>                               bufferindex = 0;
>                       }
> -
> +
>                       if (done)
>                               break;
>               }
> @@ -5413,12 +5503,18 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
>  
>       FREEBUF(outputbuffer);
>       FREEBUF(page_cache);
> +failed_member_data:
> +     if (mi->include) {
> +             FREEBUF(members);
> +             for (i = 0; i < nr_members; i++)
> +                     free(member_data[i]);
> +     }
>  }
>  
>  static void
>  dump_mem_map(struct meminfo *mi)
>  {
> -     long i, n;
> +     ulong i, n, j;
>       long total_pages;
>       int others, page_not_mapped, phys_not_mapped, page_mapping;
>       ulong pp, ppend;
> @@ -5439,6 +5535,11 @@ dump_mem_map(struct meminfo *mi)
>       char buf4[BUFSIZE];
>       char *page_cache;
>       char *pcache;
> +     char *members = NULL;
> +     char *memberlist[MAXARGS];
> +     struct struct_member_data *member_data[MAXARGS];
> +     int nr_members, populated;
> +     ulong tmpvalue;
>       long buffersize;
>       char *outputbuffer;
>       int bufferindex;
> @@ -5456,67 +5557,82 @@ dump_mem_map(struct meminfo *mi)
>               return;
>       }
>  
> -     sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
> -                     space(MINSPACE),
> -                     (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     space(MINSPACE),
> -                     VADDR_PRLEN,
> -                     space(MINSPACE),
> -                     space(MINSPACE));
> -     sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
> -                     VADDR_PRLEN,
> -                     space(MINSPACE),
> -                     (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     space(MINSPACE),
> -                     mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
> -                     space(MINSPACE),
> -                     mkstring(buf4, 8, CENTER|RJUST, " "),
> -                     " ");
> -     sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
> -                     VADDR_PRLEN,
> -                     space(MINSPACE),
> -                     (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     space(MINSPACE),
> -                     mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
> -                     space(MINSPACE),
> -                     mkstring(buf4, 8, CENTER|RJUST, "-----"));
> -     sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
> -                     VADDR_PRLEN,
> -                     space(MINSPACE),
> -                     (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     space(MINSPACE),
> -                     VADDR_PRLEN,
> -                     space(MINSPACE));
> +     nr_members = mapping = index = 0;
> +     reserved = shared = slabs = buffers = inode = offset = 0;
> +     pg_spec = phys_spec = print_hdr = FALSE;
>  
>       v22 = VALID_MEMBER(page_inode);  /* page.inode vs. page.mapping */
>  
> -        if (v22) {
> -             sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
> -                 mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
> -                 space(MINSPACE),
> -                    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                     RJUST, "PHYSICAL"),
> -                 space(MINSPACE),
> -                 mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
> -                 space(MINSPACE),
> -                 mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
> -                 space(MINSPACE-1));
> -        } else {
> -             sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
> -                 mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
> -                 space(MINSPACE),
> -                    mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> -                        RJUST, "PHYSICAL"),
> -                 space(MINSPACE),
> -                 mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
> -                 space(MINSPACE),
> -                 mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
> -        }
> +     if (!mi->include) {
> +             sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
> +                             space(MINSPACE),
> +                             (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             space(MINSPACE),
> +                             VADDR_PRLEN,
> +                             space(MINSPACE),
> +                             space(MINSPACE));
> +             sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
> +                             VADDR_PRLEN,
> +                             space(MINSPACE),
> +                             (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             space(MINSPACE),
> +                             mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
> +                             space(MINSPACE),
> +                             mkstring(buf4, 8, CENTER|RJUST, " "),
> +                             " ");
> +             sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
> +                             VADDR_PRLEN,
> +                             space(MINSPACE),
> +                             (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             space(MINSPACE),
> +                             mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, 
> "-------"),
> +                             space(MINSPACE),
> +                             mkstring(buf4, 8, CENTER|RJUST, "-----"));
> +             sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d 
> ",
> +                             VADDR_PRLEN,
> +                             space(MINSPACE),
> +                             (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             space(MINSPACE),
> +                             VADDR_PRLEN,
> +                             space(MINSPACE));
> +
> +             if (v22) {
> +                     sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
> +                         mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
> +                         space(MINSPACE),
> +                         mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             RJUST, "PHYSICAL"),
> +                         space(MINSPACE),
> +                         mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
> +                         space(MINSPACE),
> +                         mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
> +                         space(MINSPACE-1));
> +             } else {
> +                     sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
> +                         mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
> +                         space(MINSPACE),
> +                         mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
> +                             RJUST, "PHYSICAL"),
> +                         space(MINSPACE),
> +                         mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, 
> "MAPPING"),
> +                         space(MINSPACE),
> +                         mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
> +             }
> +     } else {
> +             if (count_chars(mi->include, ',') > MAXARGS)
> +                     error(FATAL, "too many members in comma-separated 
> list!\n");
> +
> +             if ((LASTCHAR(mi->include) == ',') || (LASTCHAR(mi->include) == 
> '.'))
> +                     error(FATAL, "invalid format: %s\n", mi->include);
> +
> +             members = GETBUF(strlen(mi->include)+1);
> +             strcpy(members, mi->include);
> +             replace_string(members, ",", ' ');
> +             nr_members = parse_line(members, memberlist);
> +             populated = FALSE;
> +
> +     }
>  
> -     mapping = index = 0;
> -     reserved = shared = slabs = buffers = inode = offset = 0;
> -     pg_spec = phys_spec = print_hdr = FALSE;
> -
>       switch (mi->flags)
>       {
>       case ADDRESS_SPECIFIED:
> @@ -5541,7 +5657,8 @@ dump_mem_map(struct meminfo *mi)
>                       error(FATAL, "dump_mem_map: no memtype specified\n");
>                       break;
>               }
> -             print_hdr = TRUE;
> +             if (!mi->include)
> +                     print_hdr = TRUE;
>               break;
>  
>       case GET_ALL:
> @@ -5568,7 +5685,8 @@ dump_mem_map(struct meminfo *mi)
>               break;
>  
>       default:
> -             print_hdr = TRUE;
> +             if (!mi->include)
> +                     print_hdr = TRUE;
>               break;
>       }
>  
> @@ -5625,181 +5743,245 @@ dump_mem_map(struct meminfo *mi)
>  
>                       if (!done && (pg_spec || phys_spec))
>                               continue;
> -
> -                     flags = ULONG(pcache + OFFSET(page_flags));
> -                     if (SIZE(page_flags) == 4)
> -                             flags &= 0xffffffff;
> -                     count = UINT(pcache + OFFSET(page_count));
>  
> -                     switch (mi->flags)
> -                     {
> -                     case GET_ALL:
> -                     case GET_BUFFERS_PAGES:
> -                             if (VALID_MEMBER(page_buffers)) {
> -                                     tmp = ULONG(pcache +
> -                                             OFFSET(page_buffers));
> -                                     if (tmp)
> -                                             buffers++;
> -                             } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) 
> {
> -                                     if ((flags >> v26_PG_private) & 1)
> -                                             buffers++;
> -                             } else
> -                                     error(FATAL,
> -                            "cannot determine whether pages have buffers\n");
> +                     if (mi->include) {
> +                             if (!populated) {
>  
> -                             if (mi->flags != GET_ALL)
> -                                     continue;
> +                                     j = 0;
> +                                     do {
> +                                             if (!(member_data[j] = 
> malloc(sizeof(struct struct_member_data)))) {
> +                                                     error(WARNING, "cannot 
> malloc member_data space.\n");
> +                                                     nr_members = j += 1;
> +                                                     goto failed_member_data;
> +                                             }
>  
> -                             /* FALLTHROUGH */
> +                                             member_data[j]->structure = 
> "page";
> +                                             member_data[j]->member = 
> memberlist[j];
> +                                             if 
> (!(fill_struct_member_data(member_data[j]))) {
> +                                                     error(WARNING, "Failed 
> to populate member_data: "
> +                                                             "%s.%s does not 
> exist.\n",
> +                                                             
> member_data[j]->structure, member_data[j]->member);
> +                                                     nr_members = j += 1;
> +                                                     goto failed_member_data;
> +                                             }
>  
> -                     case GET_SLAB_PAGES:
> -                             if (v22) {
> -                                     if ((flags >> v22_PG_Slab) & 1)
> -                                             slabs++;
> -                             } else if (vt->PG_slab) {
> -                                     if ((flags >> vt->PG_slab) & 1)
> -                                             slabs++;
> -                             } else {
> -                                     if ((flags >> v24_PG_slab) & 1)
> -                                             slabs++;
> +                                     } while (++j < nr_members);
> +                                     populated = TRUE;
>                               }
> -                             if (mi->flags != GET_ALL)
> -                                     continue;
>  
> -                             /* FALLTHROUGH */
>  
> -                     case GET_SHARED_PAGES:
> -                     case GET_TOTALRAM_PAGES:
> -                                if (vt->PG_reserved)
> -                                     PG_reserved_flag = vt->PG_reserved;
> -                             else
> -                                        PG_reserved_flag = v22 ?
> -                                                1 << v22_PG_reserved :
> -                                                1 << v24_PG_reserved;
> +                             bufferindex += sprintf(outputbuffer + 
> bufferindex,
> +                                     "%lx\t", pp);
>  
> -                             if (flags & PG_reserved_flag) {
> -                                     reserved++;
> -                             } else {
> -                                     if ((int)count >
> -                                         (vt->flags & PGCNT_ADJ ? 0 : 1))
> -                                             shared++;
> -                             }
> -                             continue;
> -                     }
> -
> -                     page_mapping = VALID_MEMBER(page_mapping);
> -
> -                     if (v22) {
> -                             inode = ULONG(pcache + OFFSET(page_inode));
> -                             offset = ULONG(pcache + OFFSET(page_offset));
> -                     } else if (page_mapping) {
> -                             mapping = ULONG(pcache +
> -                                     OFFSET(page_mapping));
> -                             index = ULONG(pcache + OFFSET(page_index));
> -                     }
> -
> -                     page_not_mapped = phys_not_mapped = FALSE;
> +                             j = 0;
> +                             do {
> +                                     switch (member_data[j]->type)
> +                                     {
> +                                     case TYPE_CODE_PTR:
> +                                             readmem(pp + 
> member_data[j]->offset, KVADDR, &tmpvalue,
> +                                                     member_data[j]->length, 
> "tmpvalue", FAULT_ON_ERROR);
> +                                             bufferindex += 
> sprintf(outputbuffer + bufferindex, "0x%lx\t",
> +                                                     tmpvalue);
> +                                             break;
> +                                     case TYPE_CODE_INT:
> +                                             readmem(pp + 
> member_data[j]->offset, KVADDR, &tmpvalue,
> +                                                     member_data[j]->length, 
> "tmpvalue", FAULT_ON_ERROR);
> +                                             if 
> (member_data[j]->unsigned_type ||
> +                                                     member_data[j]->length 
> == sizeof(ulonglong))
> +                                                     bufferindex += 
> sprintf(outputbuffer + bufferindex,
> +                                                             "%lu\t", 
> tmpvalue);
> +                                             else
> +                                                     bufferindex += 
> sprintf(outputbuffer + bufferindex,
> +                                                             "%d\t", 
> (int)tmpvalue);
> +                                             break;
> +                                     default:
> +                                             error(WARNING, "invalid data 
> structure reference %s.%s\n",
> +                                                     
> member_data[j]->structure, member_data[j]->member);
> +                                             nr_members = j += 1;
> +                                             goto failed_member_data;
> +                                             break;
> +                                     }
> +                             } while (++j < nr_members);
> +
> +                             bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
>  
> -                     if (v22) {
> -                             bufferindex += sprintf(outputbuffer+bufferindex,
> -                                             (char *)&style1, pp, phys, 
> inode,
> -                                             offset, count);
>                       } else {
> -                             if ((vt->flags & V_MEM_MAP)) {
> -                                     if (!machdep->verify_paddr(phys))
> -                                             phys_not_mapped = TRUE;
> -                                     if (!kvtop(NULL, pp, NULL, 0))
> -                                             page_not_mapped = TRUE;
> +
> +                             flags = ULONG(pcache + OFFSET(page_flags));
> +                             if (SIZE(page_flags) == 4)
> +                                     flags &= 0xffffffff;
> +                             count = UINT(pcache + OFFSET(page_count));
> +
> +                             switch (mi->flags)
> +                             {
> +                             case GET_ALL:
> +                             case GET_BUFFERS_PAGES:
> +                                     if (VALID_MEMBER(page_buffers)) {
> +                                             tmp = ULONG(pcache +
> +                                                     OFFSET(page_buffers));
> +                                             if (tmp)
> +                                                     buffers++;
> +                                     } else if (THIS_KERNEL_VERSION >= 
> LINUX(2,6,0)) {
> +                                             if ((flags >> v26_PG_private) & 
> 1)
> +                                                     buffers++;
> +                                     } else
> +                                             error(FATAL,
> +                                    "cannot determine whether pages have 
> buffers\n");
> +
> +                                     if (mi->flags != GET_ALL)
> +                                             continue;
> +
> +                                     /* FALLTHROUGH */
> +
> +                             case GET_SLAB_PAGES:
> +                                     if (v22) {
> +                                             if ((flags >> v22_PG_Slab) & 1)
> +                                                     slabs++;
> +                                     } else if (vt->PG_slab) {
> +                                             if ((flags >> vt->PG_slab) & 1)
> +                                                     slabs++;
> +                                     } else {
> +                                             if ((flags >> v24_PG_slab) & 1)
> +                                                     slabs++;
> +                                     }
> +                                     if (mi->flags != GET_ALL)
> +                                             continue;
> +
> +                                     /* FALLTHROUGH */
> +
> +                             case GET_SHARED_PAGES:
> +                             case GET_TOTALRAM_PAGES:
> +                                     if (vt->PG_reserved)
> +                                             PG_reserved_flag = 
> vt->PG_reserved;
> +                                     else
> +                                             PG_reserved_flag = v22 ?
> +                                                     1 << v22_PG_reserved :
> +                                                     1 << v24_PG_reserved;
> +
> +                                     if (flags & PG_reserved_flag) {
> +                                             reserved++;
> +                                     } else {
> +                                             if ((int)count >
> +                                                 (vt->flags & PGCNT_ADJ ? 0 
> : 1))
> +                                                     shared++;
> +                                     }
> +                                     continue;
>                               }
> -                             if (page_not_mapped)
> -                                     bufferindex += 
> sprintf(outputbuffer+bufferindex,
> -                                                     (char *)&style2, pp, 
> phys);
> -                             else if (!page_mapping)
> -                                     bufferindex += 
> sprintf(outputbuffer+bufferindex,
> -                                                     (char *)&style3, pp, 
> phys, count);
> -                             else
> +
> +                             page_mapping = VALID_MEMBER(page_mapping);
> +
> +                             if (v22) {
> +                                     inode = ULONG(pcache + 
> OFFSET(page_inode));
> +                                     offset = ULONG(pcache + 
> OFFSET(page_offset));
> +                             } else if (page_mapping) {
> +                                     mapping = ULONG(pcache +
> +                                             OFFSET(page_mapping));
> +                                     index = ULONG(pcache + 
> OFFSET(page_index));
> +                             }
> +
> +                             page_not_mapped = phys_not_mapped = FALSE;
> +
> +                             if (v22) {
>                                       bufferindex += 
> sprintf(outputbuffer+bufferindex,
> -                                                     (char *)&style4, pp, 
> phys,
> -                                                     mapping, index, count);
> -                     }
> -
> -                     others = 0;
> -
> +                                                     (char *)&style1, pp, 
> phys, inode,
> +                                                     offset, count);
> +                             } else {
> +                                     if ((vt->flags & V_MEM_MAP)) {
> +                                             if 
> (!machdep->verify_paddr(phys))
> +                                                     phys_not_mapped = TRUE;
> +                                             if (!kvtop(NULL, pp, NULL, 0))
> +                                                     page_not_mapped = TRUE;
> +                                     }
> +                                     if (page_not_mapped)
> +                                             bufferindex += 
> sprintf(outputbuffer+bufferindex,
> +                                                             (char 
> *)&style2, pp, phys);
> +                                     else if (!page_mapping)
> +                                             bufferindex += 
> sprintf(outputbuffer+bufferindex,
> +                                                             (char 
> *)&style3, pp, phys, count);
> +                                     else
> +                                             bufferindex += 
> sprintf(outputbuffer+bufferindex,
> +                                                             (char 
> *)&style4, pp, phys,
> +                                                             mapping, index, 
> count);
> +                             }
> +
> +                             others = 0;
> +
>  #define sprintflag(X) sprintf(outputbuffer + bufferindex, X, others++ ? ","
>  : "")
>  
> -                     if (v22) {
> -                             if ((flags >> v22_PG_DMA) & 1)
> -                                     bufferindex += sprintflag("%sDMA");
> -                             if ((flags >> v22_PG_locked) & 1)
> -                                     bufferindex += sprintflag("%slocked");
> -                             if ((flags >> v22_PG_error) & 1)
> -                                     bufferindex += sprintflag("%serror");
> -                             if ((flags >> v22_PG_referenced) & 1)
> -                                     bufferindex += 
> sprintflag("%sreferenced");
> -                             if ((flags >> v22_PG_dirty) & 1)
> -                                     bufferindex += sprintflag("%sdirty");
> -                             if ((flags >> v22_PG_uptodate) & 1)
> -                                     bufferindex += sprintflag("%suptodate");
> -                             if ((flags >> v22_PG_free_after) & 1)
> -                                     bufferindex += 
> sprintflag("%sfree_after");
> -                             if ((flags >> v22_PG_decr_after) & 1)
> -                                     bufferindex += 
> sprintflag("%sdecr_after");
> -                             if ((flags >> v22_PG_swap_unlock_after) & 1)
> -                                     bufferindex += 
> sprintflag("%sswap_unlock_after");
> -                             if ((flags >> v22_PG_Slab) & 1)
> -                                     bufferindex += sprintflag("%sslab");
> -                             if ((flags >> v22_PG_swap_cache) & 1)
> -                                     bufferindex += 
> sprintflag("%sswap_cache");
> -                             if ((flags >> v22_PG_skip) & 1)
> -                                     bufferindex += sprintflag("%sskip");
> -                             if ((flags >> v22_PG_reserved) & 1)
> -                                     bufferindex += sprintflag("%sreserved");
> -                             bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
> -                     } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
> -                             if (vt->flags & PAGEFLAGS)
> -                                     bufferindex += 
> translate_page_flags(outputbuffer+bufferindex, flags);
> -                             else
> -                                     bufferindex += 
> sprintf(outputbuffer+bufferindex, "%lx\n", flags);
> -                     } else {
> -
> -                             if ((flags >> v24_PG_locked) & 1)
> -                                     bufferindex += sprintflag("%slocked");
> -                             if ((flags >> v24_PG_error) & 1)
> -                                     bufferindex += sprintflag("%serror");
> -                             if ((flags >> v24_PG_referenced) & 1)
> -                                     bufferindex += 
> sprintflag("%sreferenced");
> -                             if ((flags >> v24_PG_uptodate) & 1)
> -                                     bufferindex += sprintflag("%suptodate");
> -                                if ((flags >> v24_PG_dirty) & 1)
> -                                     bufferindex += sprintflag("%sdirty");
> -                             if ((flags >> v24_PG_decr_after) & 1)
> -                                     bufferindex += 
> sprintflag("%sdecr_after");
> -                                if ((flags >> v24_PG_active) & 1)
> -                                     bufferindex += sprintflag("%sactive");
> -                                if ((flags >> v24_PG_inactive_dirty) & 1)
> -                                     bufferindex += 
> sprintflag("%sinactive_dirty");
> -                             if ((flags >> v24_PG_slab) & 1)
> -                                     bufferindex += sprintflag("%sslab");
> -                             if ((flags >> v24_PG_swap_cache) & 1)
> -                                     bufferindex += 
> sprintflag("%sswap_cache");
> -                             if ((flags >> v24_PG_skip) & 1)
> -                                     bufferindex += sprintflag("%sskip");
> -                             if ((flags >> v24_PG_inactive_clean) & 1)
> -                                     bufferindex += 
> sprintflag("%sinactive_clean");
> -                             if ((flags >> v24_PG_highmem) & 1)
> -                                     bufferindex += sprintflag("%shighmem");
> -                             if ((flags >> v24_PG_checked) & 1)
> -                                     bufferindex += sprintflag("%schecked");
> -                             if ((flags >> v24_PG_bigpage) & 1)
> -                                     bufferindex += sprintflag("%sbigpage");
> -                                if ((flags >> v24_PG_arch_1) & 1)
> -                                     bufferindex += sprintflag("%sarch_1");
> -                             if ((flags >> v24_PG_reserved) & 1)
> -                                     bufferindex += sprintflag("%sreserved");
> -                             if (phys_not_mapped)
> -                                     bufferindex += sprintflag("%s[NOT 
> MAPPED]");
> -
> -                             bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
> +                             if (v22) {
> +                                     if ((flags >> v22_PG_DMA) & 1)
> +                                             bufferindex += 
> sprintflag("%sDMA");
> +                                     if ((flags >> v22_PG_locked) & 1)
> +                                             bufferindex += 
> sprintflag("%slocked");
> +                                     if ((flags >> v22_PG_error) & 1)
> +                                             bufferindex += 
> sprintflag("%serror");
> +                                     if ((flags >> v22_PG_referenced) & 1)
> +                                             bufferindex += 
> sprintflag("%sreferenced");
> +                                     if ((flags >> v22_PG_dirty) & 1)
> +                                             bufferindex += 
> sprintflag("%sdirty");
> +                                     if ((flags >> v22_PG_uptodate) & 1)
> +                                             bufferindex += 
> sprintflag("%suptodate");
> +                                     if ((flags >> v22_PG_free_after) & 1)
> +                                             bufferindex += 
> sprintflag("%sfree_after");
> +                                     if ((flags >> v22_PG_decr_after) & 1)
> +                                             bufferindex += 
> sprintflag("%sdecr_after");
> +                                     if ((flags >> v22_PG_swap_unlock_after) 
> & 1)
> +                                             bufferindex += 
> sprintflag("%sswap_unlock_after");
> +                                     if ((flags >> v22_PG_Slab) & 1)
> +                                             bufferindex += 
> sprintflag("%sslab");
> +                                     if ((flags >> v22_PG_swap_cache) & 1)
> +                                             bufferindex += 
> sprintflag("%sswap_cache");
> +                                     if ((flags >> v22_PG_skip) & 1)
> +                                             bufferindex += 
> sprintflag("%sskip");
> +                                     if ((flags >> v22_PG_reserved) & 1)
> +                                             bufferindex += 
> sprintflag("%sreserved");
> +                                     bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
> +                             } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
> +                                     if (vt->flags & PAGEFLAGS)
> +                                             bufferindex += 
> translate_page_flags(outputbuffer+bufferindex, flags);
> +                                     else
> +                                             bufferindex += 
> sprintf(outputbuffer+bufferindex, "%lx\n", flags);
> +                             } else {
> +
> +                                     if ((flags >> v24_PG_locked) & 1)
> +                                             bufferindex += 
> sprintflag("%slocked");
> +                                     if ((flags >> v24_PG_error) & 1)
> +                                             bufferindex += 
> sprintflag("%serror");
> +                                     if ((flags >> v24_PG_referenced) & 1)
> +                                             bufferindex += 
> sprintflag("%sreferenced");
> +                                     if ((flags >> v24_PG_uptodate) & 1)
> +                                             bufferindex += 
> sprintflag("%suptodate");
> +                                     if ((flags >> v24_PG_dirty) & 1)
> +                                             bufferindex += 
> sprintflag("%sdirty");
> +                                     if ((flags >> v24_PG_decr_after) & 1)
> +                                             bufferindex += 
> sprintflag("%sdecr_after");
> +                                     if ((flags >> v24_PG_active) & 1)
> +                                             bufferindex += 
> sprintflag("%sactive");
> +                                     if ((flags >> v24_PG_inactive_dirty) & 
> 1)
> +                                             bufferindex += 
> sprintflag("%sinactive_dirty");
> +                                     if ((flags >> v24_PG_slab) & 1)
> +                                             bufferindex += 
> sprintflag("%sslab");
> +                                     if ((flags >> v24_PG_swap_cache) & 1)
> +                                             bufferindex += 
> sprintflag("%sswap_cache");
> +                                     if ((flags >> v24_PG_skip) & 1)
> +                                             bufferindex += 
> sprintflag("%sskip");
> +                                     if ((flags >> v24_PG_inactive_clean) & 
> 1)
> +                                             bufferindex += 
> sprintflag("%sinactive_clean");
> +                                     if ((flags >> v24_PG_highmem) & 1)
> +                                             bufferindex += 
> sprintflag("%shighmem");
> +                                     if ((flags >> v24_PG_checked) & 1)
> +                                             bufferindex += 
> sprintflag("%schecked");
> +                                     if ((flags >> v24_PG_bigpage) & 1)
> +                                             bufferindex += 
> sprintflag("%sbigpage");
> +                                     if ((flags >> v24_PG_arch_1) & 1)
> +                                             bufferindex += 
> sprintflag("%sarch_1");
> +                                     if ((flags >> v24_PG_reserved) & 1)
> +                                             bufferindex += 
> sprintflag("%sreserved");
> +                                     if (phys_not_mapped)
> +                                             bufferindex += 
> sprintflag("%s[NOT MAPPED]");
> +
> +                                     bufferindex += 
> sprintf(outputbuffer+bufferindex, "\n");
> +                             }
>                       }
>       
>                       if (bufferindex > buffersize) {
> @@ -5851,6 +6033,12 @@ dump_mem_map(struct meminfo *mi)
>  
>       FREEBUF(outputbuffer);
>       FREEBUF(page_cache);
> +failed_member_data:
> +     if (mi->include) {
> +             FREEBUF(members);
> +             for (i = 0; i < nr_members; i++)
> +                     free(member_data[i]);
> +     }
>  }
>  
>  /*
> --
> 1.9.3
> 
> --
> Crash-utility mailing list
> [email protected]
> https://www.redhat.com/mailman/listinfo/crash-utility
> 

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

Reply via email to