On Sat, Aug 15, 2026 at 02:58:50AM +0100, Kiryl Shutsemau wrote:
> From: "Kiryl Shutsemau (Meta)" <[email protected]>
>
> An mTHP collapse test needs to know that a range is backed by folios of the
> target order, and that they sit where a collapse would put them.  Nothing
> answers that today: is_backed_by_folio() classifies the folio behind a
> single page, and check_huge_anon() reads smaps AnonHugePages, which only
> accounts PMD mappings.
>
> Add is_range_backed_by_folio_orders().  For every order-aligned window of
> the range it requires a present head PFN at its natural alignment and a
> contiguous PFN run across the window.
>
> A window backed by two smaller folios fails the contiguity check, and a
> folio mapped off the window's alignment fails the head check.  The mTHP
> cases need both to tell a collapsed window from the one beside it.
>
> 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/vm_util.c | 42 ++++++++++++++++++++++++++++
>  tools/testing/selftests/mm/vm_util.h |  2 ++
>  2 files changed, 44 insertions(+)
>
> diff --git a/tools/testing/selftests/mm/vm_util.c 
> b/tools/testing/selftests/mm/vm_util.c
> index 5db1a7774f49..c9bd6c92fa41 100644
> --- a/tools/testing/selftests/mm/vm_util.c
> +++ b/tools/testing/selftests/mm/vm_util.c
> @@ -556,6 +556,48 @@ bool is_backed_by_folio(char *vaddr, int order, int 
> pagemap_fd,
>       return false;
>  }
>
> +/*
> + * Check whether every order-@order window of [start, len) maps exactly one

Strange to reference @order in a non-kdoc comment. And then to start referring
to start and len without @? :)

And I'm not sure 'window' is really clear here as a term...

> + * folio of that order, head to tail.  The address range must be naturally
> + * aligned, each window's PFN run must be contiguous, and a window's first
> + * PFN must be the folio head.

Also 'PFN run' is adding a new vague term.

> + *
> + * This is the check "did this range collapse into order-@order folios": a
> + * window assembled from parts of several folios, or mapping a folio shifted
> + * from its natural position, fails.

I think you could simplify this to something like:

        Check that the buffer @start of @len bytes is mTHP-backed by @order
        folios wholly contained within the range.

        This requires that @buffer is aligned to @order and that every folio
        is fully contained head-to-tail.

        Returns: true if wholly mTHP backed, false otherwise.

> + */
> +bool is_range_backed_by_folio_orders(char *start, size_t len, int order,

is_range_mthp_backed() seems a lot clearer?

> +                                  int pagemap_fd, int kpageflags_fd)
> +{
> +     const unsigned long nr_pages = 1UL << order;
> +     const size_t window = nr_pages * psize();

folio_size seems clearer?

> +     char *vaddr;
> +
> +     if ((uintptr_t)start % window || len % window)
> +             return false;
> +
> +     for (vaddr = start; vaddr < start + len; vaddr += window) {
> +             unsigned long pfn = pagemap_get_pfn(pagemap_fd, vaddr);

NIT: can const-ify.

> +             unsigned long i;
> +
> +             /* Not present, or not mapping the folio head. */

'Or a tail page' maybe?

> +             if (pfn == -1UL || pfn % nr_pages)
> +                     return false;
> +
> +             for (i = 1; i < nr_pages; i++) {
> +                     if (pagemap_get_pfn(pagemap_fd, vaddr + i * psize()) !=
> +                         pfn + i)
> +                             return false;
> +             }

NIT: can drop the {}.

> +
> +             if (!is_backed_by_folio(vaddr, order, pagemap_fd,
> +                                     kpageflags_fd))
> +                     return false;
> +     }
> +
> +     return true;
> +}
> +
>  /* If `ioctls' non-NULL, the allowed ioctls will be returned into the var */
>  int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len,
>                             bool miss, bool wp, bool minor, uint64_t *ioctls)
> diff --git a/tools/testing/selftests/mm/vm_util.h 
> b/tools/testing/selftests/mm/vm_util.h
> index 56a28ce7d029..39dfb18dc10c 100644
> --- a/tools/testing/selftests/mm/vm_util.h
> +++ b/tools/testing/selftests/mm/vm_util.h
> @@ -99,6 +99,8 @@ int gather_folio_orders(char *vaddr_start, size_t len,
>               int pagemap_fd, int kpageflags_fd, int orders[], int nr_orders);
>  bool is_backed_by_folio(char *vaddr, int order, int pagemap_fd,
>                       int kpageflags_fd);
> +bool is_range_backed_by_folio_orders(char *start, size_t len, int order,
> +                                  int pagemap_fd, int kpageflags_fd);
>
>  int uffd_register(int uffd, void *addr, uint64_t len,
>                 bool miss, bool wp, bool minor);
> --
> 2.54.0
>

--
Cheers, Lorenzo

Reply via email to