From: "Kiryl Shutsemau (Meta)" <[email protected]>

The harness pins max_ptes_none to 0, so khugepaged only collapses a window
once every PTE in it is present.  A window with holes takes a different
route, and never gets raced.  A hole is zero-filled in the new folio
rather than copied.  Which slots count as holes keeps moving under the
racing MADV_DONTNEED, right up to the moment the PMD is detached.

Run both ends of the occupancy scale for every driver mode, one after the
other.  mTHP collapse supports only those two, 0 and HPAGE_PMD_NR - 1, and
coerces anything between them to 0.  Each result says which end it ran:

  ok 1 stepped/strict: 5s, 231 steps, no corruption
  ok 2 stepped/holes: 5s, 194 steps, no corruption

Assisted-by: LLM
Tested-by: Muhammad Usama Anjum <[email protected]>
Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]>
---
 tools/testing/selftests/mm/khugepaged_race.c | 32 ++++++++++++--------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/tools/testing/selftests/mm/khugepaged_race.c 
b/tools/testing/selftests/mm/khugepaged_race.c
index 448256704ef4..f31f12fc0390 100644
--- a/tools/testing/selftests/mm/khugepaged_race.c
+++ b/tools/testing/selftests/mm/khugepaged_race.c
@@ -231,6 +231,8 @@ int main(int argc, char **argv)
        const int nr_threads = ARRAY_SIZE(thread_names);
        pthread_t threads[ARRAY_SIZE(thread_names)];
        static const char * const all_modes[] = { "stepped", "free", "madvise" 
};
+       static const bool occupancies[] = { false, true };      /* strict, 
holes */
+       const int nr_occupancies = ARRAY_SIZE(occupancies);
        const char *one_mode[1];
        const char * const *modes = all_modes;
        int nr_modes = ARRAY_SIZE(all_modes);
@@ -298,7 +300,7 @@ int main(int argc, char **argv)
                 -1, 0) != (void *)mremap_scratch)
                ksft_exit_fail_perror("mmap() mremap scratch");
 
-       ksft_set_plan(nr_modes);
+       ksft_set_plan(nr_modes * nr_occupancies);
 
        thp_save_settings();
        thp_read_settings(&settings);
@@ -306,8 +308,9 @@ int main(int argc, char **argv)
        /* Base of the settings stack; the bottom entry is never popped */
        thp_push_settings(&settings);
 
-       for (int m = 0; m < nr_modes; m++) {
-               const char *mode = modes[m];
+       for (int run = 0; run < nr_modes * nr_occupancies; run++) {
+               const char *mode = modes[run / nr_occupancies];
+               bool holes = occupancies[run % nr_occupancies];
 
                thp_read_settings(&settings);
                settings.thp_enabled = THP_MADVISE;
@@ -317,12 +320,14 @@ int main(int argc, char **argv)
                settings.khugepaged.scan_sleep_millisecs =
                        strcmp(mode, "free") ? 1000 : 0;
                settings.khugepaged.alloc_sleep_millisecs = 10;
+
                /*
-                * mTHP collapse honours only 0 or HPAGE_PMD_NR - 1 here, and 0
-                * keeps a step from being spent on PMD allocations that racing
-                * MADV_DONTNEED will not let succeed.
+                * mTHP collapse honours only 0 or HPAGE_PMD_NR - 1 here.  The 
two
+                * ends race different paths: a strict window has every PTE
+                * present, a hole-heavy one is mostly zero-filled.
                 */
-               settings.khugepaged.max_ptes_none = 0;
+               settings.khugepaged.max_ptes_none = holes ?
+                       (hpage_pmd_size / page_size) - 1 : 0;
                /* One wake, one pass: the playground plus the forked 
children's copies */
                settings.khugepaged.pages_to_scan =
                        nr_areas * (hpage_pmd_size / page_size) * 8;
@@ -388,8 +393,9 @@ int main(int argc, char **argv)
                        check_page(i);
 
                ksft_test_result(!corrupted,
-                                "%s: %ds, %d steps, no corruption\n",
-                                mode, duration_s, steps);
+                                "%s/%s: %ds, %d steps, no corruption\n",
+                                mode, holes ? "holes" : "strict",
+                                duration_s, steps);
 
                /* The next mode maps the same fixed address with its own 
settings */
                munmap(region, nr_areas * hpage_pmd_size);
@@ -399,9 +405,11 @@ int main(int argc, char **argv)
 
                if (corrupted) {
                        /* Memory is suspect; the rest would prove nothing */
-                       while (++m < nr_modes)
-                               ksft_test_result_skip("%s: skipped after 
corruption\n",
-                                                     modes[m]);
+                       while (++run < nr_modes * nr_occupancies)
+                               ksft_test_result_skip("%s/%s: skipped after 
corruption\n",
+                                                     modes[run / 
nr_occupancies],
+                                                     occupancies[run % 
nr_occupancies] ?
+                                                     "holes" : "strict");
                        break;
                }
        }
-- 
2.54.0


Reply via email to