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

Yuan Liu posted 2 patches 4 days, 11 hours ago
Documentation/mm/physical_memory.rst |  6 +++
drivers/base/memory.c                |  7 ++-
include/linux/mmzone.h               | 69 +++++++++++++++++++++++++++
mm/memory_hotplug.c                  | 71 ++++++++++------------------
mm/mm_init.c                         | 64 ++++++++++++++-----------
mm/mm_init.h                         |  6 ---
mm/page_alloc.h                      |  2 +-
7 files changed, 144 insertions(+), 81 deletions(-)
[PATCH v10 0/2] mm/memory_hotplug: optimize zone contiguous check when changing pfn range
Posted by Yuan Liu 4 days, 11 hours ago
This series introduces a pages_with_online_memmap member into struct
zone to avoid pageblock-by-pageblock scans across the entire zone and
improve memory hotplug performance.

Approach
========
Add a new zone member, pages_with_online_memmap, that tracks the
number of pages within the zone span that have an online memory map,
including present pages and memory holes whose memory map has been
initialized and for which pfn_to_online_page() succeeds.

For early boot memory, pages_with_online_memmap is calculated in
memmap_init_zone_range(). PFNs initialized by memmap_init_range() are
included in pages_with_online_memmap, and hole PFNs for which
pfn_to_online_page() succeeds are also counted in
init_unavailable_range(). For hotplugged memory,
pages_with_online_memmap is updated through adjust_present_page_count(),
which is called during memory online and offline operations. When
spanned_pages == pages_with_online_memmap, every PFN in the zone span
has a valid memmap entry, so pfn_to_page() can be called for any PFN
within the zone span without an additional pfn_valid() check.

Note: this counter may temporarily undercount when pages with an
online memory map exist outside the current zone span. Such pages
are only created during boot, when initializing the memory map of
pages that do not fall into any zone span. The undercount itself
can only happen after boot, during memory hotplug, when growing
the zone to cover such pages and later shrinking it back, which
may result in a "too small" value. This is safe: it merely
prevents detecting a contiguous zone.

The contiguity check using pages_with_online_memmap is stricter than
the old pageblock-by-pageblock scan. The old set_zone_contiguous()
iterated at pageblock granularity via pageblock_pfn_to_page(), so a
zone could be marked contiguous even if a subsection-sized hole
existed within a pageblock. The new check requires
spanned_pages == pages_with_online_memmap, meaning every PFN in the
zone span must satisfy pfn_to_online_page().

Performance
===========
1. For VM hotplug performance data, please refer to Patch 2.
2. This series also benefits CXL hotplug. Performance results are
   as follows
   https://lore.kernel.org/all/20260409023552.GA2807@AE/

Tested cases
============
1. Hotplug/unplug correctness with both online_movable and online
   policies, including partial unplug, middle-block offline gaps, and
   edge-block span shrink.
2. Large scale (256G/512G) plug/unplug performance.
3. Boot-time subsection holes (aligned/unaligned, in-zone and
   cross-zone) with correct pages_with_online_memmap accounting.
4. kernelcore=mirror: verified no overcounting.

Patch overview
==============
Patch 1 makes shrink_zone_span() more robust when memory/hole boundary
falls within a subsection. It checks the full subsection range to avoid
incorrectly shrinking the zone span during memory unplug.

Patch 2 introduces pages_with_online_memmap to replace
pageblock-by-pageblock scans across the entire zone for zone contiguity
checks.

v10 changes:
    1. Rebased onto v7.3-rc3.
    2. Added Acked-by: Mike Rapoport (Microsoft) on patch 2 and reworded
       the init_unavailable_range() comment as suggested.
v9:
    https://lore.kernel.org/linux-mm/20260914072929.1883794-1-yuan1.liu@intel.com/

v8:
    https://lore.kernel.org/linux-mm/20260901052950.3284540-1-yuan1.liu@intel.com/

v7:
    https://lore.kernel.org/linux-mm/20260818085702.3395529-1-yuan1.liu@intel.com/

v6:
    https://lore.kernel.org/linux-mm/20260723084946.189392-1-yuan1.liu@intel.com/

v5:
    https://lore.kernel.org/linux-mm/20260520093457.3719960-1-yuan1.liu@intel.com/

v4:
    https://lore.kernel.org/linux-mm/20260421125508.2317429-1-yuan1.liu@intel.com/

v3:
    https://lore.kernel.org/linux-mm/20260408031615.1831922-1-yuan1.liu@intel.com/

v2:
    https://lore.kernel.org/all/20260401070155.1420929-1-yuan1.liu@intel.com/

v1:
    https://lore.kernel.org/all/20260319095622.1130380-1-yuan1.liu@intel.com/

David Hildenbrand (Arm) (1):
  mm/memory_hotplug: make shrink_zone_span() more robust

Yuan Liu (1):
  mm/memory_hotplug: optimize zone contiguous check when changing pfn
    range

 Documentation/mm/physical_memory.rst |  6 +++
 drivers/base/memory.c                |  7 ++-
 include/linux/mmzone.h               | 69 +++++++++++++++++++++++++++
 mm/memory_hotplug.c                  | 71 ++++++++++------------------
 mm/mm_init.c                         | 64 ++++++++++++++-----------
 mm/mm_init.h                         |  6 ---
 mm/page_alloc.h                      |  2 +-
 7 files changed, 144 insertions(+), 81 deletions(-)


base-commit: fd73f4a6659897191fa0d40695fe370925dd3780
-- 
2.47.3
Re: [PATCH v10 0/2] mm/memory_hotplug: optimize zone contiguous check when changing pfn range
Posted by David Hildenbrand 1 day, 5 hours ago
On Sun, 20 Sep 2026 04:49:44 -0400, Yuan Liu wrote:
> This series introduces a pages_with_online_memmap member into struct
> zone to avoid pageblock-by-pageblock scans across the entire zone and
> improve memory hotplug performance.
> 
> Approach
> ========
> Add a new zone member, pages_with_online_memmap, that tracks the
> number of pages within the zone span that have an online memory map,
> including present pages and memory holes whose memory map has been
> initialized and for which pfn_to_online_page() succeeds.
> 
> [...]

Applied, thanks!

tree: mm/core.git
branch: memhp-7.4.misc

Applied patches will appear soon in mm-next, followed by linux-next.

Please report any outstanding bugs that were missed during review, so we
can either drop the patch series or decide how to fix it up.

It is encouraged to provide Acked-bys, Reviewed-bys, and Tested-bys even
though the patches have already been applied. If possible, patch trailers
will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. Further, this is not a guarantee that the
patches will go upstream. If in doubt, please check the listed branch.

[1/2] mm/memory_hotplug: make shrink_zone_span() more robust
      https://git.kernel.org/mm/core/c/1a3fed34
[2/2] mm/memory_hotplug: optimize zone contiguous check when changing pfn range
      https://git.kernel.org/mm/core/c/554e941f

-- 
Cheers,

David
Re: [PATCH v10 0/2] mm/memory_hotplug: optimize zone contiguous check when changing pfn range
Posted by David Hildenbrand (Arm) 2 days, 6 hours ago
On 9/20/26 10:49, Yuan Liu wrote:
> This series introduces a pages_with_online_memmap member into struct
> zone to avoid pageblock-by-pageblock scans across the entire zone and
> improve memory hotplug performance.
> 
> Approach
> ========
> Add a new zone member, pages_with_online_memmap, that tracks the
> number of pages within the zone span that have an online memory map,
> including present pages and memory holes whose memory map has been
> initialized and for which pfn_to_online_page() succeeds.
> 
> For early boot memory, pages_with_online_memmap is calculated in
> memmap_init_zone_range(). PFNs initialized by memmap_init_range() are
> included in pages_with_online_memmap, and hole PFNs for which
> pfn_to_online_page() succeeds are also counted in
> init_unavailable_range(). For hotplugged memory,
> pages_with_online_memmap is updated through adjust_present_page_count(),
> which is called during memory online and offline operations. When
> spanned_pages == pages_with_online_memmap, every PFN in the zone span
> has a valid memmap entry, so pfn_to_page() can be called for any PFN
> within the zone span without an additional pfn_valid() check.
> 
> Note: this counter may temporarily undercount when pages with an
> online memory map exist outside the current zone span. Such pages
> are only created during boot, when initializing the memory map of
> pages that do not fall into any zone span. The undercount itself
> can only happen after boot, during memory hotplug, when growing
> the zone to cover such pages and later shrinking it back, which
> may result in a "too small" value. This is safe: it merely
> prevents detecting a contiguous zone.
> 
> The contiguity check using pages_with_online_memmap is stricter than
> the old pageblock-by-pageblock scan. The old set_zone_contiguous()
> iterated at pageblock granularity via pageblock_pfn_to_page(), so a
> zone could be marked contiguous even if a subsection-sized hole
> existed within a pageblock. The new check requires
> spanned_pages == pages_with_online_memmap, meaning every PFN in the
> zone span must satisfy pfn_to_online_page().
> 
> Performance
> ===========
> 1. For VM hotplug performance data, please refer to Patch 2.
> 2. This series also benefits CXL hotplug. Performance results are
>    as follows
>    https://lore.kernel.org/all/20260409023552.GA2807@AE/
> 
> Tested cases
> ============
> 1. Hotplug/unplug correctness with both online_movable and online
>    policies, including partial unplug, middle-block offline gaps, and
>    edge-block span shrink.
> 2. Large scale (256G/512G) plug/unplug performance.
> 3. Boot-time subsection holes (aligned/unaligned, in-zone and
>    cross-zone) with correct pages_with_online_memmap accounting.
> 4. kernelcore=mirror: verified no overcounting.
> 
> Patch overview
> ==============
> Patch 1 makes shrink_zone_span() more robust when memory/hole boundary
> falls within a subsection. It checks the full subsection range to avoid
> incorrectly shrinking the zone span during memory unplug.
> 
> Patch 2 introduces pages_with_online_memmap to replace
> pageblock-by-pageblock scans across the entire zone for zone contiguity
> checks.
> 
> v10 changes:
>     1. Rebased onto v7.3-rc3.
>     2. Added Acked-by: Mike Rapoport (Microsoft) on patch 2 and reworded
>        the init_unavailable_range() comment as suggested.

Thanks, I'm planning on queuing this tomorrow.

-- 
Cheers,

David