[PATCH makedumpfile] Fix failure of hugetlb pages exclusion on Linux 6.9 and later

HAGIO KAZUHITO(萩尾 一仁) k-hagio-ab at nec.com
Thu May 30 00:59:02 PDT 2024


* Required for kernel 6.9

Kernel commit d99e3140a4d3 ("mm: turn folio_test_hugetlb into a
PageType") moved the PG_hugetlb flag from folio._flags_1 into
page._mapcount and introduced NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE) entry
into vmcoreinfo.

Without the patch, "makedumpfile -d 8" cannot exclude hugetlb pages.

Signed-off-by: Kazuhito Hagio <k-hagio-ab at nec.com>
---
 makedumpfile.c | 22 ++++++++++++++++++++--
 makedumpfile.h |  3 +++
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index d7f1dd41d2ca..a6cadc9092c9 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -2975,6 +2975,7 @@ read_vmcoreinfo(void)
 	READ_SRCFILE("pud_t", pud_t);
 
 	READ_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
+	READ_NUMBER("PAGE_HUGETLB_MAPCOUNT_VALUE", PAGE_HUGETLB_MAPCOUNT_VALUE);
 	READ_NUMBER("PAGE_OFFLINE_MAPCOUNT_VALUE", PAGE_OFFLINE_MAPCOUNT_VALUE);
 	READ_NUMBER("phys_base", phys_base);
 	READ_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
@@ -6510,6 +6511,9 @@ __exclude_unnecessary_pages(unsigned long mem_map,
 		_count  = UINT(pcache + OFFSET(page._refcount));
 		mapping = ULONG(pcache + OFFSET(page.mapping));
 
+		if (OFFSET(page._mapcount) != NOT_FOUND_STRUCTURE)
+			_mapcount = UINT(pcache + OFFSET(page._mapcount));
+
 		compound_order = 0;
 		compound_dtor = 0;
 		/*
@@ -6520,6 +6524,22 @@ __exclude_unnecessary_pages(unsigned long mem_map,
 		if ((index_pg < PGMM_CACHED - 1) && isCompoundHead(flags)) {
 			unsigned char *addr = pcache + SIZE(page);
 
+			/*
+			 * Linux 6.9 and later kernels use _mapcount value for hugetlb pages.
+			 * See kernel commit d99e3140a4d3.
+			 */
+			if (NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE) != NOT_FOUND_NUMBER) {
+				unsigned long _flags_1 = ULONG(addr + OFFSET(page.flags));
+				unsigned int PG_hugetlb = ~NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE);
+
+				compound_order = _flags_1 & 0xff;
+
+				if ((_mapcount & (PAGE_TYPE_BASE | PG_hugetlb)) == PAGE_TYPE_BASE)
+					compound_dtor = IS_HUGETLB;
+
+				goto check_order;
+			}
+
 			/*
 			 * Linux 6.6 and later.  Kernels that have PG_hugetlb should also
 			 * have the compound order in the low byte of folio._flags_1.
@@ -6564,8 +6584,6 @@ check_order:
 		if (OFFSET(page.compound_head) != NOT_FOUND_STRUCTURE)
 			compound_head = ULONG(pcache + OFFSET(page.compound_head));
 
-		if (OFFSET(page._mapcount) != NOT_FOUND_STRUCTURE)
-			_mapcount = UINT(pcache + OFFSET(page._mapcount));
 		if (OFFSET(page.private) != NOT_FOUND_STRUCTURE)
 			private = ULONG(pcache + OFFSET(page.private));
 
diff --git a/makedumpfile.h b/makedumpfile.h
index 75b66ceaba21..f08c49fc73be 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -165,6 +165,8 @@ test_bit(int nr, unsigned long addr)
 #define isAnon(mapping, flags)	(((unsigned long)mapping & PAGE_MAPPING_ANON) != 0 \
 				&& !isSlab(flags))
 
+#define PAGE_TYPE_BASE		(0xf0000000)
+
 #define PTOB(X)			(((unsigned long long)(X)) << PAGESHIFT())
 #define BTOP(X)			(((unsigned long long)(X)) >> PAGESHIFT())
 
@@ -2255,6 +2257,7 @@ struct number_table {
 	long    PG_hugetlb;
 
 	long	PAGE_BUDDY_MAPCOUNT_VALUE;
+	long	PAGE_HUGETLB_MAPCOUNT_VALUE;
 	long	PAGE_OFFLINE_MAPCOUNT_VALUE;
 	long	SECTION_SIZE_BITS;
 	long	MAX_PHYSMEM_BITS;
-- 
2.31.1



More information about the kexec mailing list