[RFC 12/12] selftests/mm: add PUD THP migration test

Usama Arif posted 12 patches 5 days, 8 hours ago
[RFC 12/12] selftests/mm: add PUD THP migration test
Posted by Usama Arif 5 days, 8 hours ago
Add a test that uses mbind() to change the NUMA memory policy, which
triggers migration. The kernel must split PUD THPs before migration
since there is no PUD-level migration entry support. The test verifies
data integrity after the migration attempt.

Signed-off-by: Usama Arif <usamaarif642@gmail.com>
---
 tools/testing/selftests/mm/pud_thp_test.c | 42 +++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/tools/testing/selftests/mm/pud_thp_test.c b/tools/testing/selftests/mm/pud_thp_test.c
index 961fdc489d8a2..7e227f29e69fb 100644
--- a/tools/testing/selftests/mm/pud_thp_test.c
+++ b/tools/testing/selftests/mm/pud_thp_test.c
@@ -32,6 +32,14 @@
 #define MADV_PAGEOUT	21
 #endif
 
+#ifndef MPOL_BIND
+#define MPOL_BIND	2
+#endif
+
+#ifndef MPOL_MF_MOVE
+#define MPOL_MF_MOVE	(1 << 1)
+#endif
+
 /* Get PUD-aligned address within a region */
 static inline void *pud_align(void *addr)
 {
@@ -315,4 +323,38 @@ TEST_F(pud_thp, reclaim_pageout)
 	       self->split_before, split_after);
 }
 
+/*
+ * Test: Migration via mbind
+ * Verifies that migration path correctly handles PUD THPs by splitting
+ */
+TEST_F(pud_thp, migration_mbind)
+{
+	unsigned char *bytes = (unsigned char *)self->aligned;
+	unsigned long nodemask = 1UL;  /* Node 0 */
+	unsigned long split_after;
+	int ret;
+
+	/* Touch memory to allocate PUD THP */
+	memset(self->aligned, 0xBB, PUD_SIZE);
+
+	/* Try to migrate by changing NUMA policy */
+	ret = syscall(__NR_mbind, self->aligned, PUD_SIZE, MPOL_BIND, &nodemask,
+		      sizeof(nodemask) * 8, MPOL_MF_MOVE);
+	/*
+	 * mbind may fail with EINVAL (single node) or EIO (migration failed),
+	 * which is acceptable - we just want to exercise the migration path.
+	 */
+	if (ret < 0 && errno != EINVAL && errno != EIO)
+		TH_LOG("mbind returned unexpected error: %s", strerror(errno));
+
+	split_after = read_vmstat("thp_split_pud");
+
+	/* Verify data integrity */
+	ASSERT_EQ(bytes[0], 0xBB);
+	ASSERT_EQ(bytes[PUD_SIZE - 1], 0xBB);
+
+	TH_LOG("Migration completed (thp_split_pud: %lu -> %lu)",
+	       self->split_before, split_after);
+}
+
 TEST_HARNESS_MAIN
-- 
2.47.3