Subject: Re: [PATCH 10/49] mm: move subsection_map_init() into sparse_init()

From: Mike Rapoport <[email-masked]>
Date: Tue, 28 Apr 2026 09:06:26 +0200

On Sun, Apr 05, 2026 at 08:52:01PM +0800, Muchun Song wrote:
> Move the initialization of the subsection map from free_area_init()
> into sparse_init(). This encapsulates the logic within the sparse
> memory initialization code.
> 
> Signed-off-by: Muchun Song <[email-masked]>

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

> ---
>  mm/internal.h       |  5 ++---
>  mm/mm_init.c        | 10 ++--------
>  mm/sparse-vmemmap.c | 11 ++++++++++-
>  mm/sparse.c         |  1 +
>  4 files changed, 15 insertions(+), 12 deletions(-)
> 
> diff --git a/mm/internal.h b/mm/internal.h
> index edb1c04d0617..d70075d0e788 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -1004,10 +1004,9 @@ static inline void sparse_init(void) {}
>   * mm/sparse-vmemmap.c
>   */
>  #ifdef CONFIG_SPARSEMEM_VMEMMAP
> -void sparse_init_subsection_map(unsigned long pfn, unsigned long nr_pages);
> +void sparse_init_subsection_map(void);
>  #else
> -static inline void sparse_init_subsection_map(unsigned long pfn,
> -		unsigned long nr_pages)
> +static inline void sparse_init_subsection_map(void)
>  {
>  }
>  #endif /* CONFIG_SPARSEMEM_VMEMMAP */

I side note: we might want to split out mm/sparse.h and also move some
declarations from include/linux/mmzone.h there.

> diff --git a/mm/mm_init.c b/mm/mm_init.c
> index a92c5053f63d..5ca4503e7622 100644
> --- a/mm/mm_init.c
> +++ b/mm/mm_init.c
> @@ -1857,18 +1857,12 @@ static void __init free_area_init(void)
>  			       (u64)zone_movable_pfn[i] << PAGE_SHIFT);
>  	}
>  
> -	/*
> -	 * Print out the early node map, and initialize the
> -	 * subsection-map relative to active online memory ranges to
> -	 * enable future "sub-section" extensions of the memory map.
> -	 */
> +	/* Print out the early node map. */
>  	pr_info("Early memory node ranges\n");
> -	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
> +	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid)
>  		pr_info("  node %3d: [mem %#018Lx-%#018Lx]\n", nid,
>  			(u64)start_pfn << PAGE_SHIFT,
>  			((u64)end_pfn << PAGE_SHIFT) - 1);
> -		sparse_init_subsection_map(start_pfn, end_pfn - start_pfn);
> -	}
>  
>  	/* Initialise every node */
>  	mminit_verify_pageflags_layout();
> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> index 0ee03db0b22f..b7201c235419 100644
> --- a/mm/sparse-vmemmap.c
> +++ b/mm/sparse-vmemmap.c
> @@ -603,7 +603,7 @@ static void subsection_mask_set(unsigned long *map, unsigned long pfn,
>  	bitmap_set(map, idx, end - idx + 1);
>  }
>  
> -void __init sparse_init_subsection_map(unsigned long pfn, unsigned long nr_pages)
> +static void __init sparse_init_subsection_map_range(unsigned long pfn, unsigned long nr_pages)
>  {
>  	int end_sec_nr = pfn_to_section_nr(pfn + nr_pages - 1);
>  	unsigned long nr, start_sec_nr = pfn_to_section_nr(pfn);
> @@ -626,6 +626,15 @@ void __init sparse_init_subsection_map(unsigned long pfn, unsigned long nr_pages
>  	}
>  }
>  
> +void __init sparse_init_subsection_map(void)
> +{
> +	int i, nid;
> +	unsigned long start, end;
> +
> +	for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid)
> +		sparse_init_subsection_map_range(start, end - start);
> +}
> +
>  #ifdef CONFIG_MEMORY_HOTPLUG
>  
>  /* Mark all memory sections within the pfn range as online */
> diff --git a/mm/sparse.c b/mm/sparse.c
> index 5c12b979a618..c7f91dc2e5b5 100644
> --- a/mm/sparse.c
> +++ b/mm/sparse.c
> @@ -424,5 +424,6 @@ void __init sparse_init(void)
>  	}
>  	/* cover the last node */
>  	sparse_init_nid(nid_begin, pnum_begin, pnum_end, map_count);
> +	sparse_init_subsection_map();
>  	vmemmap_populate_print_last();
>  }
> -- 
> 2.20.1
> 

-- 
Sincerely yours,
Mike.