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 | <MW4PR11MB6936054EC741918CCFC6FDD6A3A32@MW4PR11MB6936.namprd11.prod.outlook.com> |
> -----Original Message----- > From: David Hildenbrand (Arm) <[email protected]> > Sent: Friday, August 21, 2026 1:46 AM > 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 > > >>> + 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. > > Ah, yeah. > > > > >> 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'd keep the for_each_valid_pfn() the outer loop. Hi David Do you mean the following approach? We use for_each_valid_pfn as the outer loop and, with VMEMMAP,check online PFNs in PAGES_PER_SUBSECTION chunks +#ifdef CONFIG_SPARSEMEM_VMEMMAP + const unsigned long chunk = PAGES_PER_SUBSECTION; +#else + const unsigned long chunk = epfn - spfn; +#endif + unsigned long pfn, next_chunk_pfn = spfn; + u64 pgcnt = 0, online_pgcnt = 0; + bool is_online = true; for_each_valid_pfn(pfn, spfn, epfn) { __init_single_page(pfn_to_page(pfn), pfn, zone, node); __SetPageReserved(pfn_to_page(pfn)); + + /* + * With VMEMMAP, subsection-sized holes can exist, and PFNs + * within these holes can fail pfn_to_online_page(). Without + * VMEMMAP, early sections only exist when actually online. + */ + if (IS_ENABLED(CONFIG_SPARSEMEM_VMEMMAP) && + pfn >= next_chunk_pfn) { + is_online = !!pfn_to_online_page(pfn); + next_chunk_pfn = min(pfn + chunk, epfn); + } + if (is_online) + online_pgcnt++; + Best Regards, Liu, Yuan > Cheers, > > David