RE: [PATCH v7 2/2] mm/memory_hotplug: optimize zone contiguous check when changing pfn range

"Liu, Yuan1" <[email protected]>
Newsgroups org.kvack.linux-mm,org.kernel.vger.linux-kernel
Message-ID <MW4PR11MB69369259EB8B2FDF237B863AA3A42@MW4PR11MB6936.namprd11.prod.outlook.com>
> -----Original Message-----
> From: David Hildenbrand (Arm) <[email protected]>
> Sent: Wednesday, August 19, 2026 11:54 PM
> To: Liu, Yuan1 <[email protected]>; Oscar Salvador <[email protected]>;
> Mike Rapoport <[email protected]>; Wei Yang <[email protected]>
> Cc: [email protected]; Zou, Nanhai <[email protected]>; Chen Zhang
> <[email protected]>; Zeng, Jason <[email protected]>; Chen, Yu C
> <[email protected]>; Deng, Pan <[email protected]>; Li, Tianyou
> <[email protected]>; [email protected]
> Subject: Re: [PATCH v7 2/2] mm/memory_hotplug: optimize zone contiguous
> check when changing pfn range
> 
> 
> >  /*
> >   * Only struct pages that correspond to ranges defined by
> memblock.memory
> >   * are zeroed and initialized by going through __init_single_page()
> during
> > @@ -822,22 +844,27 @@ void __meminit init_deferred_page(unsigned long
> pfn, int nid)
> >   *   zone/node above the hole except for the trailing pages in the last
> >   *   section that will be appended to the zone/node below.
> >   */
> > -static void __init init_unavailable_range(unsigned long spfn,
> > -					  unsigned long epfn,
> > -					  int zone, int node)
> > +static unsigned long __init init_unavailable_range(unsigned long spfn,
> > +						   unsigned long epfn,
> > +						   int zone, int node)
> >  {
> >  	unsigned long pfn;
> > -	u64 pgcnt = 0;
> > +	u64 pgcnt = 0, online_pgcnt = 0;
> > +	unsigned long last_subsection = -1;
> > +	bool is_online = false;
> >
> >  	for_each_valid_pfn(pfn, spfn, epfn) {
> >  		__init_single_page(pfn_to_page(pfn), pfn, zone, node);
> >  		__SetPageReserved(pfn_to_page(pfn));
> > +		if (unavailable_pfn_is_online(pfn, &last_subsection,
> &is_online))
> > +			online_pgcnt++;
> 
> Can we avoid these helpers?
> 
> 		const unsigned long subsection = pfn & PAGE_SUBSECTION_MASK;
> 
> 		/* We can have section-sized online holes with VMEMMAP. */
> 		if (IS_ENMABLED(CONFIG_SPARSEMEM_VMEMMAP) &&
> 		    subsection != last_subsection) {
> 			is_online = pfn_to_online_page(pfn);
> 			last_subsection = subsection;
> 		}
> 		if (is_online)
> 			online_pgcnt++;

I think there may be an issue here: PAGE_SUBSECTION_MASK is not
defined when CONFIG_FLATMEM is enabled, which would result in a
build failure.

> An alternative is an inner loop that just walks in SUBSECTION chunks until
> epfn.
> That would probably be even cleaner and faster.
> 
> I remember !vmemmap always only has early sections when they are actually
> online. We could extent the comment to clarify that.

Hi David

What about the following approach? It removes the helper and changes
the per-PFN online check to a per-chunk check.

+       u64 pgcnt = 0, online_pgcnt = 0;
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+       const unsigned long chunk = PAGES_PER_SUBSECTION;
+#else
+       const unsigned long chunk = epfn - spfn;
+#endif

-       for_each_valid_pfn(pfn, spfn, epfn) {
-               __init_single_page(pfn_to_page(pfn), pfn, zone, node);
-               __SetPageReserved(pfn_to_page(pfn));
-               pgcnt++;
+       /*
+        * With VMEMMAP, subsection-sized holes can exist, and PFNs within
+        * these holes can fail pfn_to_online_page(). Without VMEMMAP, we
+        * always only have early sections when they are actually online.
+        */
+       for (pfn = spfn; pfn < epfn; pfn += chunk) {
+               const unsigned long chunk_epfn = min(pfn + chunk, epfn);
+               const bool is_online = !IS_ENABLED(CONFIG_SPARSEMEM_VMEMMAP) ||
+                                      pfn_to_online_page(pfn);
+               unsigned long p;
+
+               for_each_valid_pfn(p, pfn, chunk_epfn) {
+                       __init_single_page(pfn_to_page(p), p, zone, node);
+                       __SetPageReserved(pfn_to_page(p));
+                       if (is_online)
+                               online_pgcnt++;
+                       pgcnt++;
+               }
 
> (I have patches to clean that init code up)
> 
> 
> --
> Cheers,
> 
> David
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.