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

Mike Rapoport
2026-04-28T06:57:02Z

On Sun, Apr 05, 2026 at 08:52:00PM +0800, Muchun Song wrote:
> 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>

Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

> ---
> 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);

Please consider using memblock_alloc_or_panic() in sparse_usage_init(), it
would simplify the code even more.

> 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
>

--
Sincerely yours,
Mike.