[Crash-utility] [PATCH 1/5] memory: better compound page support

Yu Zhao yuzhao at google.com
Thu Feb 5 21:06:44 UTC 2015


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




More information about the Crash-utility mailing list