Re: [BUG] mm/memory_hotplug: panic due to race between compaction and memory hot-unplug

From: Wei Yang

Date: Fri Sep 11 2026 - 22:08:24 EST


On Thu, Sep 10, 2026 at 09:40:32AM +0200, 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.
>
>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)
>

Thanks for the explanation. I still have one confusion.

What we have here is:

isolate_freepages(cc)
page = pageblock_pfn_to_page()
if (zone->contiguous)
return pfn_to_page(pfn)
return __pageblock_pfn_to_page()
start_page = pfn_to_online_page() (1)
... check page_zone(start_page) and page_zone_id()
return start_page
suitable_migration_target(cc, page)
if (PageBuddy(page)) (2)

It looks the extra stuff between (1) and (2) is trivial and they still rely on
page struct.

Do you think it could be caused by the data synchronization between CPUs?

Two possible points:

a) zone->contiguous
b) section_mem_map's SECTION_IS_ONLINE bit

At either point, if we get the old data, we would think page is still valid
and access it.

>Using RCU is usually not easily possible. Mostly only comapction does something
>like that.
>
>--
>Cheers,
>
>David

--
Wei Yang
Help you, Help me