[PATCH 10/46] mm/huge_memory: fix list corruption when deferred_split_scan() races with deferred_split_folio()
Mani Tofigh
mt4022 at columbia.edu
Tue Oct 27 17:14:07 PDT 2026
On 10/26/26 7:17 PM, David Hildenbrand (Arm) wrote:
> Since the deferred split queue became a list_lru, the isolate callback
> moves the folios it took a reference on to an on-stack list, linked
> through folio->_deferred_list, and deferred_split_scan() takes them off
> that list with list_del_init() without holding the list_lru lock.
>
> deferred_split_folio() does not know about the on-stack list. It only
> holds the list_lru lock when it looks at the same list_head, and it can
> run for such a folio: a THP is queued when it is mapped, as a candidate
> for the underused check, and is queued "again" when a part of it gets
> unmapped:
>
> CPU0 deferred_split_scan() CPU1 deferred_split_folio()
> list_del_init(&folio->_deferred_list)
> next->prev = prev
> prev->next = next
> entry->next = entry
> list_lru_lock_irqsave()
> folio_set_partially_mapped()
> __list_lru_add()
> list_empty(item) -> true
> list_add_tail(item, &l->list)
> item->next = &l->list
> item->prev = tail
> entry->prev = entry
>
> The folio now sits on the list_lru with ->prev pointing to itself. The
> next removal leaves the neighbours pointing to it, and they still do so
> after the folio has been freed. With CONFIG_DEBUG_LIST:
>
> list_del corruption. prev->next should be ffd4000000270090, but was
> ffd4000000278090. (prev=ffd4000000270090)
>
> Fix it by grabbing the lock around list_del_init() so
> deferred_split_folio() cannot race with it.
>
> Fixes: fafaeceb89a5 ("mm: switch deferred split shrinker to list_lru")
> Cc: stable at vger.kernel.org
> Reported-by: Josef Bacik <josef at toxicpanda.com>
> Signed-off-by: David Hildenbrand (Arm) <david at kernel.org>
Reviewed-by: Mani Tofigh <mt4022 at columbia.edu>
Tested-by: Mani Tofigh <mt4022 at columbia.edu>
More information about the kexec
mailing list