[PATCH 0/6] mm: fix pfn walker races with memory offline
From: Gregory Price (Meta)
Date: Tue Oct 27 2026 - 00:23:09 EST
Several pfn walkers check that a struct page is online, then use it
after memory offline has poisoned it (CONFIG_DEBUG_VM) or removal has
freed the vmemmap. Five of the races crash the kernel; the sixth leaves
an offline spinning with the device hotplug lock held.
Patch 1 adds pfn_walk, an SRCU-fast read section that offline waits for
before poisoning the memmap. Patches 2 and 5 use it; patches 3 and 6
hold get_online_mems() instead.
1. compaction scanners
2. page_owner reads
3. memory_failure(), soft_offline_page(), unpoison_memory()
4. alloc_contig_range() undoing another caller's isolation
5. alloc_contig_pages() isolating a range that went offline
6. the hwpoison-inject filter
All six are for stable.
Patches 2 and 5 need patch 1
patch 5 builds on patch 4
patch 6 builds on patch 3
Testing
=======
Each race was reproduced on unmodified source in a QEMU guest with three
NUMA nodes and a pc-dimm left offline at boot (DEBUG_VM, KASAN,
lockdep). A test module holds one task inside the window while the
offline or eject runs, then releases it.
base this series
patch outcome runs outcome runs
----- ---------------------- ----- ---------------------- -----
1 GPF 3/3 offline waits, clean 3/3
2 GPF or #PF 6/6 offline waits, clean 6/6
3 GPF, or unpoison of a 9/9 blocks, -EIO/-ENXIO 9/9
poisoned page
4 offline still looping 4/4 offline completes 3/3
after 30s
5 GPF 3/3 offline waits, clean 6/6
6 #PF 3/3 eject waits, -ENXIO 3/3
Without forcing the window, offline/online cycling under compaction
faulted in 8 of 24 runs on base and 0 of 12 with patch 1.
Cost
====
I was unable to measure a discernable cost beyond noise, stddev of
walkers and scanners runtimes on real hardware was wildly inconsistent.
Leads me to believe this change is largely imperceivable.
Gregory Price (Meta) (6):
mm/compaction: wait for pfn walkers before poisoning offlined memmap
mm/page_owner: hold off memory offline while a page is read
mm/memory-failure: keep the page online while handling it
mm/page_alloc: don't undo another isolation in alloc_contig_range
mm/page_alloc: keep the range online while alloc_contig isolates it
mm/hwpoison-inject: keep the page online while filtering it
mm/compaction.c | 8 +++++++
mm/hwpoison-inject.c | 55 +++++++++++++++++++++++++++++---------------
mm/internal.h | 41 +++++++++++++++++++++++++++++++++
mm/memory-failure.c | 31 +++++++++++++++++--------
mm/memory_hotplug.c | 16 +++++++++++--
mm/mm_init.c | 4 ++--
mm/page_alloc.c | 35 +++++++++++++++++++++++++---
mm/page_alloc.h | 7 +++++-
mm/page_owner.c | 45 +++++++++++++++++++-----------------
9 files changed, 186 insertions(+), 56 deletions(-)
--
2.53.0-Meta