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.
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.
The table of cases is raised to 256 entries first. It holds 64, and a full
invocation -- every context crossed with every memory type, which needs a
directory for the file and shmem ones -- already registers 63, so the next
case added anywhere aborts the whole suite before a single test runs.
Four existing cases fail on the environment rather than on the kernel:
- The collapse wait is a fixed three seconds, whatever a huge page costs
to build. Scale it with the PMD size.
- collapse_compound_extreme wants a 512M folio from the fault path. Skip
it where the PMD is that large.
- The page cache caps folio order below the PMD order where a PMD is 512M,
so nothing can hold a PMD-sized page cache folio. Skip the shmem and
file cases there.
- The swap cases ask a best-effort MADV_PAGEOUT for an exact swap count,
and khugepaged reads the pages back in while they ask. Retry, hold the
range out of the daemon's reach while retrying, and skip if the pages
still will not go.
This is why the suite now runs on arm64 with 64K pages.
Then the new coverage:
- Folio-order helpers in vm_util, and folio_order_check to validate them
against the kernel before any collapse test trusts them.
- Four order-parameterized anon collapse cases, plus mixed sources by
source order, at every supported order by default.
- A shared-source write race: a co-sharer writing throughout a collapse
and the collapsing side must not see each other's pages.
- khugepaged_full_pass(), which steps the daemon one scan at a time
through the sysfs wake path, and khugepaged_sync_check to hold it to
exactly one attributed collapse per step.
- khugepaged_race, racing faults, MADV_DONTNEED, pins, fork and mremap
against collapse, checked by content and by KASAN and lockdep.
Changes since v2:
- Raise MAX_TEST_CASES before adding cases (new patch 1): a full
invocation aborted and ran nothing, at seven points in v2 (Sashiko).
- The swap cases hold MADV_NOHUGEPAGE while paging out, and skip when the
count still does not arrive, whatever the reason (Alexander Gordeev,
David Hildenbrand).
- Bound -s and -c: an out-of-range order indexed past a struct and shifted
by 65 (Sashiko).
- The mixed-source case skips, rather than ending the run, when the
allocator leaves nothing of the source order (Sashiko).
- khugepaged_race: clamp the zap and the pin to the shared areas, and keep
stdio out of the forked child (Sashiko).
- Name runs skipped after corruption the way finished ones are named
(Sashiko).
- Drop migration.c's ALIGN, which clashes with vm_util.h's (Sashiko).
- Rebased onto current mm-new.
Muhammad's Tested-by is carried onto every patch whose code is unchanged or
only mechanically changed since v2. It is not on patch 1, which is new, or
on the swap patch, which behaves differently from what he ran.
Tested on an unmodified mm-new (480a31230b42), with KASAN, lockdep,
DEBUG_VM and page_table_check, in 16G guests:
x86-64 4K 104 pass, 11 skip, 0 fail
arm64 64K 102 pass, 3 skip, 0 fail
The skips are structural: mixed sources declines at the smallest order, and
at 64K collapse_compound_extreme skips as above. arm64 runs fewer cases
than x86-64 rather than skipping them: with no PMD-order page cache folio
the file and shmem contexts are never registered there.
Kiryl Shutsemau (Meta) (18):
selftests/mm: raise the khugepaged test-case cap
selftests/mm: skip collapse_compound_extreme where the PMD is too
large
selftests/mm: scale khugepaged's collapse wait with the PMD size
selftests/mm: skip khugepaged page cache cases without a PMD folio
selftests/mm: keep khugepaged out of the swapout the swap cases set up
selftests/mm: move is_backed_by_folio() into vm_util
selftests/mm: add folio-order check for address ranges
selftests/mm: add folio-order detection self-check
selftests/mm: add khugepaged completion barrier helper
selftests/mm: add order-parameterized khugepaged collapse cases
selftests/mm: parameterize the mixed-source collapse case by source
order
selftests/mm: cover a shared-source collapse write race
selftests/mm: run every supported collapse order by default
selftests/mm: verify synchronous khugepaged driving is attributable
selftests/mm: add khugepaged race harness
selftests/mm: race collapse of windows with holes
selftests/mm: add memory-pressure threads to the khugepaged race
harness
selftests/mm: zap whole PTE tables in the khugepaged race harness
tools/testing/selftests/mm/Makefile | 3 +
.../testing/selftests/mm/folio_order_check.c | 137 ++++
tools/testing/selftests/mm/hmm-tests.c | 1 -
.../testing/selftests/mm/hugepage_settings.c | 72 ++-
.../testing/selftests/mm/hugepage_settings.h | 3 +
tools/testing/selftests/mm/khugepaged.c | 499 +++++++++++++-
tools/testing/selftests/mm/khugepaged_race.c | 610 ++++++++++++++++++
.../selftests/mm/khugepaged_sync_check.c | 217 +++++++
tools/testing/selftests/mm/migration.c | 1 -
tools/testing/selftests/mm/run_vmtests.sh | 8 +-
.../selftests/mm/split_huge_page_test.c | 62 --
tools/testing/selftests/mm/vm_util.c | 145 +++++
tools/testing/selftests/mm/vm_util.h | 10 +
13 files changed, 1668 insertions(+), 100 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
base-commit: 480a31230b426efb005b6e71a14ef80f405f18b6
--
2.54.0