[PATCH v6 04/17] mm/sparse-vmemmap: initialize shared tail vmemmap pages on allocation

From: Muchun Song

Date: Thu Sep 10 2026 - 02:36:36 EST


The shared tail vmemmap page allocated in vmemmap_get_tail() used to be
left uninitialized, because memmap_init_range() would later overwrite
it. That forced users such as HugeTLB to defer the initialization to
their own setup paths.

Now that memmap_init_range() skips shared tail vmemmap pages, initialize
them immediately in vmemmap_get_tail() with init_compound_tail()
instead.

This adds initialization at the point where the shared tail page is
allocated. The existing HugeTLB initialization remains necessary until
the compound page order is set and memmap_init_range() starts skipping
shared tails. It is removed when HugeTLB switches to the section-based
mechanism.

Signed-off-by: Muchun Song <songmuchun@xxxxxxxxxxxxx>
Acked-by: Mike Rapoport (Microsoft) <rppt@xxxxxxxxxx>
Acked-by: Qi Zheng <qi.zheng@xxxxxxxxx>
---
v6:
- Clarify the timing of shared tail page initialization removal
(suggested by David Hildenbrand)
- Collect Acked-by from Mike Rapoport and Qi Zheng
---
mm/sparse-vmemmap.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index aa6a4a2fae98..107215cf8488 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -338,19 +338,11 @@ static __meminit struct page *vmemmap_get_tail(unsigned int order, struct zone *
tail = zone->vmemmap_tails[idx];
if (tail)
return tail;
-
- /*
- * Only allocate the page, but do not initialize it.
- *
- * Any initialization done here will be overwritten by memmap_init().
- *
- * hugetlb_bootmem_struct_page_init() will take care of initialization
- * after memmap_init().
- */
-
p = vmemmap_alloc_block_zero(PAGE_SIZE, node);
if (!p)
return NULL;
+ for (int i = 0; i < PAGE_SIZE / sizeof(struct page); i++)
+ init_compound_tail(p + i, NULL, order, zone);

tail = virt_to_page(p);
zone->vmemmap_tails[idx] = tail;
--
2.54.0