diff mbox series

[v2,63/69] mm/hugetlb: Initialize the full bootmem hugepage in hugetlb code

Message ID 20260513132044.41690-17-songmuchun@bytedance.com (mailing list archive)
State Handled Elsewhere
Headers show
Series mm: Generalize HVO for HugeTLB and device DAX | expand

Commit Message

Muchun Song May 13, 2026, 1:20 p.m. UTC
Boot-time gigantic hugepages currently leave the head struct page to
the generic memmap initialization path while the HugeTLB code
initializes the remaining struct pages itself.

Mark the full hugepage noinit and initialize the head struct page in
hugetlb_folio_init_vmemmap() as well, so the whole compound-page setup
is handled in one place.

This can also reduce memblock metadata overhead when many boot-time
HugeTLB pages are reserved, because physically contiguous hugepages
can be covered by fewer noinit regions.

Signed-off-by: Muchun Song <songmuchun@bytedance.com>
---
 mm/hugetlb.c | 20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)
diff mbox series

Patch

diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 950b0fa3bc27..10f04fa95d43 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3112,15 +3112,7 @@  static bool __init alloc_bootmem_huge_page(struct hstate *h, int nid)
 		list_add_tail(&m->list, &huge_boot_pages[nid]);
 		m->flags |= HUGE_BOOTMEM_ZONES_VALID;
 		hugetlb_vmemmap_optimize_bootmem_page(m);
-		/*
-		 * Only initialize the head struct page in memmap_init_reserved_pages,
-		 * rest of the struct pages will be initialized by the HugeTLB
-		 * subsystem itself.
-		 * The head struct page is used to get folio information by the HugeTLB
-		 * subsystem like zone id and node id.
-		 */
-		memblock_reserved_mark_noinit(__pa((void *)m + PAGE_SIZE),
-				huge_page_size(h) - PAGE_SIZE);
+		memblock_reserved_mark_noinit(__pa(m), huge_page_size(h));
 	}
 
 	return true;
@@ -3129,16 +3121,13 @@  static bool __init alloc_bootmem_huge_page(struct hstate *h, int nid)
 static void __init hugetlb_folio_init_vmemmap(struct page *head, unsigned long pfn,
 		enum zone_type zone, int nid, unsigned int order, unsigned int nr_pages)
 {
-	int ret;
-
 	/*
 	 * This is an open-coded prep_compound_page() whereby we avoid
 	 * walking pages twice by initializing/preparing+freezing them in the
 	 * same go.
 	 */
-	__ClearPageReserved(head);
-	ret = page_ref_freeze(head, 1);
-	VM_BUG_ON(!ret);
+	__init_single_page(head, pfn, zone, nid);
+	set_page_count(head, 0);
 
 	__SetPageHead(head);
 	for (int i = 1; i < nr_pages; i++) {
@@ -3208,7 +3197,7 @@  static void __init gather_bootmem_prealloc_node(unsigned long nid)
 		struct folio *folio = (void *)page;
 		unsigned long pfn = PHYS_PFN(__pa(m));
 		unsigned long nr_pages = pages_per_huge_page(m->hstate);
-		enum zone_type zone = folio_zonenum(folio);
+		enum zone_type zone = zone_idx(pfn_to_zone(pfn, nid));
 
 		h = m->hstate;
 		/*
@@ -3220,7 +3209,6 @@  static void __init gather_bootmem_prealloc_node(unsigned long nid)
 		prev_h = h;
 
 		VM_BUG_ON(!hstate_is_gigantic(h));
-		WARN_ON(folio_ref_count(folio) != 1);
 
 		hugetlb_folio_init_vmemmap(page, pfn, zone, nid, huge_page_order(h),
 					   vmemmap_nr_struct_pages(pfn, nr_pages));