mirror of
https://github.com/torvalds/linux
synced 2024-11-02 18:48:59 +00:00
mm/mglru: make memcg_lru->lock irq safe
lru_gen_rotate_memcg() can happen in softirq if memory.soft_limit_in_bytes
is set. This requires memcg_lru->lock to be irq safe. Lockdep warns on
this.
This problem only affects memcg v1.
Link: https://lkml.kernel.org/r/20230619193821.2710944-1-yuzhao@google.com
Fixes: e4dde56cd2
("mm: multi-gen LRU: per-node lru_gen_folio lists")
Signed-off-by: Yu Zhao <yuzhao@google.com>
Reported-by: syzbot+87c490fd2be656269b6a@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=87c490fd2be656269b6a
Reviewed-by: Yosry Ahmed <yosryahmed@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
0518dbe97f
commit
814bc1de03
1 changed files with 7 additions and 6 deletions
13
mm/vmscan.c
13
mm/vmscan.c
|
@ -4728,10 +4728,11 @@ static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
|
|||
{
|
||||
int seg;
|
||||
int old, new;
|
||||
unsigned long flags;
|
||||
int bin = get_random_u32_below(MEMCG_NR_BINS);
|
||||
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
|
||||
|
||||
spin_lock(&pgdat->memcg_lru.lock);
|
||||
spin_lock_irqsave(&pgdat->memcg_lru.lock, flags);
|
||||
|
||||
VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list));
|
||||
|
||||
|
@ -4766,7 +4767,7 @@ static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
|
|||
if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq))
|
||||
WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1);
|
||||
|
||||
spin_unlock(&pgdat->memcg_lru.lock);
|
||||
spin_unlock_irqrestore(&pgdat->memcg_lru.lock, flags);
|
||||
}
|
||||
|
||||
void lru_gen_online_memcg(struct mem_cgroup *memcg)
|
||||
|
@ -4779,7 +4780,7 @@ void lru_gen_online_memcg(struct mem_cgroup *memcg)
|
|||
struct pglist_data *pgdat = NODE_DATA(nid);
|
||||
struct lruvec *lruvec = get_lruvec(memcg, nid);
|
||||
|
||||
spin_lock(&pgdat->memcg_lru.lock);
|
||||
spin_lock_irq(&pgdat->memcg_lru.lock);
|
||||
|
||||
VM_WARN_ON_ONCE(!hlist_nulls_unhashed(&lruvec->lrugen.list));
|
||||
|
||||
|
@ -4790,7 +4791,7 @@ void lru_gen_online_memcg(struct mem_cgroup *memcg)
|
|||
|
||||
lruvec->lrugen.gen = gen;
|
||||
|
||||
spin_unlock(&pgdat->memcg_lru.lock);
|
||||
spin_unlock_irq(&pgdat->memcg_lru.lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4814,7 +4815,7 @@ void lru_gen_release_memcg(struct mem_cgroup *memcg)
|
|||
struct pglist_data *pgdat = NODE_DATA(nid);
|
||||
struct lruvec *lruvec = get_lruvec(memcg, nid);
|
||||
|
||||
spin_lock(&pgdat->memcg_lru.lock);
|
||||
spin_lock_irq(&pgdat->memcg_lru.lock);
|
||||
|
||||
VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list));
|
||||
|
||||
|
@ -4826,7 +4827,7 @@ void lru_gen_release_memcg(struct mem_cgroup *memcg)
|
|||
if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq))
|
||||
WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1);
|
||||
|
||||
spin_unlock(&pgdat->memcg_lru.lock);
|
||||
spin_unlock_irq(&pgdat->memcg_lru.lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue