|
@@ -864,9 +864,15 @@ static void mem_cgroup_update_soft_limit(struct mem_cgroup *memcg)
|
|
|
/*
|
|
|
* Necessary to update all ancestors when hierarchy is used
|
|
|
* because their event counter is not touched.
|
|
|
+ * We track children even outside the hierarchy for the root
|
|
|
+ * cgroup because tree walk starting at root should visit
|
|
|
+ * all cgroups and we want to prevent from pointless tree
|
|
|
+ * walk if no children is below the limit.
|
|
|
*/
|
|
|
while (delta && (parent = parent_mem_cgroup(parent)))
|
|
|
atomic_add(delta, &parent->children_in_excess);
|
|
|
+ if (memcg != root_mem_cgroup && !root_mem_cgroup->use_hierarchy)
|
|
|
+ atomic_add(delta, &root_mem_cgroup->children_in_excess);
|
|
|
spin_unlock(&memcg->soft_lock);
|
|
|
}
|
|
|
|
|
@@ -6043,6 +6049,9 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
|
|
|
if (memcg->soft_contributed) {
|
|
|
while ((memcg = parent_mem_cgroup(memcg)))
|
|
|
atomic_dec(&memcg->children_in_excess);
|
|
|
+
|
|
|
+ if (memcg != root_mem_cgroup && !root_mem_cgroup->use_hierarchy)
|
|
|
+ atomic_dec(&root_mem_cgroup->children_in_excess);
|
|
|
}
|
|
|
mem_cgroup_destroy_all_caches(memcg);
|
|
|
vmpressure_cleanup(&memcg->vmpressure);
|