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

From: Muchun Song

Date: Thu Jul 02 2026 - 06:03:08 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 moves the initialization to the point where the shared tail page is
allocated and avoids relying on deferred handling in individual users.
The remaining deferred initialization in HugeTLB will be removed once it
switches to the section-based vmemmap optimization mechanism.

Signed-off-by: Muchun Song <songmuchun@xxxxxxxxxxxxx>
---
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 1d72283e179b..8931510c99c4 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -336,19 +336,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