[PATCH] selftests/mm: skip collapse_compound_extreme() on THP allocation failure

From: Zenghui Yu

Date: Wed Oct 28 2026 - 06:02:53 EST


From: "Zenghui Yu (Huawei)" <zenghui.yu@xxxxxxxxx>

collapse_compound_extreme() needs hpage_pmd_nr PMD-order allocations in a
row, and it kills the whole test binary via ksft_exit_fail_msg() as soon as
one of them fails.

Gating the case by PMD size (commit b36bec6a01b1) -- the current workaround
for arm64 with 64K base pages, where a 512M PMD makes every construction
step an order-13 allocation -- is not enough: the case still dies below the
cutoff, e.g. on an arm64 VM with 16K base pages and 8G of RAM, where the
construction would need ~64G worth of PMD-order allocations.

Remove the PMD-size gating and treat a failure to allocate a huge page
during the construction as a skip: whether the allocator can hand out
that many PMD-order folios in a row depends on the memory available on
the machine, not on the kernel.

Suggested-by: Kiryl Shutsemau <kirill@xxxxxxxxxxxxx>
Link: https://lore.kernel.org/all/atiQmWnz8zx2AKI7@thinkstation
Signed-off-by: Zenghui Yu (Huawei) <zenghui.yu@xxxxxxxxx>
---
tools/testing/selftests/mm/khugepaged.c | 26 +++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
index 1bc7acc66a46..e6151732b17c 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -953,23 +953,25 @@ static void collapse_compound_extreme(struct collapse_context *c, struct mem_ops
void *p;
int i;

- /*
- * This needs hpage_pmd_nr PMD-order allocations in a row, which the
- * allocator will not supply if the PMD is very large.
- */
- if (hpage_pmd_size > (32UL << 20)) {
- ksft_test_result_skip("%s: PMD too large for fault-time THP construction\n",
- __func__);
- return;
- }
-
p = ops->setup_area(1);
ksft_print_msg("Construct PTE page table full of different PTE-mapped compound pages\n");
for (i = 0; i < hpage_pmd_nr; i++) {
madvise(BASE_ADDR, hpage_pmd_size, MADV_HUGEPAGE);
ops->fault(BASE_ADDR, 0, hpage_pmd_size);
- if (!ops->check_huge(BASE_ADDR, hpage_pmd_size, 1, hpage_pmd_size))
- ksft_exit_fail_msg("Failed to allocate huge page\n");
+ if (!ops->check_huge(BASE_ADDR, hpage_pmd_size, 1, hpage_pmd_size)) {
+ /*
+ * Constructing the PTE table requires hpage_pmd_nr
+ * PMD-order allocations in a row. Whether the
+ * allocator can supply them depends on the memory
+ * available on the machine, not on the kernel: skip
+ * instead of failing the test run.
+ */
+ ops->cleanup_area(BASE_ADDR - i * page_size,
+ i * page_size + hpage_pmd_size);
+ ksft_test_result_skip("%s: Failed to allocate huge page\n",
+ __func__);
+ return;
+ }
madvise(BASE_ADDR, hpage_pmd_size, MADV_NOHUGEPAGE);

p = mremap(BASE_ADDR - i * page_size,
--
2.56.0