提交 2f7dd7a4 编写于 作者: J Johannes Weiner 提交者: Linus Torvalds

mm: memcontrol: do not iterate uninitialized memcgs

The cgroup iterators yield css objects that have not yet gone through
css_online(), but they are not complete memcgs at this point and so the
memcg iterators should not return them.  Commit d8ad3055 ("mm/memcg:
iteration skip memcgs not yet fully initialized") set out to implement
exactly this, but it uses CSS_ONLINE, a cgroup-internal flag that does
not meet the ordering requirements for memcg, and so the iterator may
skip over initialized groups, or return partially initialized memcgs.

The cgroup core can not reasonably provide a clear answer on whether the
object around the css has been fully initialized, as that depends on
controller-specific locking and lifetime rules.  Thus, introduce a
memcg-specific flag that is set after the memcg has been initialized in
css_online(), and read before mem_cgroup_iter() callers access the memcg
members.
Signed-off-by: NJohannes Weiner <hannes@cmpxchg.org>
Cc: Tejun Heo <tj@kernel.org>
Acked-by: NMichal Hocko <mhocko@suse.cz>
Cc: Hugh Dickins <hughd@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: <stable@vger.kernel.org>	[3.12+]
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 55dacd22
...@@ -292,6 +292,9 @@ struct mem_cgroup { ...@@ -292,6 +292,9 @@ struct mem_cgroup {
/* vmpressure notifications */ /* vmpressure notifications */
struct vmpressure vmpressure; struct vmpressure vmpressure;
/* css_online() has been completed */
int initialized;
/* /*
* the counter to account for mem+swap usage. * the counter to account for mem+swap usage.
*/ */
...@@ -1099,10 +1102,21 @@ static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root, ...@@ -1099,10 +1102,21 @@ static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root,
* skipping css reference should be safe. * skipping css reference should be safe.
*/ */
if (next_css) { if (next_css) {
if ((next_css == &root->css) || struct mem_cgroup *memcg = mem_cgroup_from_css(next_css);
((next_css->flags & CSS_ONLINE) &&
css_tryget_online(next_css))) if (next_css == &root->css)
return mem_cgroup_from_css(next_css); return memcg;
if (css_tryget_online(next_css)) {
/*
* Make sure the memcg is initialized:
* mem_cgroup_css_online() orders the the
* initialization against setting the flag.
*/
if (smp_load_acquire(&memcg->initialized))
return memcg;
css_put(next_css);
}
prev_css = next_css; prev_css = next_css;
goto skip_node; goto skip_node;
...@@ -5549,6 +5563,7 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) ...@@ -5549,6 +5563,7 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
{ {
struct mem_cgroup *memcg = mem_cgroup_from_css(css); struct mem_cgroup *memcg = mem_cgroup_from_css(css);
struct mem_cgroup *parent = mem_cgroup_from_css(css->parent); struct mem_cgroup *parent = mem_cgroup_from_css(css->parent);
int ret;
if (css->id > MEM_CGROUP_ID_MAX) if (css->id > MEM_CGROUP_ID_MAX)
return -ENOSPC; return -ENOSPC;
...@@ -5585,7 +5600,18 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) ...@@ -5585,7 +5600,18 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
} }
mutex_unlock(&memcg_create_mutex); mutex_unlock(&memcg_create_mutex);
return memcg_init_kmem(memcg, &memory_cgrp_subsys); ret = memcg_init_kmem(memcg, &memory_cgrp_subsys);
if (ret)
return ret;
/*
* Make sure the memcg is initialized: mem_cgroup_iter()
* orders reading memcg->initialized against its callers
* reading the memcg members.
*/
smp_store_release(&memcg->initialized, 1);
return 0;
} }
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册