RE: [PATCH v7 1/2] mm/memory_hotplug: make shrink_zone_span() more robust

From: Liu, Yuan1

Date: Thu Aug 20 2026 - 08:55:16 EST


> -----Original Message-----
> From: Liu, Yuan1 <yuan1.liu@xxxxxxxxx>
> Sent: Tuesday, August 18, 2026 4:57 PM
> To: David Hildenbrand <david@xxxxxxxxxx>; Oscar Salvador
> <osalvador@xxxxxxx>; Mike Rapoport <rppt@xxxxxxxxxx>; Wei Yang
> <richard.weiyang@xxxxxxxxx>
> Cc: linux-mm@xxxxxxxxx; Zou, Nanhai <nanhai.zou@xxxxxxxxx>; Chen Zhang
> <zhangchen.kidd@xxxxxx>; Liu, Yuan1 <yuan1.liu@xxxxxxxxx>; Zeng, Jason
> <jason.zeng@xxxxxxxxx>; Chen, Yu C <yu.c.chen@xxxxxxxxx>; Deng, Pan
> <pan.deng@xxxxxxxxx>; Li, Tianyou <tianyou.li@xxxxxxxxx>; linux-
> kernel@xxxxxxxxxxxxxxx
> Subject: [PATCH v7 1/2] mm/memory_hotplug: make shrink_zone_span() more
> robust
>
> From: "David Hildenbrand (Arm)" <david@xxxxxxxxxx>
>
> Let's make shrink_zone_span() more robust by checking in
> find_smallest_section_pfn() / find_biggest_section_pfn() that the
> start and end PFNs of the subsection are within the zone.
>
> While at it, clean up the function by factoring the core check out
> into subsection_overlaps_zone().
>
> There likely is no need to check the nid first. We require
> SPARSEMEM_VMEMMAP_ENABLE, where pfn_to_page() is cheap, and
> pfn_to_nid() on CONFIG_NUMA would call pfn_to_page() either way.
> So let's just drop that for now.
>
> Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
> Tested-by: Yuan Liu <yuan1.liu@xxxxxxxxx>
> Signed-off-by: Yuan Liu <yuan1.liu@xxxxxxxxx>
> ---
> mm/memory_hotplug.c | 59 ++++++++++++++++++---------------------------
> 1 file changed, 24 insertions(+), 35 deletions(-)
>
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index 7ac19fab2263..cd82e79f0782 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
[...]

> /* find the biggest valid pfn in the range [start_pfn, end_pfn). */
> -static unsigned long find_biggest_section_pfn(int nid, struct zone *zone,
> - unsigned long start_pfn,
> - unsigned long end_pfn)
> +static unsigned long find_biggest_section_pfn(struct zone *zone,
> + unsigned long start_pfn, unsigned long end_pfn)
> {
> - unsigned long pfn;
> -
> - /* pfn is the end pfn of a memory section. */
> - pfn = end_pfn - 1;
> - for (; pfn >= start_pfn; pfn -= PAGES_PER_SUBSECTION) {
> - if (unlikely(!pfn_to_online_page(pfn)))
> - continue;
> -
> - if (unlikely(pfn_to_nid(pfn) != nid))
> - continue;
> -
> - if (zone != page_zone(pfn_to_page(pfn)))
> - continue;
> -
> - return pfn;
> + for (; end_pfn >= start_pfn; end_pfn -= PAGES_PER_SUBSECTION) {
> + if (subsection_overlaps_zone(end_pfn - 1, zone))
> + return end_pfn - 1;
> }

Hi David

Sashiko[1] pointed out that the loop can evaluate an out-of-range PFN
and underflow when start_pfn is 0. I'll change the condition to
end_pfn > start_pfn to address this.

[1] https://sashiko.dev/#/patchset/20260818085702.3395529-1-yuan1.liu%40intel.com

Best Regards,
Liu, Yuan

> -
> return 0;
> }