• Roman Gushchin's avatar
    mm: memcontrol: switch to rcu protection in drain_all_stock() · e1a366be
    Roman Gushchin authored
    Commit 72f0184c ("mm, memcg: remove hotplug locking from try_charge")
    introduced css_tryget()/css_put() calls in drain_all_stock(), which are
    supposed to protect the target memory cgroup from being released during
    the mem_cgroup_is_descendant() call.
    
    However, it's not completely safe.  In theory, memcg can go away between
    reading stock->cached pointer and calling css_tryget().
    
    This can happen if drain_all_stock() races with drain_local_stock()
    performed on the remote cpu as a result of a work, scheduled by the
    previous invocation of drain_all_stock().
    
    The race is a bit theoretical and there are few chances to trigger it, but
    the current code looks a bit confusing, so it makes sense to fix it
    anyway.  The code looks like as if css_tryget() and css_put() are used to
    protect stocks drainage.  It's not necessary because stocked pages are
    holding references to the cached cgroup.  And it obviously won't work for
    works, scheduled on other cpus.
    
    So, let's read the stock->cached pointer and evaluate the memory cgroup
    inside a rcu read section, and get rid of css_tryget()/css_put() calls.
    
    Link: http://lkml.kernel.org/r/20190802192241.3253165-1-guro@fb.comSigned-off-by: default avatarRoman Gushchin <guro@fb.com>
    Acked-by: default avatarMichal Hocko <mhocko@suse.com>
    Cc: Hillf Danton <hdanton@sina.com>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    e1a366be
memcontrol.c 187 KB