Re: [PATCH] mm/migrate: fix softlockup in do_pages_move() with huge page arrays
From: shao.mingyin
Date: Sun Nov 08 2026 - 01:27:50 EST
On Sat, Nov 07, 2026 at 08:11:22PM +0100, David Hildenbrand wrote:
> Right, and I'd like to see an actual reproducer, because we sure have a bunch of
> cond_resched() already in migration code.
The existing cond_resched() calls are in migrate_hugetlbs(),
migrate_folios_move() and migrate_pages_batch(). All three only run when the
pagelist is non-empty, i.e. after add_folio_for_migration() has isolated a
folio. For an array of addresses that are already on the target node,
add_folio_for_migration() returns 0, the folio is never queued, and
move_pages_and_store_status() returns at its list_empty() check. The loop
body (two get_user(), mmap_read_lock()/unlock(), folio walk, put_user())
therefore runs without a voluntary preemption point on PREEMPT_NONE.
I reproduced it on 6.6.60, x86_64, CONFIG_PREEMPT_NONE=y, CONFIG_NUMA=y,
under QEMU TCG (no KVM, 2 vCPUs, 3 GiB; I do not have a bare-metal
machine that can still select PREEMPT_NONE). move_pages() with 50 million
entries pointing at one page, all already on node 0, keeps CPU#1 in
kernel_move_pages() for 42.9 s and trips the watchdog:
watchdog: BUG: soft lockup - CPU#1 stuck for 26s! [init:1]
RIP: 0010:kernel_move_pages+0x424/0x820
Call Trace:
<IRQ>
? watchdog_timer_fn+0x1ad/0x210
</IRQ>
<TASK>
? kernel_move_pages+0x424/0x820
__x64_sys_move_pages+0x24/0x30
entry_SYSCALL_64_after_hwframe+0x78/0xe2
(do_pages_move() is inlined into kernel_move_pages() in this build; it is
followed by an rcu_sched self-detected stall on the same CPU.)
With this patch applied to the same tree and the same initramfs, the same
50M-entry call completes in 44.3 s with no softlockup and no RCU stall
(ret=0, all status entries 0).
The 10M figure in the v1 changelog is from the do_pages_stat() report (6.6-based
arm64 with KASAN and function tracing). Without that instrumentation this
TCG guest needs about 50M entries to stay in the loop for 20 s; 10M finishes
in 8.5 s here. Same code path, only the machine speed and instrumentation
differ.
I will send a v2 that only describes this reproduction in the changelog and
keeps the code as is, the same treatment 8e934ab44389 got for do_pages_stat().
If you would rather not carry this in mm at all, say so and I will withdraw
it; a stable-only submission would also fit the reachability.
Thanks,
Shao