[PATCH 09/49] mm: panic on memory allocation failure in sparse_init_nid()

Muchun Song
2026-04-05T12:54:24Z

When vmemmap pages allocation or usemap allocation fails, sparse_init_nid()
currently only marks the corresponding section as non-present. However,
subsequent code like memmap_init() iterating over PFNs does not check for
non-present sections, leading to invalid memory access (additional,
subsection_map_init() accessing the unallocated usemap as well).

It is complex to audit and fix all boot-time PFN iterators to handle these
partially initialized sections correctly. Since vmemmap and usemap allocation
failures are extremely rare during early boot, the more appropriate approach
is to expose the problem as early as possible.

Therefore, use BUG_ON() to panic immediately if allocation fails, instead of
attempting a partial recovery that leads to obscure crashes later.

Signed-off-by: Muchun Song <songmuchun@bytedance.com>
---
mm/sparse.c | 37 ++++++++-----------------------------
1 file changed, 8 insertions(+), 29 deletions(-)

diff --git a/mm/sparse.c b/mm/sparse.c
index effdac6b0ab1..5c12b979a618 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -354,19 +354,15 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
unsigned long map_count)
{
unsigned long pnum;
- struct page *map;
- struct mem_section *ms;
-
- if (sparse_usage_init(nid, map_count)) {
- pr_err("%s: node[%d] usemap allocation failed", __func__, nid);
- goto failed;
- }

+ if (sparse_usage_init(nid, map_count))
+ panic("The node[%d] usemap allocation failed\n", nid);
sparse_buffer_init(map_count * section_map_size(), nid);

sparse_vmemmap_init_nid_early(nid);

for_each_present_section_nr(pnum_begin, pnum) {
+ struct mem_section *ms;
unsigned long pfn = section_nr_to_pfn(pnum);

if (pnum >= pnum_end)
@@ -374,16 +370,12 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin,

ms = __nr_to_section(pnum);
if (!preinited_vmemmap_section(ms)) {
+ struct page *map;
+
map = __populate_section_memmap(pfn, PAGES_PER_SECTION,
- nid, NULL, NULL);
- if (!map) {
- pr_err("%s: node[%d] memory map backing failed. Some memory will not be available.",
- __func__, nid);
- pnum_begin = pnum;
- sparse_usage_fini();
- sparse_buffer_fini();
- goto failed;
- }
+ nid, NULL, NULL);
+ if (!map)
+ panic("Populate section (%ld) on node[%d] failed\n", pnum, nid);
memmap_boot_pages_add(DIV_ROUND_UP(PAGES_PER_SECTION * sizeof(struct page),
PAGE_SIZE));
sparse_init_early_section(nid, map, pnum, 0);
@@ -391,19 +383,6 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
}
sparse_usage_fini();
sparse_buffer_fini();
- return;
-failed:
- /*
- * We failed to allocate, mark all the following pnums as not present,
- * except the ones already initialized earlier.
- */
- for_each_present_section_nr(pnum_begin, pnum) {
- if (pnum >= pnum_end)
- break;
- ms = __nr_to_section(pnum);
- if (!preinited_vmemmap_section(ms))
- ms->section_mem_map = 0;
- }
}

/*
--
2.20.1