[PATCH 14/16] selftests/mm: zap whole PTE tables in the khugepaged race harness

Kiryl Shutsemau <[email protected]> Sun, 2 Aug 2026 20:52:46 +0100
Newsgroups org.kernel.vger.linux-kselftest,org.kernel.vger.linux-kernel,org.kvack.linux-mm
Message-ID <[email protected]>
From: "Kiryl Shutsemau (Meta)" <[email protected]>

The race harness's MADV_DONTNEED thread zaps 1..32 pages at a time —
never a whole PMD-aligned area, so the empty-table reclaim
(CONFIG_PT_RECLAIM), which only engages when a zap spans the full
table, never ran against a collapse in any soak. Fuzzing had to find
the resulting class instead: the table vanishing between the
engine's park and install passes.

Make the thread zap a whole PMD-aligned area once every 64
iterations, keeping the fine-grained zaps as the common case.

Assisted-by: Claude-Code:claude-opus-5
Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]>
---
 tools/testing/selftests/mm/khugepaged_race.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/mm/khugepaged_race.c b/tools/testing/selftests/mm/khugepaged_race.c
index 304c72b4ee3c..2aa45c9e8a77 100644
--- a/tools/testing/selftests/mm/khugepaged_race.c
+++ b/tools/testing/selftests/mm/khugepaged_race.c
@@ -124,8 +124,23 @@ static void *dontneed_fn(void *arg)
 		unsigned long page_idx = rand_page(&seed);
 		unsigned long nr = 1UL << (rand_r(&seed) % 6);	/* 1..32 pages */
 
-		madvise(region + page_idx * page_size, nr * page_size,
-			MADV_DONTNEED);
+		/*
+		 * Once in a while zap a whole PMD-aligned area: only a
+		 * zap spanning the full table triggers the empty-table
+		 * reclaim (CONFIG_PT_RECLAIM), which can free a table
+		 * out from under a parked collapse — sub-table zaps
+		 * never reach that path.
+		 */
+		if (!(rand_r(&seed) % 64)) {
+			unsigned long area = page_idx /
+					(hpage_pmd_size / page_size);
+
+			madvise(region + area * hpage_pmd_size,
+				hpage_pmd_size, MADV_DONTNEED);
+		} else {
+			madvise(region + page_idx * page_size,
+				nr * page_size, MADV_DONTNEED);
+		}
 		usleep(rand_r(&seed) % 500);
 	}
 	return NULL;
-- 
2.54.0