Add a test that uses MADV_PAGEOUT to advise the kernel to page out
the PUD THP memory. This exercises the reclaim path which must split
the PUD THP before reclaiming the individual pages.
Signed-off-by: Usama Arif <usamaarif642@gmail.com>
---
tools/testing/selftests/mm/pud_thp_test.c | 33 +++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/tools/testing/selftests/mm/pud_thp_test.c b/tools/testing/selftests/mm/pud_thp_test.c
index b59eb470adbba..961fdc489d8a2 100644
--- a/tools/testing/selftests/mm/pud_thp_test.c
+++ b/tools/testing/selftests/mm/pud_thp_test.c
@@ -28,6 +28,10 @@
#define TEST_REGION_SIZE (2 * PUD_SIZE) /* 2GB to ensure PUD alignment */
+#ifndef MADV_PAGEOUT
+#define MADV_PAGEOUT 21
+#endif
+
/* Get PUD-aligned address within a region */
static inline void *pud_align(void *addr)
{
@@ -282,4 +286,33 @@ TEST_F(pud_thp, mprotect_split)
self->split_before, split_after);
}
+/*
+ * Test: Reclaim via MADV_PAGEOUT
+ * Verifies that reclaim path correctly handles PUD THPs
+ */
+TEST_F(pud_thp, reclaim_pageout)
+{
+ volatile unsigned char *p;
+ unsigned long split_after;
+ int ret;
+
+ /* Touch memory to allocate PUD THP */
+ memset(self->aligned, 0xAA, PUD_SIZE);
+
+ /* Try to reclaim the pages */
+ ret = madvise(self->aligned, PUD_SIZE, MADV_PAGEOUT);
+ if (ret < 0 && errno == EINVAL)
+ SKIP(return, "MADV_PAGEOUT not supported");
+ ASSERT_EQ(ret, 0);
+
+ split_after = read_vmstat("thp_split_pud");
+
+ /* Touch memory again to verify it's still accessible */
+ p = (unsigned char *)self->aligned;
+ (void)*p; /* Read to bring pages back if swapped */
+
+ TH_LOG("Reclaim completed (thp_split_pud: %lu -> %lu)",
+ self->split_before, split_after);
+}
+
TEST_HARNESS_MAIN
--
2.47.3