Skip to contentSkip to conversation

kselftest: mm: fix some failure of split_huge_page_test

PATCH Superseded Yeoreum Yun 2 participants 8 messages Sep 14 – Sep 15

Subsystems (5)

v6 of 9 Superseded Latest is v9 →

lore
Share & tools
lore
#0 lore raw

v6 cover kselftest: mm: fix some failure of split_huge_page_test

split_huge_page_test can fail for the following reasons:

1. During the test, khugepaged may collapse previously split pages again, causing intermittent failures.

2. Since glibc commit 321e1fc73f (“malloc: Enable 2MB THP by default on AArch64”), glibc may call madvise(MADV_HUGEPAGE) for sufficiently large allocations made by memalign(). The underlying VMA may start at a different address from the aligned address returned by memalign(). Moreover, a subsequent madvise(MADV_HUGEPAGE) call does not split the VMA because it already has the same advice.

This causes the test to fail because the check_huge_xxx() helpers incorrectly require the address returned by memalign() to match the VMA start address reported in /proc/self/smaps.

Address these issues by applying MADV_NOHUGEPAGE after faulting in the huge page, preventing khugepaged from collapsing it again, and instead of relying on /proc/self/smaps, use /proc/self/pagemap and /proc/kpageflags to detect huge-page mappings and large folios:

1. If hpage_size == pmd_pagesize, check PAGE_IS_HUGE instead of using check_large_folios(), since only the mapping type matters. This identifies PMD-mapped huge pages.
2. Otherwise, use check_large_folios() to detect large folios. This covers mTHP cases.
3. Check the folio flags according to the type of huge page.

Since check_huge_shmem() was required to distinguish shmem huge pages because /proc/self/smaps reports them using a dedicated “ShmemPmdMapped” entry, as opposed to “FilePmdMapped” for file-backed huge pages.

Now that /proc/self/smaps is no longer used to detect huge pages and /proc/kpageflags is used instead, it is sufficient to distinguish
between file-backed and anonymous pages since the ShmemPmdMapped is also
kind of file-backed.

Therefore, remove check_huge_shmem() and use check_huge_file() instead.

This patch based on mm-unstable

---
Changes in v6:
- drop alloc_isolated_mem() patch.
- remove check_huge_shmem().
- Link to v5: https://lore.kernel.org/r/[email protected]

Changes in v5:
- rename madv_nohuge() to disable_khugepaged().
- Link to v4: https://lore.kernel.org/r/[email protected]

Changes in v4:
- reparse commit message.
- introduce alloc_isolated_mem().
- make madv_nohuge() helper according to suggestion.
- Link to v3: https://lore.kernel.org/r/[email protected]

Changes in v3:
- change message in case of failure of madvise() with MADV_NOHUGEPAGE.
- fix collapse_single_mthp (mthp_khugepaged:anon) test case failure.
- Link to v2: https://lore.kernel.org/all/[email protected]/

Changes in v2:
- rebase to mm-unstable.
- add message in case of failure of madvise() with MADV_NOHUGEPAGE.
- fix wrong setup expected_huge in check_huge_shmem().
- Link to v1: https://lore.kernel.org/r/[email protected]

---
Yeoreum Yun (3):
kselftest: mm: prevent random failure of huge page split for khugepaged
kselftest: mm: replace usage of /proc/self/smaps for check_huge_xxx() helper
kselftest: mm: remove check_huge_shmem()

 tools/testing/selftests/mm/folio_split_race_test.c |   2 +-
 tools/testing/selftests/mm/khugepaged.c            |   5 +-
 tools/testing/selftests/mm/split_huge_page_test.c  |  19 +++
 tools/testing/selftests/mm/uffd-common.c           |   4 +-
 tools/testing/selftests/mm/vm_util.c               | 134 ++++++++++++---------
 tools/testing/selftests/mm/vm_util.h               |   1 -
 6 files changed, 104 insertions(+), 61 deletions(-)

---
base-commit: 6b41451631cabf9ea3b384c2a099088e1598f963
change-id: 20260820-fix_split-f44939ec44b8

Best regards,

Signature · 2 lines
Sincerely,
Yeoreum Yun
#1 lore raw

PATCH v6 1/3 kselftest: mm: prevent random failure of huge page split for khugepaged

There're some random failure for split_huge_page_test when khugepaged collapses pages into pmd again which had split by the test.

Prevent the khugepaged's collapses for split page by setting the mapped pmd-huge-page with MADV_NOHUGEPAGE before split.

---
 tools/testing/selftests/mm/split_huge_page_test.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
tools/testing/selftests/mm/split_huge_page_test.c +19 -0
index c01d227d7fd6..cba327f77873 100644
@@ -167,6 +167,18 @@ static char *allocate_zero_filled_hugepage(size_t len)
 	return result;
 }
 
+static void disable_khugepaged(void *addr, size_t len)
+{
+	/*
+	 * Disables khugepaged from collapsing THPs in range, existing THP
+	 * pages remain.
+	 */
+	if (!madvise(addr, len, MADV_NOHUGEPAGE))
+		return;
+
+	ksft_exit_fail_msg("MADV_NOHUGEPAGE failed, err=%d\n", errno);
+}
+
 static void verify_rss_anon_split_huge_page_all_zeroes(char *one_page, int nr_hpages, size_t len)
 {
 	unsigned long rss_anon_before, rss_anon_after;
@@ -179,6 +191,8 @@ static void verify_rss_anon_split_huge_page_all_zeroes(char *one_page, int nr_hp
 	if (!rss_anon_before)
 		ksft_exit_fail_msg("No RssAnon is allocated before split\n");
 
+	disable_khugepaged(one_page, len);
+
 	/* split all THPs */
 	write_debugfs(PID_FMT, getpid(), (uint64_t)one_page,
 		      (uint64_t)one_page + len, 0);
@@ -226,6 +240,8 @@ static void split_pmd_thp_to_order(int order)
 	if (!check_huge_anon(one_page, 4 * pmd_pagesize, 4, pmd_pagesize))
 		ksft_exit_fail_msg("No THP is allocated\n");
 
+	disable_khugepaged(one_page, len);
+
 	/* split all THPs */
 	write_debugfs(PID_FMT, getpid(), (uint64_t)one_page,
 		(uint64_t)one_page + len, order);
@@ -274,6 +290,8 @@ static void split_pte_mapped_thp(void)
 		goto out;
 	}
 
+	disable_khugepaged(thp_area, thp_area_size);
+
 	/*
 	 * To challenge spitting code, we will mremap a single page of each
 	 * THP (page[i] of thp[i]) in the thp_area into page_area. This will
@@ -541,6 +559,7 @@ static int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size,
 		ksft_test_result_skip("Pagecache folio split skipped\n");
 		return -2;
 	}
+	disable_khugepaged(*addr, fd_size);
 	return 0;
 err_out_close:
 	close(*fd);
Signature · 1 line
2.43.0
#2 lore raw

PATCH v6 2/3 kselftest: mm: replace usage of /proc/self/smaps for check_huge_xxx() helper

In reply to Yeoreum Yun

Since glibc commit 321e1fc73f (“malloc: Enable 2MB THP by default on AArch64”), glibc may call madvise(MADV_HUGEPAGE) for sufficiently large allocations made by memalign().

The underlying VMA may start at a different address from the aligned address returned by memalign(). Furthermore, a subsequent madvise(MADV_HUGEPAGE) call does not split the VMA because the flag is already set.

This causes split_huge_page_test to fail because the check_huge_xxx() helpers incorrectly require the address returned by memalign() to match the VMA start address reported in /proc/self/smaps.

Instead of relying on /proc/self/smaps, use /proc/self/pagemap and /proc/kpageflags to detect huge-page mappings and large folios:

1. If hpage_size == pmd_pagesize, check PAGE_IS_HUGE instead of using check_large_folios(), since only the mapping type matters. This identifies PMD-mapped huge pages.
2. Otherwise, use check_large_folios() to detect large folios. This covers mTHP cases.
3. Check the folio flags according to the type of huge page.

---
 tools/testing/selftests/mm/vm_util.c | 143 ++++++++++++++++++++++-------------
 tools/testing/selftests/mm/vm_util.h |   1 +
 2 files changed, 90 insertions(+), 54 deletions(-)
tools/testing/selftests/mm/vm_util.c +89 -54
index 4821a3563036..98f110098179 100644
@@ -351,31 +351,13 @@ char *__get_smap_entry(void *addr, const char *pattern, char *buf, size_t len)
 	return entry;
 }
 
-static bool __check_pmd_huge(void *addr, char *pattern, int nr_hpages,
-		  uint64_t hpage_size)
-{
-	char buffer[MAX_LINE_LENGTH];
-	uint64_t thp = -1;
-	char *entry;
-
-	entry = __get_smap_entry(addr, pattern, buffer, sizeof(buffer));
-	if (!entry)
-		goto err_out;
-
-	if (sscanf(entry, "%9" SCNu64 " kB", &thp) != 1)
-		ksft_exit_fail_msg("Reading smap error\n");
-
-err_out:
-	return thp == (nr_hpages * (hpage_size >> 10));
-}
-
-static bool check_large_folios(void *addr, size_t len, int nr_hpages,
-		uint64_t hpage_size)
+static bool check_large_folios(int pagemap_fd, int kpageflags_fd,
+			       void *addr, size_t len, int nr_hpages,
+			       uint64_t hpage_size)
 {
 	int order = 0, pagesize = getpagesize();
 	unsigned int nr_pages = hpage_size / pagesize;
 	int orders[MAX_NR_ORDERS], status;
-	int pagemap_fd, kpageflags_fd;
 	bool ret = false;
 
 	if (!nr_pages)
@@ -386,15 +368,6 @@ static bool check_large_folios(void *addr, size_t len, int nr_hpages,
 		ksft_exit_fail_msg("invalid order\n");
 
 	memset(orders, 0, sizeof(int) * MAX_NR_ORDERS);
-	pagemap_fd = open(PAGEMAP_PATH, O_RDONLY);
-	if (pagemap_fd == -1)
-		ksft_exit_fail_msg("read pagemap fail\n");
-
-	kpageflags_fd = open(KPAGEFLAGS_PATH, O_RDONLY);
-	if (kpageflags_fd == -1) {
-		close(pagemap_fd);
-		ksft_exit_fail_msg("read kpageflags fail\n");
-	}
 
 	status = gather_folio_orders(addr, len, pagemap_fd,
 			kpageflags_fd, orders, MAX_NR_ORDERS);
@@ -405,48 +378,110 @@ static bool check_large_folios(void *addr, size_t len, int nr_hpages,
 		ret = true;
 
 out:
-	close(pagemap_fd);
-	close(kpageflags_fd);
 	return ret;
 }
 
-bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
-{
-	uint64_t pmd_pagesize = read_pmd_pagesize();
-
-	if (!pmd_pagesize)
-		ksft_exit_fail_msg("reading PMD pagesize failed\n");
+enum check_huge_type {
+	CHECK_HUGE_ANON,
+	CHECK_HUGE_FILE,
+	CHECK_HUGE_SHMEM,
+};
 
-	if (hpage_size == pmd_pagesize)
-		return __check_pmd_huge(addr, "AnonHugePages: ", nr_hpages, hpage_size);
+static bool check_huge_type(uint64_t categories, uint64_t kpageflags,
+			    enum check_huge_type type)
+{
+	const bool file = categories & PAGE_IS_FILE;
+	const bool swapbacked = kpageflags & KPF_SWAPBACKED;
+
+	switch (type) {
+	case CHECK_HUGE_ANON:
+		return !file;
+	case CHECK_HUGE_FILE:
+		return file && !swapbacked;
+	case CHECK_HUGE_SHMEM:
+		return file && swapbacked;
+	}
 
-	return check_large_folios(addr, len, nr_hpages, hpage_size);
+	return false;
 }
 
-bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
+static bool __check_huge(void *addr, size_t len, int nr_hpages,
+			 uint64_t hpage_size, enum check_huge_type type)
 {
-	uint64_t pmd_pagesize = read_pmd_pagesize();
+	bool ret = false;
+	int pagemap_fd, kpageflags_fd;
+	int nr_pmd_mappings = 0;
+	uint64_t pmd_pagesize, scan_mapping_size;
+	uint64_t categories, kpf;
+	unsigned long pfn;
+	bool check_pmd_mapping, allow_nonpresent;
+	char *start = addr;
+	char *end = start + len;
 
+	pmd_pagesize = read_pmd_pagesize();
 	if (!pmd_pagesize)
 		ksft_exit_fail_msg("reading PMD pagesize failed\n");
 
-	if (hpage_size == pmd_pagesize)
-		return __check_pmd_huge(addr, "FilePmdMapped:", nr_hpages, hpage_size);
+	check_pmd_mapping = (hpage_size == pmd_pagesize);
+	scan_mapping_size = (nr_hpages > 0) ? hpage_size : psize();
+	/* Some mTHP tests check a partially populated PMD-sized range. */
+	allow_nonpresent = (uint64_t)nr_hpages * hpage_size < len;
 
-	return check_large_folios(addr, len, nr_hpages, hpage_size);
+	pagemap_fd = open(PAGEMAP_PATH, O_RDONLY);
+	if (pagemap_fd < 0)
+		ksft_exit_fail_msg("open pagemap fail\n");
+
+	kpageflags_fd = open(KPAGEFLAGS_PATH, O_RDONLY);
+	if (kpageflags_fd < 0)
+		ksft_exit_fail_msg("open kpageflags fail\n");
+
+	if (!check_pmd_mapping &&
+	    !check_large_folios(pagemap_fd, kpageflags_fd,
+				addr, len, nr_hpages, hpage_size))
+		goto out;
+
+	for (; start < end; start += scan_mapping_size) {
+		categories = pagemap_scan_get_categories(pagemap_fd, start);
+		pfn = pagemap_get_pfn(pagemap_fd, start);
+		if (pfn == -1UL) {
+			if (!allow_nonpresent)
+				goto out;
+			else
+				continue;
+		}
+		if (pageflags_get(pfn, kpageflags_fd, &kpf))
+			ksft_exit_fail_msg("read kpageflags: %s\n", strerror(errno));
+		if (check_pmd_mapping && (categories & PAGE_IS_HUGE))
+			nr_pmd_mappings++;
+		if (kpf & KPF_COMPOUND_TAIL)
+			continue;
+		if (!check_huge_type(categories, kpf, type))
+			goto out;
+	}
+
+	if (check_pmd_mapping && (nr_pmd_mappings != nr_hpages))
+		goto out;
+	ret = true;
+
+out:
+	close(pagemap_fd);
+	close(kpageflags_fd);
+	return ret;
 }
 
-bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
+bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
 {
-	uint64_t pmd_pagesize = read_pmd_pagesize();
-
-	if (!pmd_pagesize)
-		ksft_exit_fail_msg("reading PMD pagesize failed\n");
+	return __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_ANON);
+}
 
-	if (hpage_size == pmd_pagesize)
-		return __check_pmd_huge(addr, "ShmemPmdMapped:", nr_hpages, hpage_size);
+bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
+{
+	return __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_FILE);
+}
 
-	return check_large_folios(addr, len, nr_hpages, hpage_size);
+bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
+{
+	return __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_SHMEM);
 }
 
 int64_t allocate_transhuge(void *ptr, int pagemap_fd)
tools/testing/selftests/mm/vm_util.h +1 -0
index 9a49af88702e..f19bd17817e5 100644
@@ -18,6 +18,7 @@
 #define PM_SWAP                       BIT_ULL(62)
 #define PM_PRESENT                    BIT_ULL(63)
 
+#define KPF_SWAPBACKED                BIT_ULL(14)
 #define KPF_COMPOUND_HEAD             BIT_ULL(15)
 #define KPF_COMPOUND_TAIL             BIT_ULL(16)
 #define KPF_HWPOISON                  BIT_ULL(19)
Signature · 1 line
2.43.0
#3 lore raw

Re: [PATCH v6 2/3] kselftest: mm: replace usage of /proc/self/smaps for check_huge_xxx() helper

Quoted 8 lines
tools/testing/selftests/mm/vm_util.c +4 -2
-	if (hpage_size == pmd_pagesize)
-		return __check_pmd_huge(addr, "AnonHugePages: ", nr_hpages, hpage_size);
+static bool check_huge_type(uint64_t categories, uint64_t kpageflags,
+			    enum check_huge_type type)
+{
+	const bool file = categories & PAGE_IS_FILE;

tools/testing/selftests/mm/vm_util.c static bool check_large_folios(void *addr, size_t len, int nr_hpages, · line 403

Quoted 10 lines
tools/testing/selftests/mm/vm_util.c +10 -0
+	const bool swapbacked = kpageflags & KPF_SWAPBACKED;
+
+	switch (type) {
+	case CHECK_HUGE_ANON:
+		return !file;
+	case CHECK_HUGE_FILE:
+		return file && !swapbacked;
+	case CHECK_HUGE_SHMEM:
+		return file && swapbacked;
+	}

I wasn't probably clear. Don't add an intermediate CHECK_HUGE_SHMEM. Make check_huge_shmem() simply use CHECK_HUGE_FILE and remove the function then in patch #3.

Signature · 3 lines
Cheers,

David
#4 lore raw

Re: [PATCH v6 2/3] kselftest: mm: replace usage of /proc/self/smaps for check_huge_xxx() helper

Quoted 14 lines · David Hildenbrand (Arm)
Quoted 14 lines
tools/testing/selftests/mm/vm_util.c +10 -2
-	if (hpage_size == pmd_pagesize)
-		return __check_pmd_huge(addr, "AnonHugePages: ", nr_hpages, hpage_size);
+static bool check_huge_type(uint64_t categories, uint64_t kpageflags,
+			    enum check_huge_type type)
+{
+	const bool file = categories & PAGE_IS_FILE;
+	const bool swapbacked = kpageflags & KPF_SWAPBACKED;
+
+	switch (type) {
+	case CHECK_HUGE_ANON:
+		return !file;
+	case CHECK_HUGE_FILE:
Quoted 8 lines

tools/testing/selftests/mm/vm_util.c static bool check_large_folios(void *addr, size_t len, int nr_hpages, · line 403

Quoted 4 lines
tools/testing/selftests/mm/vm_util.c +4 -0
+		return file && !swapbacked;
+	case CHECK_HUGE_SHMEM:
+		return file && swapbacked;
+	}

I wasn't probably clear. Don't add an intermediate CHECK_HUGE_SHMEM. Make check_huge_shmem() simply use CHECK_HUGE_FILE and remove the function then in patch #3.

Okay. Thanks for clarification ;)

Signature · 2 lines
Sincerely,
Yeoreum Yun
#5 lore raw

PATCH v6 3/3 kselftest: mm: remove check_huge_shmem()

In reply to Yeoreum Yun

check_huge_shmem() was required to distinguish shmem huge pages because /proc/self/smaps reports them using a dedicated “ShmemPmdMapped” entry, as opposed to “FilePmdMapped” for file-backed huge pages.

Now that /proc/self/smaps is no longer used to detect huge pages and /proc/kpageflags is used instead, it is sufficient to distinguish between file-backed and anonymous pages since the ShmemPmdMapped is also kind of file-backed.

Therefore, remove check_huge_shmem() and use check_huge_file() instead.

---
 tools/testing/selftests/mm/folio_split_race_test.c |  2 +-
 tools/testing/selftests/mm/khugepaged.c            |  5 ++---
 tools/testing/selftests/mm/uffd-common.c           |  4 ++--
 tools/testing/selftests/mm/vm_util.c               | 11 +----------
 tools/testing/selftests/mm/vm_util.h               |  2 --
 5 files changed, 6 insertions(+), 18 deletions(-)
tools/testing/selftests/mm/folio_split_race_test.c +1 -1
index 1960635a953e..4c0d3b6a411b 100644
@@ -182,7 +182,7 @@ static uint64_t run_iteration(void)
 	for (i = 0; i < TOTAL_PAGES; i++)
 		fill_page(mmap_base, i);
 
-	if (!check_huge_shmem(mmap_base, FILE_SIZE, NR_PMD_PAGE, pmd_pagesize))
+	if (!check_huge_file(mmap_base, FILE_SIZE, NR_PMD_PAGE, pmd_pagesize))
 		ksft_exit_fail_msg("No shmem THP is allocated\n");
 
 	if (pthread_barrier_init(&ctl.barrier, NULL, NUM_READER_THREADS + 1) != 0)
tools/testing/selftests/mm/khugepaged.c +2 -3
index f82673f5f6b4..6cd1effea465 100644
@@ -416,9 +416,8 @@ static bool file_check_huge(void *addr, size_t len, int nr_hpages,
 {
 	switch (finfo.type) {
 	case VMA_FILE:
-		return check_huge_file(addr, len, nr_hpages, hpage_size);
 	case VMA_SHMEM:
-		return check_huge_shmem(addr, len, nr_hpages, hpage_size);
+		return check_huge_file(addr, len, nr_hpages, hpage_size);
 	default:
 		ksft_exit_fail_msg("Unknown VMA type\n");
 		return false;
@@ -451,7 +450,7 @@ static void shmem_cleanup_area(void *p, unsigned long size)
 static bool shmem_check_huge(void *addr, size_t len, int nr_hpages,
 		unsigned long hpage_size)
 {
-	return check_huge_shmem(addr, len, nr_hpages, hpage_size);
+	return check_huge_file(addr, len, nr_hpages, hpage_size);
 }
 
 static struct mem_ops __anon_ops = {
tools/testing/selftests/mm/uffd-common.c +2 -2
index 1fb967ef4985..a76851aced4d 100644
@@ -196,8 +196,8 @@ static void shmem_check_pmd_mapping(uffd_global_test_opts_t *gopts, void *p, int
 {
 	size_t len = expect_nr_hpages * read_pmd_pagesize();
 
-	if (!check_huge_shmem(gopts->area_dst_alias, len, expect_nr_hpages,
-			      read_pmd_pagesize()))
+	if (!check_huge_file(gopts->area_dst_alias, len, expect_nr_hpages,
+			     read_pmd_pagesize()))
 		err("Did not find expected %d number of hugepages",
 		    expect_nr_hpages);
 }
tools/testing/selftests/mm/vm_util.c +1 -10
index 98f110098179..e31e88d5af76 100644
@@ -384,22 +384,18 @@ static bool check_large_folios(int pagemap_fd, int kpageflags_fd,
 enum check_huge_type {
 	CHECK_HUGE_ANON,
 	CHECK_HUGE_FILE,
-	CHECK_HUGE_SHMEM,
 };
 
 static bool check_huge_type(uint64_t categories, uint64_t kpageflags,
 			    enum check_huge_type type)
 {
 	const bool file = categories & PAGE_IS_FILE;
-	const bool swapbacked = kpageflags & KPF_SWAPBACKED;
 
 	switch (type) {
 	case CHECK_HUGE_ANON:
 		return !file;
 	case CHECK_HUGE_FILE:
-		return file && !swapbacked;
-	case CHECK_HUGE_SHMEM:
-		return file && swapbacked;
+		return file;
 	}
 
 	return false;
@@ -479,11 +475,6 @@ bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
 	return __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_FILE);
 }
 
-bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size)
-{
-	return __check_huge(addr, len, nr_hpages, hpage_size, CHECK_HUGE_SHMEM);
-}
-
 int64_t allocate_transhuge(void *ptr, int pagemap_fd)
 {
 	uint64_t ent[2];
tools/testing/selftests/mm/vm_util.h +0 -2
index f19bd17817e5..fc9c93235f6f 100644
@@ -18,7 +18,6 @@
 #define PM_SWAP                       BIT_ULL(62)
 #define PM_PRESENT                    BIT_ULL(63)
 
-#define KPF_SWAPBACKED                BIT_ULL(14)
 #define KPF_COMPOUND_HEAD             BIT_ULL(15)
 #define KPF_COMPOUND_TAIL             BIT_ULL(16)
 #define KPF_HWPOISON                  BIT_ULL(19)
@@ -93,7 +92,6 @@ uint64_t read_pmd_pagesize(void);
 unsigned long rss_anon(void);
 bool check_huge_anon(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);
 bool check_huge_file(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);
-bool check_huge_shmem(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);
 int64_t allocate_transhuge(void *ptr, int pagemap_fd);
 int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags);
 int gather_folio_orders(char *vaddr_start, size_t len,
Signature · 1 line
2.43.0
#6 lore raw

Re: [PATCH v6 3/3] kselftest: mm: remove check_huge_shmem()

Quoted 39 lines · Yeoreum Yun

check_huge_shmem() was required to distinguish shmem huge pages because /proc/self/smaps reports them using a dedicated “ShmemPmdMapped” entry, as opposed to “FilePmdMapped” for file-backed huge pages.

Now that /proc/self/smaps is no longer used to detect huge pages and /proc/kpageflags is used instead, it is sufficient to distinguish between file-backed and anonymous pages since the ShmemPmdMapped is also kind of file-backed.

Therefore, remove check_huge_shmem() and use check_huge_file() instead.

---
 tools/testing/selftests/mm/folio_split_race_test.c |  2 +-
 tools/testing/selftests/mm/khugepaged.c            |  5 ++---
 tools/testing/selftests/mm/uffd-common.c           |  4 ++--
 tools/testing/selftests/mm/vm_util.c               | 11 +----------
 tools/testing/selftests/mm/vm_util.h               |  2 --
 5 files changed, 6 insertions(+), 18 deletions(-)
tools/testing/selftests/mm/folio_split_race_test.c +1 -1
index 1960635a953e..4c0d3b6a411b 100644
@@ -182,7 +182,7 @@ static uint64_t run_iteration(void)
 	for (i = 0; i < TOTAL_PAGES; i++)
 		fill_page(mmap_base, i);
 
-	if (!check_huge_shmem(mmap_base, FILE_SIZE, NR_PMD_PAGE, pmd_pagesize))
+	if (!check_huge_file(mmap_base, FILE_SIZE, NR_PMD_PAGE, pmd_pagesize))
 		ksft_exit_fail_msg("No shmem THP is allocated\n");
 
 	if (pthread_barrier_init(&ctl.barrier, NULL, NUM_READER_THREADS + 1) != 0)
tools/testing/selftests/mm/khugepaged.c +0 -0
index f82673f5f6b4..6cd1effea465 100644

tools/testing/selftests/mm/khugepaged.c static bool file_check_huge(void *addr, size_t len, int nr_hpages, · line 423

Quoted 10 lines
tools/testing/selftests/mm/khugepaged.c +1 -2
@@ -416,9 +416,8 @@ static bool file_check_huge(void *addr, size_t len, int nr_hpages,
 {
 	switch (finfo.type) {
 	case VMA_FILE:
-		return check_huge_file(addr, len, nr_hpages, hpage_size);
 	case VMA_SHMEM:
-		return check_huge_shmem(addr, len, nr_hpages, hpage_size);
+		return check_huge_file(addr, len, nr_hpages, hpage_size);
 	default:
 		ksft_exit_fail_msg("Unknown VMA type\n");
 		return false;

Assuming we do:

tools/testing/selftests/mm/khugepaged.c +1 -1
index f82673f5f6b47..9542173a748e2 100644
@@ -53,7 +53,7 @@ struct mem_ops {
        void *(*setup_area)(int nr_hpages);
        void (*cleanup_area)(void *p, unsigned long size);
        void (*fault)(void *p, unsigned long start, unsigned long end);
-       bool (*check_huge)(void *addr, size_t len, int nr_hpages, unsigned long hpage_size);
+       bool (*check_huge)(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);
        const char *name;
 };
 

Could we then simply use check_huge_anon/check_huge_file directly and get rid of these helpers anon_check_huge + check_huge_file entirely?

Signature · 3 lines
Cheers,

David
#7 lore raw

Re: [PATCH v6 3/3] kselftest: mm: remove check_huge_shmem()

Quoted 68 lines · David Hildenbrand (Arm)
Quoted 39 lines · Yeoreum Yun

check_huge_shmem() was required to distinguish shmem huge pages because /proc/self/smaps reports them using a dedicated “ShmemPmdMapped” entry, as opposed to “FilePmdMapped” for file-backed huge pages.

Now that /proc/self/smaps is no longer used to detect huge pages and /proc/kpageflags is used instead, it is sufficient to distinguish between file-backed and anonymous pages since the ShmemPmdMapped is also kind of file-backed.

Therefore, remove check_huge_shmem() and use check_huge_file() instead.

---
 tools/testing/selftests/mm/folio_split_race_test.c |  2 +-
 tools/testing/selftests/mm/khugepaged.c            |  5 ++---
 tools/testing/selftests/mm/uffd-common.c           |  4 ++--
 tools/testing/selftests/mm/vm_util.c               | 11 +----------
 tools/testing/selftests/mm/vm_util.h               |  2 --
 5 files changed, 6 insertions(+), 18 deletions(-)
tools/testing/selftests/mm/folio_split_race_test.c +1 -1
index 1960635a953e..4c0d3b6a411b 100644
@@ -182,7 +182,7 @@ static uint64_t run_iteration(void)
 	for (i = 0; i < TOTAL_PAGES; i++)
 		fill_page(mmap_base, i);
 
-	if (!check_huge_shmem(mmap_base, FILE_SIZE, NR_PMD_PAGE, pmd_pagesize))
+	if (!check_huge_file(mmap_base, FILE_SIZE, NR_PMD_PAGE, pmd_pagesize))
 		ksft_exit_fail_msg("No shmem THP is allocated\n");
 
 	if (pthread_barrier_init(&ctl.barrier, NULL, NUM_READER_THREADS + 1) != 0)
tools/testing/selftests/mm/khugepaged.c +0 -0
index f82673f5f6b4..6cd1effea465 100644

tools/testing/selftests/mm/khugepaged.c static bool file_check_huge(void *addr, size_t len, int nr_hpages, · line 423

Quoted 10 lines
tools/testing/selftests/mm/khugepaged.c +1 -2
@@ -416,9 +416,8 @@ static bool file_check_huge(void *addr, size_t len, int nr_hpages,
 {
 	switch (finfo.type) {
 	case VMA_FILE:
-		return check_huge_file(addr, len, nr_hpages, hpage_size);
 	case VMA_SHMEM:
-		return check_huge_shmem(addr, len, nr_hpages, hpage_size);
+		return check_huge_file(addr, len, nr_hpages, hpage_size);
 	default:
 		ksft_exit_fail_msg("Unknown VMA type\n");
 		return false;

Assuming we do:

tools/testing/selftests/mm/khugepaged.c +1 -1
index f82673f5f6b47..9542173a748e2 100644
@@ -53,7 +53,7 @@ struct mem_ops {
        void *(*setup_area)(int nr_hpages);
        void (*cleanup_area)(void *p, unsigned long size);
        void (*fault)(void *p, unsigned long start, unsigned long end);
-       bool (*check_huge)(void *addr, size_t len, int nr_hpages, unsigned long hpage_size);
+       bool (*check_huge)(void *addr, size_t len, int nr_hpages, uint64_t hpage_size);
        const char *name;
 };
 
Quoted 2 lines

Could we then simply use check_huge_anon/check_huge_file directly and get rid of these helpers anon_check_huge + check_huge_file entirely?

Yeap. I'll follow your suggetion. Thanks!

Signature · 2 lines
Sincerely,
Yeoreum Yun