• M
    memcg: fix endless loop caused by mem_cgroup_iter · ecc736fc
    Michal Hocko 提交于
    Hugh has reported an endless loop when the hardlimit reclaim sees the
    same group all the time.  This might happen when the reclaim races with
    the memcg removal.
    
    shrink_zone
                                                    [rmdir root]
      mem_cgroup_iter(root, NULL, reclaim)
        // prev = NULL
        rcu_read_lock()
        mem_cgroup_iter_load
          last_visited = iter->last_visited   // gets root || NULL
          css_tryget(last_visited)            // failed
          last_visited = NULL                 [1]
        memcg = root = __mem_cgroup_iter_next(root, NULL)
        mem_cgroup_iter_update
          iter->last_visited = root;
        reclaim->generation = iter->generation
    
     mem_cgroup_iter(root, root, reclaim)
       // prev = root
       rcu_read_lock
        mem_cgroup_iter_load
          last_visited = iter->last_visited   // gets root
          css_tryget(last_visited)            // failed
        [1]
    
    The issue seemed to be introduced by commit 5f578161 ("memcg: relax
    memcg iter caching") which has replaced unconditional css_get/css_put by
    css_tryget/css_put for the cached iterator.
    
    This patch fixes the issue by skipping css_tryget on the root of the
    tree walk in mem_cgroup_iter_load and symmetrically doesn't release it
    in mem_cgroup_iter_update.
    Signed-off-by: NMichal Hocko <mhocko@suse.cz>
    Reported-by: NHugh Dickins <hughd@google.com>
    Tested-by: NHugh Dickins <hughd@google.com>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Cc: Greg Thelen <gthelen@google.com>
    Cc: <stable@vger.kernel.org>	[3.10+]
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    ecc736fc
memcontrol.c 193.7 KB