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 <[email protected]> --- 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

