Skip to content

Commit 9ffa045

Browse files
Harry Yoojfvogel
authored andcommitted
mm: memcontrol: protect lruvec critical section with the RCU read lock
While acquiring the lruvec lock is sufficient to prevent memcgs and objcgs from being released [1], calling folio_memcg() within the critical section can trigger a bogus lockdep splat, as rcu_read_lock() is not held: WARNING: CPU: 23 PID: 186 at include/linux/memcontrol.h:407 lru_add+0x411/0x460 [...] Call Trace: <TASK> ? srso_alias_return_thunk+0x5/0xfbef5 ? folio_lruvec_lock_irqsave+0x135/0x2c0 ? __pfx_lru_add+0x10/0x10 folio_batch_move_lru+0x6c/0x1d0 ? lock_acquire+0x107/0x140 ? __pfx_lru_add+0x10/0x10 __folio_batch_add_and_move+0x109/0x340 filemap_add_folio+0xd5/0x100 [...] </TASK> Altough it is technically safe to not hold the RCU read lock while holding the lruvec lock, these false warnings make it harder to spot and debug real issues where the RCU lock is required but missing. Therefore, explicitly hold the RCU read lock within the critical section protected by the lruvec lock. This behavior is aligned with the Muchun Song's latest patch series [2]. Orabug: 37997580 Link: https://lore.kernel.org/linux-mm/[email protected]/ [1] Link: https://lore.kernel.org/linux-mm/[email protected]/ [2] Reviewed-by: Imran Khan <[email protected]> Signed-off-by: Harry Yoo <[email protected]>
1 parent 5fabff6 commit 9ffa045

File tree

3 files changed

+3
-4
lines changed

3 files changed

+3
-4
lines changed

include/linux/memcontrol.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,17 +1587,20 @@ static inline struct lruvec *parent_lruvec(struct lruvec *lruvec)
15871587
static inline void lruvec_unlock(struct lruvec *lruvec)
15881588
{
15891589
spin_unlock(&lruvec->lru_lock);
1590+
rcu_read_unlock();
15901591
}
15911592

15921593
static inline void lruvec_unlock_irq(struct lruvec *lruvec)
15931594
{
15941595
spin_unlock_irq(&lruvec->lru_lock);
1596+
rcu_read_unlock();
15951597
}
15961598

15971599
static inline void lruvec_unlock_irqrestore(struct lruvec *lruvec,
15981600
unsigned long flags)
15991601
{
16001602
spin_unlock_irqrestore(&lruvec->lru_lock, flags);
1603+
rcu_read_unlock();
16011604
}
16021605

16031606
/* Test requires a stable folio->memcg binding, see folio_memcg() */

mm/compaction.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,6 @@ compact_folio_lruvec_lock_irqsave(struct folio *folio, unsigned long *flags,
564564
spin_unlock_irqrestore(&lruvec->lru_lock, *flags);
565565
goto retry;
566566
}
567-
rcu_read_unlock();
568567

569568
return lruvec;
570569
}

mm/memcontrol.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,7 +1347,6 @@ struct lruvec *folio_lruvec_lock(struct folio *folio)
13471347
spin_unlock(&lruvec->lru_lock);
13481348
goto retry;
13491349
}
1350-
rcu_read_unlock();
13511350

13521351
return lruvec;
13531352
}
@@ -1378,7 +1377,6 @@ struct lruvec *folio_lruvec_lock_irq(struct folio *folio)
13781377
spin_unlock_irq(&lruvec->lru_lock);
13791378
goto retry;
13801379
}
1381-
rcu_read_unlock();
13821380

13831381
return lruvec;
13841382
}
@@ -1411,7 +1409,6 @@ struct lruvec *folio_lruvec_lock_irqsave(struct folio *folio,
14111409
spin_unlock_irqrestore(&lruvec->lru_lock, *flags);
14121410
goto retry;
14131411
}
1414-
rcu_read_unlock();
14151412

14161413
return lruvec;
14171414
}

0 commit comments

Comments
 (0)