summaryrefslogtreecommitdiff
path: root/include/linux/mmzone.h
diff options
context:
space:
mode:
authorDavid Hildenbrand (Arm) <david@kernel.org>2026-10-18 10:06:04 +0200
committerDavid Hildenbrand (Arm) <david@kernel.org>2026-10-18 10:26:46 +0200
commit07ae95d933b84db98696f23e24de078b251561ff (patch)
treee05d70980d5f44df442fdeac13d4eebf9d2657f6 /include/linux/mmzone.h
parentc91a4ad0ea2166080682e6b75fca63a0608b76e0 (diff)
parentc31bb839fb829958101250ee5acfa4f94fdb7ecd (diff)
Merge 'memhp-7.4.misc'
MEMHP (Memory Hotplug) updates: Fixes: - Fix missing rollback when sparse_add_section() fails (Lance Yang) Performance: - Reduce zone contiguity checking overhead during memory hot(un)plug (Yuan Liu) Cleanups: - Prepare shrink_zone_span() for further changes (David Hildenbrand) Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
Diffstat (limited to 'include/linux/mmzone.h')
-rw-r--r--include/linux/mmzone.h69
1 files changed, 69 insertions, 0 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 94f9c3ff5416..7befe50223d1 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1043,6 +1043,42 @@ struct zone {
* cma pages is present pages that are assigned for CMA use
* (MIGRATE_CMA).
*
+ * pages_with_online_memmap tracks pages within the zone that have
+ * an online memory map: present pages and memory holes whose
+ * memory map has been initialized and pfn_to_online_page()
+ * succeeds. When spanned_pages == pages_with_online_memmap,
+ * pfn_to_page() can be performed without further checks on any
+ * PFN within the zone span.
+ *
+ * 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.
+ *
+ * Here is an example (page numbers are just for illustration
+ * purposes):
+ * after boot:
+ * [ zone span ]
+ * [ zone pages ]
+ * spanned=10, initialized=15, online=10
+ * online == spanned -> contiguous
+ *
+ * growing after hotplug (hotplug 5):
+ * [ zone span ]
+ * [ zone pages ] [ zone pages ]
+ * spanned=30, initialized=20, online=15
+ * online != spanned -> not contiguous
+ *
+ * shrinking after hotunplug (hotunplug 5 again):
+ * [ zone span ]
+ * [ zone pages ]
+ * spanned=15, initialized=15, online=10
+ * online != spanned -> not contiguous although contiguous
+ *
* So present_pages may be used by memory hotplug or memory power
* management logic to figure out unmanaged pages by checking
* (present_pages - managed_pages). And managed_pages should be used
@@ -1067,6 +1103,7 @@ struct zone {
atomic_long_t managed_pages;
unsigned long spanned_pages;
unsigned long present_pages;
+ unsigned long pages_with_online_memmap;
#if defined(CONFIG_MEMORY_HOTPLUG)
unsigned long present_early_pages;
#endif
@@ -1694,6 +1731,38 @@ static inline bool zone_is_zone_device(const struct zone *zone)
}
#endif
+/**
+ * zone_is_contiguous - test whether a zone is contiguous
+ * @zone: the zone to test.
+ *
+ * In a contiguous zone, it is valid to call pfn_to_page() on any PFN in the
+ * spanned zone without requiring pfn_valid() or pfn_to_online_page() checks.
+ *
+ * Note that missing synchronization with memory offlining makes any PFN
+ * traversal prone to races.
+ *
+ * ZONE_DEVICE zones are always marked non-contiguous.
+ *
+ * Return: true if contiguous, otherwise false.
+ */
+static inline bool zone_is_contiguous(const struct zone *zone)
+{
+ return READ_ONCE(zone->contiguous);
+}
+
+static inline void set_zone_contiguous(struct zone *zone)
+{
+ if (zone_is_zone_device(zone))
+ return;
+ if (zone->spanned_pages == zone->pages_with_online_memmap)
+ WRITE_ONCE(zone->contiguous, true);
+}
+
+static inline void clear_zone_contiguous(struct zone *zone)
+{
+ WRITE_ONCE(zone->contiguous, false);
+}
+
/*
* Returns true if a zone has pages managed by the buddy allocator.
* All the reclaim decisions have to use this function rather than