Re: [BUG] mm/memory_hotplug: panic due to race between compaction and memory hot-unplug
From: Ketan Kishore
Date: Wed Nov 04 2026 - 00:19:55 EST
On 9/10/2026 1:10 PM, David Hildenbrand (Arm) wrote:
On 9/10/26 05:16, Wei Yang wrote:
On Mon, Sep 07, 2026 at 04:27:50PM +0200, David Hildenbrand (Arm) wrote:
On 9/3/26 11:55, Yuan Liu wrote:
Hi all,
Hi!
While stress testing memory hotplug on a VM guest running an
unmodified vanilla mainline kernel (7.3.0-rc1, as reported by
uname -r), we hit a kernel panic in the guest when memory
hot-unplug runs concurrently with memory compaction.
The kernel was built from mainline at commit:
cee9395acd80 ("Linux 7.3-rc1")
To be more specific, after a large virtio-mem hot-unplug, the guest
kernel takes a fatal page fault in suitable_migration_target(), called
from isolate_freepages() during compaction.
Sounds like a real problem we should tackle.
We are not sure whether this race is reachable under realistic
workloads or only under this synthetic stress test. Sharing it here
in case it is useful, and in case this is already a known issue.
Thanks.
Call trace (top to bottom)
==========================
- RIP: suitable_migration_target+0x5/0x70
isolate_freepages() <- compaction_alloc() <-
migrate_pages() <- compact_zone() <- compact_node() <-
sysctl_compaction_handler().
Why the race happens
====================
CPU0 (compaction free-scanner) CPU1 (virtio-mem hot-unplug)
---- ----
page = pageblock_pfn_to_page()
/* checks pass, section ONLINE */
/* returns valid struct page* */
offline_pages()
/* section -> offline */
__remove_pages()
vmemmap_free()
/* struct page UNMAPPED */
suitable_migration_target(page)
PageBuddy(page)
read page->page_type
*** not-present fault -> panic ***
Does it mean, the combination of pfn_to_online_page() / PageBuddy(page) is not
safe, when there is hot-remove, even for other users. Not only compaction.
There is an inherent race between any
pfn_to_online_page() user that then takes a look at the memmap (PageBuddy,
whatever).
Usually, that's not really relevant, because for things to go terrible wrong
(instead of only being slightly suboptimal :) )
You have to run both, memory offlining *and* memory removal.
Hello
We faced similar issue internally on one of our target's guest VM run,
where kcompactd de-referenced a vmemmap pointer for a PFN after the hot-unplug path had already freed that vmemmap,with no lock preventing the two from running simultaneously.
Call trace:
suitable_migration_target+0x0/0x8c (P)
migrate_pages_batch+0x1b4/0xc74
migrate_pages+0x150/0x654
compact_zone+0x5bc/0xb30
compact_node+0xa0/0x18c
kcompactd+0x228/0x4d0
Would it be okay to introduce something like "try_get_online_mems" as shown below to try a readlock in compaction path for hot-unplug to wait
for kcompactd to complete before freeing the vmemmap?
get_online_mems()
-> percpu_down_read(&mem_hotplug_lock); /* may sleep */
try_get_online_mems()
-> percpu_down_read_trylock(&mem_hotplug_lock); /* won't sleep */
kcompactd / compaction memory hot-remove
---------------------- -----------------
try_get_online_mems() -> true
holds read lock
uses PFNs and struct page pointers
mem_hotplug_begin()
percpu_down_write()
waits for readers to leave
finishes compaction
put_online_mems() // releases read lock
writer acquires write lock
offline/remove memory
free vmemmap
mem_hotplug_done()
And to skip compaction if taking the lock is not successful here.
Appreciate any suggestions or feedback.
Thankyou.
For things like
page = pfn_to_online_page()
if (PageBuddy(page))
That's unlikely to hit (no reports), and we could likely easily fix it with the
help of RCU.
It gets more problematic when we do things like
page = pfn_to_online_page()
... do all other kind of stuff
if (PageBuddy(page))
(what we have here)
Using RCU is usually not easily possible. Mostly only comapction does something
like that.