Re: [PATCH 3/5] mm: Rename __thp_get_unmapped_area to mm_get_unmapped_area_aligned

Peter Xu
2025-06-13T18:45:40Z

On Fri, Jun 13, 2025 at 04:36:57PM +0100, Lorenzo Stoakes wrote:
> On Fri, Jun 13, 2025 at 09:41:09AM -0400, Peter Xu wrote:
> > This function is pretty handy for any type of VMA to provide a size-aligned
> > VMA address when mmap(). Rename the function and export it.
>
> This isn't a great commit message, 'to provide a size-aligned VMA address when
> mmap()' is super unclear - do you mean 'to provide an unmapped address that is
> also aligned to the specified size'?

I sincerely don't know the difference, not a native speaker here..
Suggestions welcomed, I can update to whatever both of us agree on.

>
> I think you should also specify your motive, renaming and exporting something
> because it seems handy isn't sufficient justifiation.
>
> Also why would we need to export this? What modules might want to use this? I'm
> generally not a huge fan of exporting things unless we strictly have to.

It's one of the major reasons why I sent this together with the VFIO
patches. It'll be used in VFIO patches that is in the same series. I will
mention it in the commit message when repost.

>
> >
> > About the rename:
> >
> > - Dropping "THP" because it doesn't really have much to do with THP
> > internally.
>
> Well the function seems specifically tailored to the THP use. I think you'll
> need to further adjust this.

Actually.. it is almost exactly what I need so far. I can justify it below.

>
> >
> > - The suffix "_aligned" imply it is a helper to generate aligned virtual
> > address based on what is specified (which can be not PMD_SIZE).
>
> Ack this is sensible!
>
> >
> > Cc: Zi Yan <ziy@nvidia.com>
> > Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
> > Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com>
> > Cc: Ryan Roberts <ryan.roberts@arm.com>
> > Cc: Dev Jain <dev.jain@arm.com>
> > Cc: Barry Song <baohua@kernel.org>
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> > include/linux/huge_mm.h | 14 +++++++++++++-
> > mm/huge_memory.c | 6 ++++--
> > 2 files changed, 17 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
> > index 2f190c90192d..706488d92bb6 100644
> > --- a/include/linux/huge_mm.h
> > +++ b/include/linux/huge_mm.h
>
> Why are we keeping everything in huge_mm.h, huge_memory.c if this is being made
> generic?
>
> Surely this should be moved out into mm/mmap.c no?

No objections, but I suggest a separate discussion and patch submission
when the original function resides in huge_memory.c. Hope it's ok for you.

>
> > @@ -339,7 +339,10 @@ unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
> > unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
> > unsigned long len, unsigned long pgoff, unsigned long flags,
> > vm_flags_t vm_flags);
> > -
> > +unsigned long mm_get_unmapped_area_aligned(struct file *filp,
> > + unsigned long addr, unsigned long len,
> > + loff_t off, unsigned long flags, unsigned long size,
> > + vm_flags_t vm_flags);
>
> I echo Jason's comments about a kdoc and explanation of what this function does.
>
> > bool can_split_folio(struct folio *folio, int caller_pins, int *pextra_pins);
> > int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
> > unsigned int new_order);
> > @@ -543,6 +546,15 @@ thp_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
> > return 0;
> > }
> >
> > +static inline unsigned long
> > +mm_get_unmapped_area_aligned(struct file *filp,
> > + unsigned long addr, unsigned long len,
> > + loff_t off, unsigned long flags, unsigned long size,
> > + vm_flags_t vm_flags)
> > +{
> > + return 0;
> > +}
> > +
> > static inline bool
> > can_split_folio(struct folio *folio, int caller_pins, int *pextra_pins)
> > {
> > diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> > index 4734de1dc0ae..52f13a70562f 100644
> > --- a/mm/huge_memory.c
> > +++ b/mm/huge_memory.c
> > @@ -1088,7 +1088,7 @@ static inline bool is_transparent_hugepage(const struct folio *folio)
> > folio_test_large_rmappable(folio);
> > }
> >
> > -static unsigned long __thp_get_unmapped_area(struct file *filp,
> > +unsigned long mm_get_unmapped_area_aligned(struct file *filp,
> > unsigned long addr, unsigned long len,
> > loff_t off, unsigned long flags, unsigned long size,
> > vm_flags_t vm_flags)
> > @@ -1132,6 +1132,7 @@ static unsigned long __thp_get_unmapped_area(struct file *filp,
> > ret += off_sub;
> > return ret;
> > }
> > +EXPORT_SYMBOL_GPL(mm_get_unmapped_area_aligned);
>
> I'm not convinced about exporting this... shouldn't be export only if we
> explicitly have a user?
>
> I'd rather we didn't unless we needed to.
>
> >
> > unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
> > unsigned long len, unsigned long pgoff, unsigned long flags,
> > @@ -1140,7 +1141,8 @@ unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long add
> > unsigned long ret;
> > loff_t off = (loff_t)pgoff << PAGE_SHIFT;
> >
> > - ret = __thp_get_unmapped_area(filp, addr, len, off, flags, PMD_SIZE, vm_flags);
> > + ret = mm_get_unmapped_area_aligned(filp, addr, len, off, flags,
> > + PMD_SIZE, vm_flags);
> > if (ret)
> > return ret;
> >
> > --
> > 2.49.0
> >
>
> So, you don't touch the original function but there's stuff there I think we
> need to think about if this is generalised.
>
> E.g.:
>
> if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall())
> return 0;
>
> This still valid?

Yes. I want this feature (for VFIO) to not be enabled on 32bits, and not
enabled with compat syscals.

>
> /*
> * The failure might be due to length padding. The caller will retry
> * without the padding.
> */
> if (IS_ERR_VALUE(ret))
> return 0;
>
> This is assuming things the (currently single) caller will do, that is no longer
> an assumption you can make, especially if exported.

It's part of core function we want from a generic helper. We want to know
when the va allocation, after padded, would fail due to the padding. Then
the caller can decide what to do next. It needs to fail here properly.

>
> Actually you maybe want to abstract the whole of thp_get_unmapped_area_vmflags()
> no? As this has a fallback mode?
>
> /*
> * Do not try to align to THP boundary if allocation at the address
> * hint succeeds.
> */
> if (ret == addr)
> return addr;

This is not a fallback. This is when user specified a hint address (no
matter with / without MAP_FIXED), if that address works then we should
reuse that address, ignoring the alignment requirement from the driver.
This is exactly the behavior VFIO needs, and this should also be the
suggested behavior for whatever new drivers that would like to start using
this generic helper.

>
> What was that about this no longer being relevant to THP? :>)
>
> Are all of these 'return 0' cases expected by any sensible caller? It seems like
> it's a way for thp_get_unmapped_area_vmflags() to recognise when to fall back to
> non-aligned?

Hope above justfies everything. It's my intention to reuse everything
here. If you have any concern on any of the "return 0" cases in the
function being exported, please shoot, we can discuss.

Thanks,

--
Peter Xu