* + mm-memory_hotplug-resize-zones-under-their-seqlock.patch added to mm-unstable branch
@ 2026-10-27 20:05 Andrew Morton
0 siblings, 0 replies; only message in thread
From: Andrew Morton @ 2026-10-27 20:05 UTC (permalink / raw)
To: mm-commits, ziy, willy, vbabka, surenb, stable, shakeel.butt,
rppt, osalvador, mhocko, hannes, gourry, david, brendan.jackman,
josef, akpm
The patch titled
Subject: mm/memory_hotplug: resize zones under their seqlock
has been added to the -mm mm-unstable branch. Its filename is
mm-memory_hotplug-resize-zones-under-their-seqlock.patch
This patch will shortly appear at
https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-memory_hotplug-resize-zones-under-their-seqlock.patch
This patch will later appear in the mm-unstable branch at
git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Before you just go and hit "reply", please:
a) Consider who else should be cc'ed
b) Prefer to cc a suitable mailing list as well
c) Ideally: find the original patch on the mailing list and do a
reply-to-all to that, adding suitable additional cc's
*** Remember to use Documentation/process/submit-checklist.rst when testing your code ***
The -mm tree is included into linux-next via various
branches at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
and is updated there most days
------------------------------------------------------
From: Josef Bacik <josef@toxicpanda.com>
Subject: mm/memory_hotplug: resize zones under their seqlock
Date: Tue, 27 Oct 2026 16:46:34 +0100
With CONFIG_DEBUG_VM the page allocator checks that a page which is
freed, split or allocated lies within its zone. The check reads
zone->zone_start_pfn and zone->spanned_pages under zone->span_seqlock, as
memory hotplug can change the two at any time.
Commit 27cacaad16c5 ("mm,memory_hotplug: drop unneeded locking") removed
the write side, since all resizing is serialized by the hotplug lock. That
leaves the reader without protection. When memory below the start of a
zone goes online, the start is lowered first and the size is raised
afterwards. When the lowest memory of a zone goes offline, the size is
reduced first. In between, the zone seems to end before its last pages. If
one of them goes through the allocator at that moment, it is reported as
being outside of the zone and VM_BUG_ON_PAGE() kills the kernel.
Write the two fields in a write section of the seqlock. Interrupts are
disabled as pages are freed from interrupts, too, and the reader would
wait for the writer which it has interrupted.
Link: https://lore.kernel.org/20261027-pgalloc-ai-hotfixes-v1-8-9c7d1aca801e@kernel.org
Fixes: 27cacaad16c5 ("mm,memory_hotplug: drop unneeded locking")
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Assisted-by: LLM
Cc: Zi Yan <ziy@nvidia.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Brendan Jackman <brendan.jackman@linux.dev>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Gregory Price (Meta)" <gourry@gourry.net>
Cc: <stable@vger.kernel.org>
---
mm/memory_hotplug.c | 44 ++++++++++++++++++++++++++----------------
1 file changed, 28 insertions(+), 16 deletions(-)
--- a/mm/memory_hotplug.c~mm-memory_hotplug-resize-zones-under-their-seqlock
+++ a/mm/memory_hotplug.c
@@ -467,6 +467,22 @@ static unsigned long find_biggest_sectio
return 0;
}
+/*
+ * The page allocator checks pages against the span of their zone while the
+ * zone is resized, see page_outside_zone_boundaries(). It must not see the
+ * new value of one field together with the old value of the other one.
+ */
+static void zone_set_span(struct zone *zone, unsigned long start_pfn,
+ unsigned long spanned_pages)
+{
+ unsigned long flags;
+
+ write_seqlock_irqsave(&zone->span_seqlock, flags);
+ zone->zone_start_pfn = start_pfn;
+ zone->spanned_pages = spanned_pages;
+ write_sequnlock_irqrestore(&zone->span_seqlock, flags);
+}
+
static void shrink_zone_span(struct zone *zone, unsigned long start_pfn,
unsigned long end_pfn)
{
@@ -482,13 +498,10 @@ static void shrink_zone_span(struct zone
*/
pfn = find_smallest_section_pfn(nid, zone, end_pfn,
zone_end_pfn(zone));
- if (pfn) {
- zone->spanned_pages = zone_end_pfn(zone) - pfn;
- zone->zone_start_pfn = pfn;
- } else {
- zone->zone_start_pfn = 0;
- zone->spanned_pages = 0;
- }
+ if (pfn)
+ zone_set_span(zone, pfn, zone_end_pfn(zone) - pfn);
+ else
+ zone_set_span(zone, 0, 0);
} else if (zone_end_pfn(zone) == end_pfn) {
/*
* If the section is biggest section in the zone, it need
@@ -499,11 +512,10 @@ static void shrink_zone_span(struct zone
pfn = find_biggest_section_pfn(nid, zone, zone->zone_start_pfn,
start_pfn);
if (pfn)
- zone->spanned_pages = pfn - zone->zone_start_pfn + 1;
- else {
- zone->zone_start_pfn = 0;
- zone->spanned_pages = 0;
- }
+ zone_set_span(zone, zone->zone_start_pfn,
+ pfn - zone->zone_start_pfn + 1);
+ else
+ zone_set_span(zone, 0, 0);
}
}
@@ -696,12 +708,12 @@ static void online_pages_range(unsigned
static void __meminit resize_zone_range(struct zone *zone, unsigned long start_pfn,
unsigned long nr_pages)
{
- unsigned long old_end_pfn = zone_end_pfn(zone);
+ unsigned long end_pfn = max(start_pfn + nr_pages, zone_end_pfn(zone));
- if (zone_is_empty(zone) || start_pfn < zone->zone_start_pfn)
- zone->zone_start_pfn = start_pfn;
+ if (!zone_is_empty(zone) && start_pfn > zone->zone_start_pfn)
+ start_pfn = zone->zone_start_pfn;
- zone->spanned_pages = max(start_pfn + nr_pages, old_end_pfn) - zone->zone_start_pfn;
+ zone_set_span(zone, start_pfn, end_pfn - start_pfn);
}
static void __meminit resize_pgdat_range(struct pglist_data *pgdat, unsigned long start_pfn,
_
Patches currently in -mm which might be from josef@toxicpanda.com are
mm-page_alloc-dont-undo-a-racing-start_isolate_page_range.patch
mm-page_alloc-clear-private-of-deferred-free-pages.patch
mm-page_frag-refill-the-cache-for-large-fragments.patch
mm-page_alloc-keep-the-pagesets-of-an-empty-zone.patch
mm-page_alloc-pass-zone-pointer-to-trace_reclaim_retry_zone.patch
mm-compaction-trust-zone-contiguous-only-in-the-span.patch
mm-page_isolation-do-not-take-slab-pages-for-free.patch
mm-memory_hotplug-resize-zones-under-their-seqlock.patch
mm-page_alloc-check-pageblock-pfns-under-span-seqlock.patch
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-27 20:05 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-27 20:05 + mm-memory_hotplug-resize-zones-under-their-seqlock.patch added to mm-unstable branch Andrew Morton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox