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

From: Mike Rapoport <[email-masked]>
Date: Tue, 28 Apr 2026 08:56:48 +0200

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 <[email-masked]>

Acked-by: Mike Rapoport (Microsoft) <[email-masked]>

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