[PATCH 1/4] mm: Rename __thp_get_unmapped_area to mm_get_unmapped_area_aligned

From: Peter Xu
Date: Fri May 30 2025 - 12:45:55 EST


This function is handy to locate an unmapped region which is best aligned
to the specified alignment, taking whatever form of pgoff address space
into considerations.

Rename the function and make it more general for even non-THP use in follow
up patches. Dropping "THP" in the name because it doesn't have much to do
with THP internally. The suffix "_aligned" imply it is a helper to
generate aligned virtual address based on what is specified (which can be
not PMD_SIZE).

When at it, using check_add_overflow() helpers to verify the inputs to make
sure no overflow will happen.

Cc: Baolin Wang <baolin.wang@xxxxxxxxxxxxxxxxx>
Cc: Lorenzo Stoakes <lorenzo.stoakes@xxxxxxxxxx>
Cc: "Liam R. Howlett" <Liam.Howlett@xxxxxxxxxx>
Cc: Ryan Roberts <ryan.roberts@xxxxxxx>
Cc: Dev Jain <dev.jain@xxxxxxx>
Cc: Barry Song <baohua@xxxxxxxxxx>
Signed-off-by: Peter Xu <peterx@xxxxxxxxxx>
---
mm/huge_memory.c | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 4734de1dc0ae..885b5845dbba 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1088,23 +1088,28 @@ 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,
+static 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,
+ loff_t off, unsigned long flags, unsigned long align,
vm_flags_t vm_flags)
{
- loff_t off_end = off + len;
- loff_t off_align = round_up(off, size);
+ loff_t off_end;
+ loff_t off_align = round_up(off, align);
unsigned long len_pad, ret, off_sub;

if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall())
return 0;

- if (off_end <= off_align || (off_end - off_align) < size)
+ /* Can't use the overflow API, do manual check for now */
+ if (off_align < off)
return 0;
-
- len_pad = len + size;
- if (len_pad < len || (off + len_pad) < off)
+ if (check_add_overflow(off, len, &off_end))
+ return 0;
+ if (off_end <= off_align || (off_end - off_align) < align)
+ return 0;
+ if (check_add_overflow(len, align, &len_pad))
+ return 0;
+ if ((off + len_pad) < off)
return 0;

ret = mm_get_unmapped_area_vmflags(current->mm, filp, addr, len_pad,
@@ -1118,16 +1123,16 @@ static unsigned long __thp_get_unmapped_area(struct file *filp,
return 0;

/*
- * Do not try to align to THP boundary if allocation at the address
+ * Do not try to provide alignment if allocation at the address
* hint succeeds.
*/
if (ret == addr)
return addr;

- off_sub = (off - ret) & (size - 1);
+ off_sub = (off - ret) & (align - 1);

if (test_bit(MMF_TOPDOWN, &current->mm->flags) && !off_sub)
- return ret + size;
+ return ret + align;

ret += off_sub;
return ret;
@@ -1140,7 +1145,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