From: Yuan Liu <yuan1.liu@intel.com>
set_zone_contiguous() uses __pageblock_pfn_to_page() to detect
pageblocks that either do not exist (hole) or that do not belong
to the same zone.
__pageblock_pfn_to_page(), however, relies on pfn_to_online_page(),
effectively always returning NULL for memory ranges that were not
onlined yet. So when called on a range-to-be-onlined, it indicates
a memory hole to set_zone_contiguous().
Consequently, the set_zone_contiguous() call in move_pfn_range_to_zone(),
which happens early during memory onlining, will never detect a
zone as being contiguous. Bad.
To fix the issue, move the set_zone_contiguous() call to a later
stage in memory onlining, where pfn_to_online_page() will succeed:
after we mark the memory sections to be online.
Fixes: 2d070eab2e82 ("mm: consider zone which is not fully populated to have holes")
Cc: Michal Hocko <mhocko@suse.com>
Reviewed-by: Nanhai Zou <nanhai.zou@intel.com>
Signed-off-by: Yuan Liu <yuan1.liu@intel.com>
Signed-off-by: Tianyou Li <tianyou.li@intel.com>
---
mm/memory_hotplug.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index a63ec679d861..c8f492b5daf0 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -782,8 +782,6 @@ void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
memmap_init_range(nr_pages, nid, zone_idx(zone), start_pfn, 0,
MEMINIT_HOTPLUG, altmap, migratetype,
isolate_pageblock);
-
- set_zone_contiguous(zone);
}
struct auto_movable_stats {
@@ -1205,6 +1203,13 @@ int online_pages(unsigned long pfn, unsigned long nr_pages,
}
online_pages_range(pfn, nr_pages);
+
+ /*
+ * Now that the ranges are indicated as online, check whether the whole
+ * zone is contiguous.
+ */
+ set_zone_contiguous(zone);
+
adjust_present_page_count(pfn_to_page(pfn), group, nr_pages);
if (node_arg.nid >= 0)
--
2.47.1
Hi,
On Tue, Jan 20, 2026 at 10:33:44PM +0800, Tianyou Li wrote:
> From: Yuan Liu <yuan1.liu@intel.com>
>
> set_zone_contiguous() uses __pageblock_pfn_to_page() to detect
> pageblocks that either do not exist (hole) or that do not belong
> to the same zone.
>
> __pageblock_pfn_to_page(), however, relies on pfn_to_online_page(),
> effectively always returning NULL for memory ranges that were not
> onlined yet. So when called on a range-to-be-onlined, it indicates
> a memory hole to set_zone_contiguous().
>
> Consequently, the set_zone_contiguous() call in move_pfn_range_to_zone(),
> which happens early during memory onlining, will never detect a
> zone as being contiguous. Bad.
>
> To fix the issue, move the set_zone_contiguous() call to a later
> stage in memory onlining, where pfn_to_online_page() will succeed:
> after we mark the memory sections to be online.
>
> Fixes: 2d070eab2e82 ("mm: consider zone which is not fully populated to have holes")
cc stable@ perhaps?
> Cc: Michal Hocko <mhocko@suse.com>
> Reviewed-by: Nanhai Zou <nanhai.zou@intel.com>
> Signed-off-by: Yuan Liu <yuan1.liu@intel.com>
> Signed-off-by: Tianyou Li <tianyou.li@intel.com>
> ---
> mm/memory_hotplug.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index a63ec679d861..c8f492b5daf0 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -782,8 +782,6 @@ void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
> memmap_init_range(nr_pages, nid, zone_idx(zone), start_pfn, 0,
> MEMINIT_HOTPLUG, altmap, migratetype,
> isolate_pageblock);
> -
> - set_zone_contiguous(zone);
move_pfn_range_to_zone() is also called from memremap::pagemap_range().
Shouldn't we add set_zone_contiguous() there as well?
> }
>
> struct auto_movable_stats {
> @@ -1205,6 +1203,13 @@ int online_pages(unsigned long pfn, unsigned long nr_pages,
> }
>
> online_pages_range(pfn, nr_pages);
> +
> + /*
> + * Now that the ranges are indicated as online, check whether the whole
> + * zone is contiguous.
> + */
> + set_zone_contiguous(zone);
> +
> adjust_present_page_count(pfn_to_page(pfn), group, nr_pages);
>
> if (node_arg.nid >= 0)
> --
> 2.47.1
>
--
Sincerely yours,
Mike.
Appreciated for your review, Mike.
On 1/22/2026 7:16 PM, Mike Rapoport wrote:
> Hi,
>
> On Tue, Jan 20, 2026 at 10:33:44PM +0800, Tianyou Li wrote:
>> From: Yuan Liu <yuan1.liu@intel.com>
>>
>> set_zone_contiguous() uses __pageblock_pfn_to_page() to detect
>> pageblocks that either do not exist (hole) or that do not belong
>> to the same zone.
>>
>> __pageblock_pfn_to_page(), however, relies on pfn_to_online_page(),
>> effectively always returning NULL for memory ranges that were not
>> onlined yet. So when called on a range-to-be-onlined, it indicates
>> a memory hole to set_zone_contiguous().
>>
>> Consequently, the set_zone_contiguous() call in move_pfn_range_to_zone(),
>> which happens early during memory onlining, will never detect a
>> zone as being contiguous. Bad.
>>
>> To fix the issue, move the set_zone_contiguous() call to a later
>> stage in memory onlining, where pfn_to_online_page() will succeed:
>> after we mark the memory sections to be online.
>>
>> Fixes: 2d070eab2e82 ("mm: consider zone which is not fully populated to have holes")
> cc stable@ perhaps?
Yes, will do. Thanks.
>
>> Cc: Michal Hocko <mhocko@suse.com>
>> Reviewed-by: Nanhai Zou <nanhai.zou@intel.com>
>> Signed-off-by: Yuan Liu <yuan1.liu@intel.com>
>> Signed-off-by: Tianyou Li <tianyou.li@intel.com>
>> ---
>> mm/memory_hotplug.c | 9 +++++++--
>> 1 file changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
>> index a63ec679d861..c8f492b5daf0 100644
>> --- a/mm/memory_hotplug.c
>> +++ b/mm/memory_hotplug.c
>> @@ -782,8 +782,6 @@ void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
>> memmap_init_range(nr_pages, nid, zone_idx(zone), start_pfn, 0,
>> MEMINIT_HOTPLUG, altmap, migratetype,
>> isolate_pageblock);
>> -
>> - set_zone_contiguous(zone);
> move_pfn_range_to_zone() is also called from memremap::pagemap_range().
> Shouldn't we add set_zone_contiguous() there as well?
I did not find the place where the online_pages was invoked along path
of the memremap:pagemap_range() function. Would there be other functions
to online the pages remapped? Much appreciated for the guidance.
I leave the zone contiguous state remains the same as the optimization
not took place in case any unexpected behavior.
>> }
>>
>> struct auto_movable_stats {
>> @@ -1205,6 +1203,13 @@ int online_pages(unsigned long pfn, unsigned long nr_pages,
>> }
>>
>> online_pages_range(pfn, nr_pages);
>> +
>> + /*
>> + * Now that the ranges are indicated as online, check whether the whole
>> + * zone is contiguous.
>> + */
>> + set_zone_contiguous(zone);
>> +
>> adjust_present_page_count(pfn_to_page(pfn), group, nr_pages);
>>
>> if (node_arg.nid >= 0)
>> --
>> 2.47.1
>>
Hi, On Sat, Jan 24, 2026 at 08:18:39PM +0800, Li, Tianyou wrote: > On 1/22/2026 7:16 PM, Mike Rapoport wrote: > > On Tue, Jan 20, 2026 at 10:33:44PM +0800, Tianyou Li wrote: > > > diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c > > > index a63ec679d861..c8f492b5daf0 100644 > > > --- a/mm/memory_hotplug.c > > > +++ b/mm/memory_hotplug.c > > > @@ -782,8 +782,6 @@ void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn, > > > memmap_init_range(nr_pages, nid, zone_idx(zone), start_pfn, 0, > > > MEMINIT_HOTPLUG, altmap, migratetype, > > > isolate_pageblock); > > > - > > > - set_zone_contiguous(zone); > > move_pfn_range_to_zone() is also called from memremap::pagemap_range(). > > Shouldn't we add set_zone_contiguous() there as well? > > I did not find the place where the online_pages was invoked along path of > the memremap:pagemap_range() function. Would there be other functions to > online the pages remapped? Much appreciated for the guidance. Currently when we do memremap_pages() we have memremap_pages() -> pagemap_range() -> move_pfn_range_to_zone() -> set_zone_contiguous(); Once set_zone_contiguous() is moved out from move_pfn_range_to_zone(), memremap_pages() path never calls it. I'm not sure if the pages added in memremap_pages() are online, but to keep it's current behaviour I think it should call set_zone_contiguous() explicitly. -- Sincerely yours, Mike.
On 1/27/2026 2:53 PM, Mike Rapoport wrote: > Hi, > > On Sat, Jan 24, 2026 at 08:18:39PM +0800, Li, Tianyou wrote: >> On 1/22/2026 7:16 PM, Mike Rapoport wrote: >>> On Tue, Jan 20, 2026 at 10:33:44PM +0800, Tianyou Li wrote: >>>> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c >>>> index a63ec679d861..c8f492b5daf0 100644 >>>> --- a/mm/memory_hotplug.c >>>> +++ b/mm/memory_hotplug.c >>>> @@ -782,8 +782,6 @@ void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn, >>>> memmap_init_range(nr_pages, nid, zone_idx(zone), start_pfn, 0, >>>> MEMINIT_HOTPLUG, altmap, migratetype, >>>> isolate_pageblock); >>>> - >>>> - set_zone_contiguous(zone); >>> move_pfn_range_to_zone() is also called from memremap::pagemap_range(). >>> Shouldn't we add set_zone_contiguous() there as well? >> I did not find the place where the online_pages was invoked along path of >> the memremap:pagemap_range() function. Would there be other functions to >> online the pages remapped? Much appreciated for the guidance. > Currently when we do memremap_pages() we have > > memremap_pages() -> > pagemap_range() -> > move_pfn_range_to_zone() -> > set_zone_contiguous(); > > Once set_zone_contiguous() is moved out from move_pfn_range_to_zone(), > memremap_pages() path never calls it. > I'm not sure if the pages added in memremap_pages() are online, but to keep > it's current behaviour I think it should call set_zone_contiguous() > explicitly. Thanks Mike. It's doable for me to add such a line. I am worried about place a set_zone_contiguous() will not add any meaningful value. Per my understanding, the zone contiguous will remain as false because the page is not online. Regards, Tianyou
On Sat, 24 Jan 2026 20:18:39 +0800 "Li, Tianyou" <tianyou.li@intel.com> wrote: > > cc stable@ perhaps? > > Yes, will do. Thanks. Please separate backportable patches from those which target the next merge window. They have different timing and take different routes into mainline. Thanks.
On 1/27/2026 5:58 AM, Andrew Morton wrote: > On Sat, 24 Jan 2026 20:18:39 +0800 "Li, Tianyou" <tianyou.li@intel.com> wrote: > >>> cc stable@ perhaps? >> Yes, will do. Thanks. > Please separate backportable patches from those which target the next > merge window. They have different timing and take different routes > into mainline. > > Thanks. > > Appreciated Andrew for your kind explanation. My bad. Will separate it from the patch set in next version. Again, thanks Mike for pointing it out. Regards, Tianyou
© 2016 - 2026 Red Hat, Inc.