[PATCH RESEND v1 5/5] selftests/mm: retry migration failures for the full runtime
From: Muhammad Usama Anjum
Date: Wed Jul 22 2026 - 05:21:10 EST
move_pages() migration is best effort and may temporarily leave a page
unmigrated when another task faults on the folio during unmapping. The
migration test currently tolerates 100 consecutive partial failures,
but a busy machine can exhaust those retries in a fraction of a second
and fail long before the intended 20-second runtime expires.
This is especially visible in the shared-anon cases, where every worker
process continuously accesses the same mapping. The retry count then
measures syscall rate rather than whether the test can exercise a
successful migration entry.
Retry positive move_pages() results for the full runtime and record the
per-page status. Pass if at least one migration succeeds, and report the
last status before failing if no migration makes progress. Continue to
fail immediately for syscall-level errors.
Signed-off-by: Muhammad Usama Anjum <usama.anjum@xxxxxxx>
---
tools/testing/selftests/mm/migration.c | 34 +++++++++++++++++---------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/tools/testing/selftests/mm/migration.c b/tools/testing/selftests/mm/migration.c
index 29f7492453d43..19b4cef65f345 100644
--- a/tools/testing/selftests/mm/migration.c
+++ b/tools/testing/selftests/mm/migration.c
@@ -7,7 +7,7 @@
#include "kselftest_harness.h"
#include "hugepage_settings.h"
-#include <strings.h>
+#include <string.h>
#include <pthread.h>
#include <numa.h>
#include <numaif.h>
@@ -20,7 +20,6 @@
#define TWOMEG (2<<20)
#define RUNTIME (20)
-#define MAX_RETRIES 100
#define ALIGN(x, a) (((x) + (a - 1)) & (~((a) - 1)))
HUGETLB_SETUP_DEFAULT_PAGES(1)
@@ -110,7 +109,8 @@ int migrate(uint64_t *ptr, int n1, int n2)
int ret, tmp;
int status = 0;
struct timespec ts1, ts2;
- int failures = 0;
+ int last_status = 0;
+ unsigned long successes = 0;
if (clock_gettime(CLOCK_MONOTONIC, &ts1))
return -1;
@@ -119,23 +119,33 @@ int migrate(uint64_t *ptr, int n1, int n2)
if (clock_gettime(CLOCK_MONOTONIC, &ts2))
return -1;
- if (ts2.tv_sec - ts1.tv_sec >= RUNTIME)
- return 0;
+ if (ts2.tv_sec - ts1.tv_sec >= RUNTIME) {
+ if (successes)
+ return 0;
+ if (last_status < 0)
+ printf("No page migration succeeded: %s (%d)\n",
+ strerror(-last_status), last_status);
+ else
+ printf("No page migration succeeded: status %d\n",
+ last_status);
+ return -2;
+ }
+
+ status = 0;
ret = move_pages(0, 1, (void **) &ptr, &n2, &status,
MPOL_MF_MOVE_ALL);
if (ret) {
if (ret > 0) {
- /* Migration is best effort; try again */
- if (++failures < MAX_RETRIES)
- continue;
- printf("Didn't migrate %d pages\n", ret);
- }
- else
+ /* Migration is best effort; try again. */
+ last_status = status;
+ continue;
+ } else {
perror("Couldn't migrate pages");
+ }
return -2;
}
- failures = 0;
+ successes++;
tmp = n2;
n2 = n1;
n1 = tmp;
--
2.47.3