From: "David Hildenbrand (Arm)" <david@kernel.org>
To: "Liu, Yuan1" <yuan1.liu@intel.com>,
Oscar Salvador <osalvador@suse.de>,
Mike Rapoport <rppt@kernel.org>,
Wei Yang <richard.weiyang@gmail.com>
Cc: "linux-mm@kvack.org" <linux-mm@kvack.org>,
"Zou, Nanhai" <nanhai.zou@intel.com>,
Chen Zhang <zhangchen.kidd@jd.com>,
"Zeng, Jason" <jason.zeng@intel.com>,
"Chen, Yu C" <yu.c.chen@intel.com>,
"Deng, Pan" <pan.deng@intel.com>,
"Li, Tianyou" <tianyou.li@intel.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v7 2/2] mm/memory_hotplug: optimize zone contiguous check when changing pfn range
Date: Wed, 26 Aug 2026 11:06:26 +0200 [thread overview]
Message-ID: <819cc4b4-1855-4dbc-adb4-3b18d6fa2924@kernel.org> (raw)
In-Reply-To: <MW4PR11MB6936054EC741918CCFC6FDD6A3A32@MW4PR11MB6936.namprd11.prod.outlook.com>
On 8/21/26 05:17, Liu, Yuan1 wrote:
>> -----Original Message-----
>> From: David Hildenbrand (Arm) <david@kernel.org>
>> Sent: Friday, August 21, 2026 1:46 AM
>> To: Liu, Yuan1 <yuan1.liu@intel.com>; Oscar Salvador <osalvador@suse.de>;
>> Mike Rapoport <rppt@kernel.org>; Wei Yang <richard.weiyang@gmail.com>
>> Cc: linux-mm@kvack.org; Zou, Nanhai <nanhai.zou@intel.com>; Chen Zhang
>> <zhangchen.kidd@jd.com>; Zeng, Jason <jason.zeng@intel.com>; Chen, Yu C
>> <yu.c.chen@intel.com>; Deng, Pan <pan.deng@intel.com>; Li, Tianyou
>> <tianyou.li@intel.com>; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH v7 2/2] mm/memory_hotplug: optimize zone contiguous
>> check when changing pfn range
>>
>>>
>>> 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.
>>
>>>
>> until
>> actually
>>>
>>> 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++;
> +
It's hard to get it any cleaner. I was wondering whether we should just have a separate
for_each_online_pfn() call afterwards, but that's also not ideal.
I was wondering whether we should also just use pfn_section_valid() directly.
Something like the following:
diff --git a/mm/mm_init.c b/mm/mm_init.c
index e9c4204b73adb..cc7d55a71a060 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -838,22 +838,39 @@ overlap_memmap_init(unsigned long zone, unsigned long *pfn)
* 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 next_chunk_pfn __maybe_unused = spfn;
unsigned long pfn;
- u64 pgcnt = 0;
+ u64 online_pgcnt = 0, 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));
pgcnt++;
+
+ /*
+ * With vmemmap, at this stage all pages in an early section
+ * have a valid memmap and are marked as online. However, only
+ * subsections in the subsection map are actually online.
+ */
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+ if (pfn >= next_chunk_pfn) {
+ is_online = pfn_section_valid(__pfn_to_section(pfn), pfn);
+ next_chunk_pfn = min(SUBSECTION_ALIGN_UP(pfn + 1), epfn);
+ }
+#endif
+ if (is_online)
+ online_pgcnt++;
}
if (pgcnt)
pr_info("On node %d, zone %s: %lld pages in unavailable ranges\n",
node, zone_names[zone], pgcnt);
+ return online_pgcnt;
}
/*
I'd love to avoid any CONFIG_SPARSEMEM_VMEMMAP, but that's hard as well :)
--
Cheers,
David
next prev parent reply other threads:[~2026-08-26 9:06 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 8:57 [PATCH v7 0/2] mm/memory_hotplug: optimize zone contiguous check when changing pfn range Yuan Liu
2026-08-18 8:57 ` [PATCH v7 1/2] mm/memory_hotplug: make shrink_zone_span() more robust Yuan Liu
2026-08-20 12:52 ` Liu, Yuan1
2026-08-21 3:14 ` Wei Yang
2026-08-21 9:32 ` David Hildenbrand (Arm)
2026-08-18 8:57 ` [PATCH v7 2/2] mm/memory_hotplug: optimize zone contiguous check when changing pfn range Yuan Liu
2026-08-19 14:56 ` Mike Rapoport
2026-08-19 15:43 ` David Hildenbrand (Arm)
2026-08-19 15:53 ` David Hildenbrand (Arm)
2026-08-20 13:21 ` Liu, Yuan1
2026-08-20 17:46 ` David Hildenbrand (Arm)
2026-08-21 3:17 ` Liu, Yuan1
2026-08-26 9:06 ` David Hildenbrand (Arm) [this message]
2026-08-27 8:33 ` Liu, Yuan1
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=819cc4b4-1855-4dbc-adb4-3b18d6fa2924@kernel.org \
--to=david@kernel.org \
--cc=jason.zeng@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=nanhai.zou@intel.com \
--cc=osalvador@suse.de \
--cc=pan.deng@intel.com \
--cc=richard.weiyang@gmail.com \
--cc=rppt@kernel.org \
--cc=tianyou.li@intel.com \
--cc=yu.c.chen@intel.com \
--cc=yuan1.liu@intel.com \
--cc=zhangchen.kidd@jd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.