Re: [PATCH v3 3/9] mm: move anon-exclusive batch helper to rmap.h

From: Barry Song

Date: Thu Sep 24 2026 - 17:07:38 EST


On Thu, Sep 24, 2026 at 9:11 PM Dev Jain <dev.jain@xxxxxxx> wrote:
>
> In preparation for optimizing large folio unmapping, we need to reuse
> the page_anon_exclusive_batch helper in rmap.c and rmap.h and obey the
> existing use in mprotect.c .
>
> Therefore, move it from mprotect.c to rmap.h.
>
> While at it, change return type, start_idx and max_len to unsigned long
> type for future proofing against THP support at >= PUD level. Also
> shorten expected_anon_exclusive -> anon_exclusive.

I really think the `expected` prefix makes the semantics clearer, so I
don't think it's necessary to remove it.

If you really find it too long, maybe just use
`expected_exclusive`, since we're already in the anon context and
know that it is definitely anon.

Another option might be to make `*exclusive` an output parameter.
Then we wouldn't need to call
`expected_anon_exclusive = PageAnonExclusive(first_page + batch_idx);`
in the caller.

static __always_inline unsigned long
page_anon_exclusive_batch(unsigned long start_idx,
unsigned long max_len, struct page *first_page, bool *exclusive)

>
> Signed-off-by: Dev Jain <dev.jain@xxxxxxx>

Otherwise, the patch looks good to me.

Reviewed-by: Barry Song <baohua@xxxxxxxxxx>

> ---
> include/linux/rmap.h | 17 +++++++++++++++++
> mm/mprotect.c | 18 +-----------------
> 2 files changed, 18 insertions(+), 17 deletions(-)
>
> diff --git a/include/linux/rmap.h b/include/linux/rmap.h
> index 74cca0e3c7264..62ef511a6175a 100644
> --- a/include/linux/rmap.h
> +++ b/include/linux/rmap.h
> @@ -106,6 +106,23 @@ enum ttu_flags {
>
> #ifdef CONFIG_MMU
>
> +/*
> + * Get max length of consecutive PTEs pointing to PageAnonExclusive() pages or
> + * !PageAnonExclusive() pages, starting from start_idx. Caller must enforce
> + * that the PTEs point to consecutive pages of the same anon large folio.
> + */
> +static __always_inline unsigned long page_anon_exclusive_batch(unsigned long start_idx,
> + unsigned long max_len, struct page *first_page, bool anon_exclusive)
> +{
> + unsigned long idx;
> +
> + for (idx = start_idx + 1; idx < start_idx + max_len; ++idx) {
> + if (anon_exclusive != PageAnonExclusive(first_page + idx))
> + break;
> + }
> + return idx - start_idx;
> +}
> +

Thanks
Barry