[PATCH] fixup! mm/sparse-vmemmap: switch device DAX to shared tail vmemmap pages

From: Muchun Song

Date: Mon Sep 28 2026 - 00:42:16 EST


Each PTE mapping the shared device DAX tail page takes a page reference.
A sufficiently large range could therefore cycle the reference count back
to zero if population were allowed to continue after it became
non-positive.

Use try_get_page() so further mappings fail once the reference count is no
longer positive. The section population error path tears down mappings
created for the failed section, while the warning makes this currently
impractical limit visible.

Signed-off-by: Muchun Song <songmuchun@xxxxxxxxxxxxx>
---
mm/sparse-vmemmap.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index b617ff1b985d..66de04f8863b 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -278,14 +278,18 @@ static pte_t * __meminit vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, in
/*
* When a PTE/PMD entry is freed from the init_mm
* there's a free_pages() call to this page allocated
- * above. Thus this get_page() is paired with the
+ * above. Thus this try_get_page() is paired with the
* put_page_testzero() on the freeing path.
* This can only called by certain ZONE_DEVICE path,
* and through vmemmap_populate_compound_pages() when
* slab is available.
+ *
+ * Use try_get_page() to prevent the shared page refcount
+ * from overflowing.
*/
- if (flags & VMEMMAP_POPULATE_DAX)
- get_page(pfn_to_page(ptpfn));
+ if ((flags & VMEMMAP_POPULATE_DAX) &&
+ !try_get_page(pfn_to_page(ptpfn)))
+ return NULL;
}
entry = pfn_pte(ptpfn, PAGE_KERNEL);
set_pte_at(&init_mm, addr, pte, entry);
--
2.54.0