---
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