On 8/3/26 3:52 AM, Kiryl Shutsemau wrote:
From: "Kiryl Shutsemau (Meta)" <[email protected]>
mTHP collapse went in for 7.2 with no functional selftest coverage. Every
khugepaged collapse case is PMD-shaped, down to the detection: it reads
smaps AnonHugePages, which cannot see anything below the PMD order.
Yes, I’ve already sent out several versions of mTHP collapse test
cases[1]. Not sure if you’ve seen my patchset, and it looks like some of
our work overlaps :(
[1]
https://lore.kernel.org/all/[email protected]/
I am also reworking khugepaged's collapse mechanism, and that wants a suite
worth trusting before the mechanism changes underneath it. Nothing here
depends on the rework -- everything passes on an unmodified kernel and
documents what khugepaged already does.
- vm_util grows folio-order helpers: is_backed_by_folio() moves out of
split_huge_page_test.c, and a range-level form asks whether every
order-aligned window of a range is backed by one folio of exactly that
order, mapped head to tail.
- folio_order_check validates those helpers against the kernel for every
anon THP order it supports, before any collapse test trusts them.
- khugepaged_full_pass() drives exactly one scan pass through the sysfs
wake path, so a barrier completes on the daemon's own cadence instead of
needing a short scan_sleep_millisecs.
- khugepaged -o <order> runs order-parameterized anon collapse cases: a
full table, only the populated window, default max_ptes_none and
max_ptes_none=0, and collapse upward from smaller large folios. Any
order up to the PMD order, where the same cases baseline the PMD path.
- khugepaged_race races two faulters, MADV_DONTNEED, transient FOLL_PIN,
fork and mremap against one of three collapse drivers: khugepaged a pass
at a time, khugepaged free-running, or a MADV_COLLAPSE loop. Every
racing page must read as its pattern or as zero. -z collapses
hole-bearing windows; -p adds pageout and compaction, the only threads
that elevate a source folio's refcount from the reclaim side. DEBUG_VM,
page_table_check, KASAN and lockdep are the other half of the oracle.
- A shared-source write race pins the CoW isolation contract: a co-sharer
writing throughout a collapse must not see the collapsing side's pages.
- Four tests fail on the environment rather than on the kernel: the
collapse wait is a fixed three seconds whatever a huge page costs to
build, collapse_compound_extreme wants a 512M page from the fault path,
the shmem cases want a PMD-order page cache folio the page cache caps
below, and the swap cases fail instead of skipping without swap. Scale
the wait (a 2M PMD is unchanged) and skip the other three. This is why
the suite now runs on arm64 with 64K pages.
Tested on mm-new (1dbd7c34bb92):
x86-64 4K 105 pass, 3 skip, 0 fail
arm64 64K 87 pass, 7 skip, 0 fail
The skips are structural: sub-PMD cases decline at the PMD order and the
mixed-source case at the smallest order, and on 64K pages
collapse_compound_extreme and the shmem cases skip for the reasons above.
Kiryl Shutsemau (Meta) (16):
selftests/mm: move is_backed_by_folio() into vm_util
selftests/mm: add folio-order check for VA ranges
selftests/mm: add folio-order detection self-check
selftests/mm: add order-parameterized khugepaged collapse cases
selftests/mm: add khugepaged completion barrier helper
selftests/mm: add khugepaged race harness
selftests/mm: cover a shared-source collapse write race
selftests/mm: skip collapse_compound_extreme where the PMD is too
large
selftests/mm: skip khugepaged swap tests when no swap is configured
selftests/mm: verify synchronous khugepaged driving is attributable
selftests/mm: race-harness variant for permissive hole occupancy
selftests/mm: add memory-pressure threads to the khugepaged race
harness
selftests/mm: parameterize the mixed-source collapse case by source
order
selftests/mm: zap whole PTE tables in the khugepaged race harness
selftests/mm: scale khugepaged's collapse wait with the PMD size
selftests/mm: skip khugepaged shmem cases without a PMD page cache
folio
tools/testing/selftests/mm/.gitignore | 3 +
tools/testing/selftests/mm/Makefile | 3 +
.../testing/selftests/mm/folio_order_check.c | 138 +++++
.../testing/selftests/mm/hugepage_settings.c | 66 ++-
.../testing/selftests/mm/hugepage_settings.h | 2 +
tools/testing/selftests/mm/khugepaged.c | 430 +++++++++++++++-
tools/testing/selftests/mm/khugepaged_race.c | 483 ++++++++++++++++++
.../selftests/mm/khugepaged_sync_check.c | 198 +++++++
tools/testing/selftests/mm/run_vmtests.sh | 17 +
.../selftests/mm/split_huge_page_test.c | 62 ---
tools/testing/selftests/mm/vm_util.c | 157 ++++++
tools/testing/selftests/mm/vm_util.h | 7 +
12 files changed, 1490 insertions(+), 76 deletions(-)
create mode 100644 tools/testing/selftests/mm/folio_order_check.c
create mode 100644 tools/testing/selftests/mm/khugepaged_race.c
create mode 100644 tools/testing/selftests/mm/khugepaged_sync_check.c