Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mm/mglru: fix lockless folio_putback_lru() race in evict_folios()
@ 2026-08-07 10:30 Ketan Kishore
  2026-08-07 15:12 ` Shakeel Butt
  2026-08-07 17:02 ` [syzbot ci] " syzbot ci
  0 siblings, 2 replies; 3+ messages in thread
From: Ketan Kishore @ 2026-08-07 10:30 UTC (permalink / raw)
  To: Andrew Morton, Johannes Weiner, David Hildenbrand, Michal Hocko,
	Qi Zheng, Shakeel Butt, Lorenzo Stoakes, Kairui Song, Barry Song,
	Axel Rasmussen, Yuanchu Xie, Wei Xu, Yu Zhao
  Cc: kernel, linux-mm, linux-kernel, Prakash Gupta, Ketan Kishore

folio_putback_lru() requires lru_lock to not be held by the caller,
but it internally calls folio_add_lru() -> lruvec_add_folio() ->
lru_gen_add_folio() -> list_add(), which modifies lrugen->folios[]
without acquiring lruvec->lru_lock.

In evict_folios(), lru_lock is dropped before shrink_folio_list() and
the subsequent list_for_each_entry_safe_reverse() loop. When an
unevictable folio is encountered in this lockless section,
folio_putback_lru() is called to return it to lrugen->folios[]. This
races with any concurrent CPU that holds lru_lock and operates on the
same list (e.g. via list_del or list_move), corrupting prev->next.

The corruption is detected later when move_folios_to_lru() re-acquires
lru_lock and calls list_del() on a folio whose list linkage was
corrupted, triggering BUG at lib/list_debug.c:64:

  list_del corruption. prev->next should be fffffffeead4fbc8,
  but was ffffeafeead44188. (prev=fffffffee4fc4c08)
  kernel BUG at lib/list_debug.c:64!
  Call trace:
   __list_del_entry_valid_or_report+0x100/0x14c
   evict_folios+0x145c/0x16dc
   try_to_shrink_lruvec+0x228/0x35c
   shrink_one+0x94/0x158
   shrink_many+0x1c8/0x1f4
   lru_gen_shrink_node+0x94/0x110
   shrink_node+0x468/0x8b4
   balance_pgdat+0x4f0/0x9a0
   kswapd+0x268/0x470

The race window is amplified when unevictable memory is high, causing
folio_putback_lru() to be called many times in the lockless section.

move_folios_to_lru() already handles this correctly: it drops and
re-acquires lru_lock around folio_putback_lru() for unevictable folios.
Apply the same pattern to evict_folios().

Fixes: 359a5e1416ca ("mm: multi-gen LRU: retry folios written back while isolated")
Signed-off-by: Prakash Gupta <prakash.gupta@oss.qualcomm.com>
Signed-off-by: Ketan Kishore <ketan.kishore@oss.qualcomm.com>
---
 mm/vmscan.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 26436059ea39..7c4adba13e4f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4923,7 +4923,9 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 
 		if (!folio_evictable(folio)) {
 			list_del(&folio->lru);
+			spin_lock_irq(&lruvec->lru_lock);
 			folio_putback_lru(folio);
+			spin_unlock_irq(&lruvec->lru_lock);
 			continue;
 		}
 

---
base-commit: ea2bff00da89d7767d677bb68470130ba96f4928
change-id: 20260807-evict_folios_race-f3b119e0cf97

Best regards,
--  
Ketan Kishore <ketan.kishore@oss.qualcomm.com>



^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-07 17:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-07 10:30 [PATCH] mm/mglru: fix lockless folio_putback_lru() race in evict_folios() Ketan Kishore
2026-08-07 15:12 ` Shakeel Butt
2026-08-07 17:02 ` [syzbot ci] " syzbot ci

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox