Skip to content

Commit 7f24cbc

Browse files
osalvadorvilardagaakpm00
authored andcommitted
mm/mmap: teach generic_get_unmapped_area{_topdown} to handle hugetlb mappings
Patch series "Unify hugetlb into arch_get_unmapped_area functions", v4. This is an attempt to get rid of a fair amount of duplicated code wrt. hugetlb and *get_unmapped_area* functions. HugeTLB registers a .get_unmapped_area function which gets called from __get_unmapped_area(). hugetlb_get_unmapped_area() is defined by a bunch of architectures and it also has a generic definition for those that do not define it. Short-long story is that there is a ton of duplicated code between specific hugetlb *_get_unmapped_area_* functions and mm-core functions, so we can do better by teaching arch_get_unmapped_area* functions how to deal with hugetlb mappings. Note that not a lot of things need to be taught though. hugetlb_get_unmapped_area, that gets called for hugetlb mappings, runs some sanity checks prior to calling mm_get_unmapped_area_vmflags(), so we do not need to that down the road in the respective {generic,arch}_get_unmapped_area* functions. More information can be found in the respective patches. LTP mmapstress hugetlb selftests were ran succesfully on: This patch (of 9): We want to stop special casing hugetlb mappings and make them go through generic channels, so teach generic_get_unmapped_area{_topdown} to handle those. The main difference is that we set info.align_mask for huge mappings. Link: https://lkml.kernel.org/r/20241007075037.267650-1-osalvador@suse.de Link: https://lkml.kernel.org/r/20241007075037.267650-2-osalvador@suse.de Signed-off-by: Oscar Salvador <osalvador@suse.de> Cc: David Hildenbrand <david@redhat.com> Cc: Donet Tom <donettom@linux.ibm.com> Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Muchun Song <muchun.song@linux.dev> Cc: Peter Xu <peterx@redhat.com> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 04f315a commit 7f24cbc

File tree

2 files changed

+14
-0
lines changed

2 files changed

+14
-0
lines changed

Diff for: include/linux/hugetlb.h

+10
Original file line numberDiff line numberDiff line change
@@ -1035,9 +1035,19 @@ void hugetlb_unregister_node(struct node *node);
10351035
*/
10361036
bool is_raw_hwpoison_page_in_hugepage(struct page *page);
10371037

1038+
static inline unsigned long huge_page_mask_align(struct file *file)
1039+
{
1040+
return PAGE_MASK & ~huge_page_mask(hstate_file(file));
1041+
}
1042+
10381043
#else /* CONFIG_HUGETLB_PAGE */
10391044
struct hstate {};
10401045

1046+
static inline unsigned long huge_page_mask_align(struct file *file)
1047+
{
1048+
return 0;
1049+
}
1050+
10411051
static inline struct hugepage_subpool *hugetlb_folio_subpool(struct folio *folio)
10421052
{
10431053
return NULL;

Diff for: mm/mmap.c

+4
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,8 @@ generic_get_unmapped_area(struct file *filp, unsigned long addr,
776776
info.low_limit = mm->mmap_base;
777777
info.high_limit = mmap_end;
778778
info.start_gap = stack_guard_placement(vm_flags);
779+
if (filp && is_file_hugepages(filp))
780+
info.align_mask = huge_page_mask_align(filp);
779781
return vm_unmapped_area(&info);
780782
}
781783

@@ -826,6 +828,8 @@ generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
826828
info.low_limit = PAGE_SIZE;
827829
info.high_limit = arch_get_mmap_base(addr, mm->mmap_base);
828830
info.start_gap = stack_guard_placement(vm_flags);
831+
if (filp && is_file_hugepages(filp))
832+
info.align_mask = huge_page_mask_align(filp);
829833
addr = vm_unmapped_area(&info);
830834

831835
/*

0 commit comments

Comments
 (0)