Re: [PATCH v3 02/15] mm: introduce linear_anon_page_index()

"David Hildenbrand (Arm)" <[email protected]> Mon, 3 Aug 2026 11:34:32 +0200
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kvack.linux-mm
Message-ID <[email protected]>
On 7/29/26 18:48, Lorenzo Stoakes (ARM) wrote:
> This function provides the anonymous equivalent of linear_page_index(),
> instead offsetting based on the anonymous page offset of the VMA.
> 
> It is valid only for anonymous or MAP_PRIVATE file-backed mappings. It must
> not be called for shared file-backed mappings.
> 
> For pure anon VMAs, this will be equal to linear_page_index().
> 
> Assert that both of these invariants are true In linear_anon_page_index()
> and implement the algorithm in __linear_anon_page_index().
> 
> Note that MAP_PRIVATE-/dev/zero mappings will satisfy vma_is_anonymous()
> but not fulfill this invariant, so when asserting this we check
> vma->vm_file to account for this.
> 
> We do not update callsites yet, so no functional change intended.
> 
> Also const-ify vma_is_anonymous() to make it compatible with the
> const-ified linear_anon_page_index().
> 
> VMA userland tests are also updated accordingly.

In general looks good, some comments below.

> 
> Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]>
> ---
>  include/linux/mm.h              |  2 +-
>  include/linux/pagemap.h         | 42 +++++++++++++++++++++++++++++++++++++++++
>  tools/testing/vma/include/dup.h | 25 +++++++++++++++++++++++-
>  3 files changed, 67 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index df78847f5f07..64214191e7c6 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1556,7 +1556,7 @@ static inline void vma_desc_set_anonymous(struct vm_area_desc *desc)
>  	desc->vm_ops = NULL;
>  }
>  
> -static inline bool vma_is_anonymous(struct vm_area_struct *vma)
> +static inline bool vma_is_anonymous(const struct vm_area_struct *vma)
>  {
>  	return !vma->vm_ops;
>  }
> diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
> index c6fc783aaee5..259177544b03 100644
> --- a/include/linux/pagemap.h
> +++ b/include/linux/pagemap.h
> @@ -1101,6 +1101,48 @@ static inline pgoff_t linear_page_index(const struct vm_area_struct *vma,
>  	return pgoff;
>  }
>  
> +static inline pgoff_t __linear_anon_page_index(const struct vm_area_struct *vma,
> +					       const unsigned long address)

Nit Usual "two tab" comment (same below) :)

> +{
> +	pgoff_t pgoff;
> +
> +	pgoff = linear_page_delta(vma, address);
> +	pgoff += vma_start_anon_pgoff(vma);


I'd simply do

	return vma_start_anon_pgoff(vma) + linear_page_delta(vma, address);

> +	return pgoff;
> +}
> +
> +/**
> + * linear_anon_page_index() - Determine the absolute anonymous page offset of
> + * @address within @vma.
> + * @vma: An anonymous or MAP_PRIVATE file-backed VMA in which @address resides.
> + * @address: The address whose absolute page offset is required.
> + *
> + * This returns the anonymous page offset of @address, which is the page offset
> + * the address possessed at the time the VMA was first faulted.
> + *
> + * For anonymous mappings, this returns the same value as linear_page_index().
> + *
> + * For MAP_PRIVATE file-backed mappings, this returns the anonymous page offset
> + * of @address, which is the page offset the address possessed at the time the
> + * VMA was first faulted.
> + *
> + * It is not valid to call this function for shared file-backed mappings.
> + *
> + * Returns: The absolute anonymous page offset of @address within @vma.
> + */
> +static inline pgoff_t linear_anon_page_index(const struct vm_area_struct *vma,
> +					     const unsigned long address)

Dito.

> +{
> +	const pgoff_t pgoff = __linear_anon_page_index(vma, address);
> +
> +	VM_WARN_ON_ONCE(vma_test(vma, VMA_SHARED_BIT));

Could we test or COW mappings instead?

VM_WARN_ON_ONCE(!is_cow_mapping(vma));

Because we must never have anon folios is non-cow mappings.

[...]

> +static inline pgoff_t __linear_anon_page_index(const struct vm_area_struct *vma,
> +					       const unsigned long address)
> +{
> +	pgoff_t pgoff;
> +
> +	pgoff = linear_page_delta(vma, address);
> +	pgoff += vma_start_anon_pgoff(vma);
> +	return pgoff;
> +}

Same comment as above.

-- 
Cheers,

David