---
 defs.h   |   4 ++
 memory.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 121 insertions(+), 40 deletions(-)

diff --git a/defs.h b/defs.h
index 8fc5121..ede0830 100644
--- a/defs.h
+++ b/defs.h
@@ -2214,7 +2214,11 @@ struct vm_table {                /* kernel VM-related 
data */
        ulong kmem_cache_len_nodes;
        ulong PG_reserved;
        ulong PG_slab;
+       ulong PG_head;
+       ulong PG_tail;
+       ulong PG_head_mask;
        ulong PG_head_tail_mask;
+       int is_pageflags_extended;      /* CONFIG_PAGEFLAGS_EXTENDED */
        int kmem_cache_namelen;
        ulong page_hash_table;
        int page_hash_table_len;
diff --git a/memory.c b/memory.c
index 051800f..2208553 100644
--- a/memory.c
+++ b/memory.c
@@ -268,6 +268,13 @@ static int generic_write_dumpfile(ulonglong, void *, long, 
char *, ulong);
 static int page_to_nid(ulong);
 static int get_kmem_cache_list(ulong **);
 static int get_kmem_cache_slub_data(long, struct meminfo *);
+static int __is_page_head(const char *);
+static int is_page_head(ulong);
+static int __is_page_tail(const char *);
+static int is_page_tail(ulong);
+static int __compound_order(const char *);
+static int compound_order(ulong);
+static ulong __compound_head(const char *);
 static ulong compound_head(ulong);
 static long count_partial(ulong, struct meminfo *);
 static ulong get_freepointer(struct meminfo *, void *);
@@ -4866,34 +4873,32 @@ PG_slab_flag_init(void)
                }
        }
 
-       if (vt->flags & KMALLOC_SLUB) {
-               /* 
-                *  PG_slab and the following are hardwired for 
-                *  kernels prior to the pageflags enumerator.
+       if (enumerator_value("PG_head", &flags) &&
+           enumerator_value("PG_tail", &flags2)) {
+               vt->PG_head = 1L << flags;
+               vt->PG_tail = 1L << flags2;
+               vt->is_pageflags_extended = 1;
+               if (CRASHDEBUG(2))
+                       fprintf(fp, "PG_head: %lx, PG_tail: %lx\n",
+                               vt->PG_head, vt->PG_tail);
+       } else if (enumerator_value("PG_compound", &flags) &&
+                  enumerator_value("PG_reclaim", &flags2)) {
+               vt->PG_head_mask = 1L << flags;
+               vt->PG_head_tail_mask = (1L << flags) | (1L << flags2);
+               if (CRASHDEBUG(2))
+                       fprintf(fp, "PG_head_mask: %lx, PG_head_tail_mask: 
%lx\n",
+                               vt->PG_head_mask, vt->PG_head_tail_mask);
+       } else if (vt->flags & KMALLOC_SLUB) {
+               /*
+                * PG_slab and the following are hardwired for
+                * kernels prior to the pageflags enumerator.
                 */
-#define PG_compound             14      /* Part of a compound page */
-#define PG_reclaim              17      /* To be reclaimed asap */
-               vt->PG_head_tail_mask = ((1L << PG_compound) | (1L << 
PG_reclaim));
-
-               if (enumerator_value("PG_tail", (long *)&flags))
-                       vt->PG_head_tail_mask = (1L << flags);
-               else if (enumerator_value("PG_compound", (long *)&flags) &&
-                        enumerator_value("PG_reclaim", (long *)&flags2)) {
-                       vt->PG_head_tail_mask = ((1L << flags) | (1L << 
flags2));
-                       if (CRASHDEBUG(2))
-                               fprintf(fp, "PG_head_tail_mask: %lx\n", 
-                                       vt->PG_head_tail_mask);
-               }
-       } else {
-               if (enumerator_value("PG_tail", (long *)&flags))
-                       vt->PG_head_tail_mask = (1L << flags);
-               else if (enumerator_value("PG_compound", (long *)&flags) &&
-                   enumerator_value("PG_reclaim", (long *)&flags2)) {
-                       vt->PG_head_tail_mask = ((1L << flags) | (1L << 
flags2));
-                       if (CRASHDEBUG(2))
-                               fprintf(fp, "PG_head_tail_mask: %lx 
(PG_compound|PG_reclaim)\n", 
-                                       vt->PG_head_tail_mask);
-               }
+#define PG_compound    14      /* Part of a compound page */
+#define PG_reclaim     17      /* To be reclaimed asap */
+               vt->PG_head_mask = 1L << PG_compound;
+               vt->PG_head_tail_mask = (1L << PG_compound) | (1L << 
PG_reclaim);
+               if (CRASHDEBUG(2))
+                       fprintf(fp, "hardwired PG_compound and PG_reclaim\n");
        }
 
        if (!vt->PG_slab)
@@ -13213,7 +13218,13 @@ dump_vm_table(int verbose)
         fprintf(fp, "        PG_reserved: %lx\n", vt->PG_reserved);
         fprintf(fp, "            PG_slab: %ld (%lx)\n", vt->PG_slab,
                 (ulong)1 << vt->PG_slab);
-        fprintf(fp, "  PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask);
+       if (vt->is_pageflags_extended) {
+               fprintf(fp, "  PG_head: %lx\n", vt->PG_head);
+               fprintf(fp, "  PG_tail: %lx\n", vt->PG_tail);
+       } else {
+               fprintf(fp, "  PG_head_mask: %lx\n", vt->PG_head_mask);
+               fprintf(fp, "  PG_head_tail_mask: %lx\n", 
vt->PG_head_tail_mask);
+       }
 
        fprintf(fp, "       nr_pageflags: %d\n", vt->nr_pageflags);
        fprintf(fp, "     pageflags_data: %s\n",
@@ -18179,6 +18190,80 @@ get_kmem_cache_list(ulong **cache_buf)
        return cnt;
 }
 
+static int
+__is_page_head(const char *p)
+{
+       ulong flags = ULONG(p + OFFSET(page_flags));
+
+       return vt->is_pageflags_extended ? flags & vt->PG_head :
+              flags & vt->PG_head_tail_mask == vt->PG_head_mask;
+}
+
+static int
+is_page_head(ulong page)
+{
+       ulong flags;
+
+       if (!readmem(page + OFFSET(page_flags), KVADDR, &flags, sizeof(flags),
+                    "page.flags", RETURN_ON_ERROR))
+               return 1;
+
+       return vt->is_pageflags_extended ? flags & vt->PG_head :
+              flags & vt->PG_head_tail_mask == vt->PG_head_mask;
+}
+
+static int
+__is_page_tail(const char *p)
+{
+       ulong flags = ULONG(p + OFFSET(page_flags));
+
+       return vt->is_pageflags_extended ? flags & vt->PG_tail :
+              flags & vt->PG_head_tail_mask == vt->PG_head_tail_mask;
+}
+
+static int
+is_page_tail(ulong page)
+{
+       ulong flags;
+
+       if (!readmem(page + OFFSET(page_flags), KVADDR, &flags, sizeof(flags),
+                    "page.flags", RETURN_ON_ERROR))
+               return 0;
+
+       return vt->is_pageflags_extended ? flags & vt->PG_tail :
+              flags & vt->PG_head_tail_mask == vt->PG_head_tail_mask;
+}
+
+static int
+__compound_order(const char *p)
+{
+       if (!__is_page_head(p))
+               return 0;
+
+       return ULONG(p + SIZE(page) + OFFSET(page_lru) + 
OFFSET(list_head_prev));
+}
+
+static int
+compound_order(ulong page)
+{
+
+       ulong order = 0;
+
+       if (is_page_head(page))
+               readmem(page + SIZE(page) + OFFSET(page_lru) + 
OFFSET(list_head_prev),
+                       KVADDR, &order, sizeof(order), "page.lru.prev", 
FAULT_ON_ERROR);
+
+       return order;
+}
+
+/*
+ * In contrast to compound_head(), this function only can be used on a tail 
page.
+ */
+static ulong
+__compound_head(const char *p)
+{
+       return ULONG(p + OFFSET(page_first_page));
+}
 
 /*
  *  Get the address of the head page of a compound page.
@@ -18186,19 +18271,11 @@ get_kmem_cache_list(ulong **cache_buf)
 static ulong
 compound_head(ulong page)
 {
-       ulong flags, first_page;;
+       if (is_page_tail(page))
+               readmem(page + OFFSET(page_first_page), KVADDR, &page,
+                       sizeof(page), "page.first_page", RETURN_ON_ERROR);
 
-       first_page = page;
-
-       if (!readmem(page+OFFSET(page_flags), KVADDR, &flags, sizeof(ulong),
-           "page.flags", RETURN_ON_ERROR))
-               return first_page;
-
-       if ((flags & vt->PG_head_tail_mask) == vt->PG_head_tail_mask)
-               readmem(page+OFFSET(page_first_page), KVADDR, &first_page, 
-                       sizeof(ulong), "page.first_page", RETURN_ON_ERROR);
-               
-       return first_page;
+       return page;
 }
 
 long 
-- 
2.2.0.rc0.207.ga3a616c

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

Reply via email to