• Hugh Dickins's avatar
    memcg: fix deadlock by inverting lrucare nesting · 9ce70c02
    Hugh Dickins authored
    We have forgotten the rules of lock nesting: the irq-safe ones must be
    taken inside the non-irq-safe ones, otherwise we are open to deadlock:
    
    CPU0                          CPU1
    ----                          ----
    lock(&(&pc->lock)->rlock);
                                  local_irq_disable();
                                  lock(&(&zone->lru_lock)->rlock);
                                  lock(&(&pc->lock)->rlock);
    <Interrupt>
    lock(&(&zone->lru_lock)->rlock);
    
    To check a different locking issue, I happened to add a spin_lock to
    memcg's bit_spin_lock in lock_page_cgroup(), and lockdep very quickly
    complained about __mem_cgroup_commit_charge_lrucare() (on CPU1 above).
    
    So delete __mem_cgroup_commit_charge_lrucare(), passing a bool lrucare to
    __mem_cgroup_commit_charge() instead, taking zone->lru_lock under
    lock_page_cgroup() in the lrucare case.
    
    The original was using spin_lock_irqsave, but we'd be in more trouble if
    it were ever called at interrupt time: unconditional _irq is enough.  And
    ClearPageLRU before del from lru, SetPageLRU before add to lru: no strong
    reason, but that is the ordering used consistently elsewhere.
    
    Fixes 36b62ad5 ("memcg: simplify corner case handling
    of LRU").
    Signed-off-by: default avatarHugh Dickins <hughd@google.com>
    Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
    Cc: Konstantin Khlebnikov <khlebnikov@openvz.org>
    Acked-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    9ce70c02
memcontrol.c 142 KB