|
@@ -292,6 +292,9 @@ struct mem_cgroup {
|
|
|
/* vmpressure notifications */
|
|
|
struct vmpressure vmpressure;
|
|
|
|
|
|
+ /* css_online() has been completed */
|
|
|
+ int initialized;
|
|
|
+
|
|
|
/*
|
|
|
* the counter to account for mem+swap usage.
|
|
|
*/
|
|
@@ -1099,10 +1102,21 @@ skip_node:
|
|
|
* skipping css reference should be safe.
|
|
|
*/
|
|
|
if (next_css) {
|
|
|
- if ((next_css == &root->css) ||
|
|
|
- ((next_css->flags & CSS_ONLINE) &&
|
|
|
- css_tryget_online(next_css)))
|
|
|
- return mem_cgroup_from_css(next_css);
|
|
|
+ struct mem_cgroup *memcg = mem_cgroup_from_css(next_css);
|
|
|
+
|
|
|
+ if (next_css == &root->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;
|
|
|
goto skip_node;
|
|
@@ -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 *parent = mem_cgroup_from_css(css->parent);
|
|
|
+ int ret;
|
|
|
|
|
|
if (css->id > MEM_CGROUP_ID_MAX)
|
|
|
return -ENOSPC;
|
|
@@ -5585,7 +5600,18 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
|
|
|
}
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
/*
|