Re: [PATCH] mm/huge_memory: fix deferred split list corruption on partial unmap

From: David Hildenbrand (Arm)

Date: Tue Oct 27 2026 - 05:02:08 EST


On 10/27/26 01:22, Mani Tofigh via B4 Relay wrote:
> From: Mani Tofigh <mt4022@xxxxxxxxxxxx>
>
> When a THP is partially unmapped while the deferred split shrinker is
> scanning it, the deferred split list can end up corrupted. With
> CONFIG_DEBUG_LIST, freeing the folio later reports:
>
> [ 523.871401] list_del corruption. prev->next should be ffd40000005e0090, but was ffd4000000500090. (prev=ffd40000005e0090)
> [ 523.871412] WARNING: lib/list_debug.c:62 at __list_del_entry_valid_or_report+0x177/0x220, CPU#0: thpsplit/63
> ...
> [ 523.900715] Call Trace:
> [ 523.901753] __list_lru_del+0x5f/0x220
> [ 523.902588] __folio_unqueue_deferred_split+0x238/0x520
> ...
>
> Without CONFIG_DEBUG_LIST, the list is left pointing at the folio
> after it has been freed.
>
> Since commit fafaeceb89a5 ("mm: switch deferred split shrinker to
> list_lru"), deferred_split_scan() moves the folios it scans onto a
> private list under the list_lru lock, drops the lock, and then removes
> each folio from that list with list_del_init(), which sets
> entry->next = entry and then entry->prev = entry. Another task may
> in the meantime partially unmap the same folio and call
> deferred_split_folio(), which queues it only if list_empty() reports
> it as not queued, and list_empty() reads only entry->next. If that
> happens between the two stores, the folio is queued again, and the
> store to entry->prev that follows breaks the new link:
>
> Task A (shrinker) Task B (partial unmap)
> ----------------- ----------------------
> list_del_init(entry)
> entry->next = entry
> deferred_split_folio()
> list_empty(entry) is true
> list_add_tail(entry)
> entry->prev = entry
> /* overwrites the prev link that
> list_add_tail() just set */
>
> Use list_del_init_careful() instead. It sets entry->prev first and
> then entry->next with smp_store_release(), so once list_empty() sees
> the entry as empty, the shrinker has finished writing to it.
>
> The reproducer repeatedly faults in THPs and partially unmaps them
> while the deferred split shrinker, run through
> /proc/sys/vm/drop_caches on the same CPU, is scanning them. This bug
> was found and replayed using a deterministic hypervisor currently
> under development, but the non-deterministic C reproducer can
> typically trigger it in the 10-500s time range. With the fix, nothing
> is triggered after 1800 seconds.
>
> Fixes: fafaeceb89a5 ("mm: switch deferred split shrinker to list_lru")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Mani Tofigh <mt4022@xxxxxxxxxxxx>


Are we now sending alterantive fixes for anything already posted? :)

https://lore.kernel.org/r/20261027-fixes_core-v1-10-6f74bec9a5bb@xxxxxxxxxx

If there is a better way to handle it reply to fixes already posted.

--
Cheers,

David