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

The page cache caps folio order at MAX_PAGECACHE_ORDER, which is smaller
than the PMD order on arm64 with 64K pages, where a PMD is 512M.  A
PMD-sized page cache folio is impossible there, so MADV_COLLAPSE answers
-EINVAL and khugepaged passes over the range.  The shmem cases ask for a
PMD-sized folio anyway, so four of them fail and the run bails out in the
middle.

MAX_PAGECACHE_ORDER is not shmem-specific: it caps every file folio.  Skip
both mem types where the cap is below the PMD order.

Anonymous collapse is unaffected: its orders are not capped this way.

Assisted-by: Claude-Code:claude-opus-5
Tested-by: Muhammad Usama Anjum <[email protected]>
Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]>
---
 tools/testing/selftests/mm/khugepaged.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tools/testing/selftests/mm/khugepaged.c 
b/tools/testing/selftests/mm/khugepaged.c
index c499804a0ec4..ec5c36a19d92 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -1357,6 +1357,30 @@ int main(int argc, char **argv)
 
        setbuf(stdout, NULL);
 
+       /*
+        * The page cache caps folio order at MAX_PAGECACHE_ORDER, which is
+        * below the PMD order on arm64 with 64K pages.  A PMD-sized page cache
+        * folio is impossible there, so the kernel refuses these collapses by
+        * design and there is nothing to test.  The cap is not shmem-specific:
+        * it rules out regular files too, and the per-order shmem_enabled
+        * controls exist for exactly the orders it allows, which is what makes
+        * them readable here.
+        */
+       if (!(thp_shmem_supported_orders() & (1UL << hpage_pmd_order))) {
+               if (shmem_ops) {
+                       ksft_print_msg("no PMD-order page cache folio: skipping 
shmem\n");
+                       shmem_ops = NULL;
+               }
+               if (read_only_file_ops) {
+                       ksft_print_msg("no PMD-order page cache folio: skipping 
file\n");
+                       read_only_file_ops = NULL;
+                       read_write_file_read_ops = NULL;
+                       read_write_file_write_ops = NULL;
+               }
+               if (!anon_ops && !shmem_ops && !read_only_file_ops)
+                       ksft_exit_skip("Nothing left to collapse into\n");
+       }
+
        default_settings.khugepaged.max_ptes_none = hpage_pmd_nr - 1;
        default_settings.khugepaged.max_ptes_swap = hpage_pmd_nr / 8;
        default_settings.khugepaged.max_ptes_shared = hpage_pmd_nr / 2;
-- 
2.54.0


Reply via email to