|
@@ -4959,31 +4959,18 @@ static void mem_cgroup_reparent_charges(struct mem_cgroup *memcg)
|
|
|
} while (usage > 0);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * This mainly exists for tests during the setting of set of use_hierarchy.
|
|
|
- * Since this is the very setting we are changing, the current hierarchy value
|
|
|
- * is meaningless
|
|
|
- */
|
|
|
-static inline bool __memcg_has_children(struct mem_cgroup *memcg)
|
|
|
-{
|
|
|
- struct cgroup_subsys_state *pos;
|
|
|
-
|
|
|
- /* bounce at first found */
|
|
|
- css_for_each_child(pos, &memcg->css)
|
|
|
- return true;
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Must be called with memcg_create_mutex held, unless the cgroup is guaranteed
|
|
|
- * to be already dead (as in mem_cgroup_force_empty, for instance). This is
|
|
|
- * from mem_cgroup_count_children(), in the sense that we don't really care how
|
|
|
- * many children we have; we only need to know if we have any. It also counts
|
|
|
- * any memcg without hierarchy as infertile.
|
|
|
- */
|
|
|
static inline bool memcg_has_children(struct mem_cgroup *memcg)
|
|
|
{
|
|
|
- return memcg->use_hierarchy && __memcg_has_children(memcg);
|
|
|
+ lockdep_assert_held(&memcg_create_mutex);
|
|
|
+ /*
|
|
|
+ * The lock does not prevent addition or deletion to the list
|
|
|
+ * of children, but it prevents a new child from being
|
|
|
+ * initialized based on this parent in css_online(), so it's
|
|
|
+ * enough to decide whether hierarchically inherited
|
|
|
+ * attributes can still be changed or not.
|
|
|
+ */
|
|
|
+ return memcg->use_hierarchy &&
|
|
|
+ !list_empty(&memcg->css.cgroup->children);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -5063,7 +5050,7 @@ static int mem_cgroup_hierarchy_write(struct cgroup_subsys_state *css,
|
|
|
*/
|
|
|
if ((!parent_memcg || !parent_memcg->use_hierarchy) &&
|
|
|
(val == 1 || val == 0)) {
|
|
|
- if (!__memcg_has_children(memcg))
|
|
|
+ if (list_empty(&memcg->css.cgroup->children))
|
|
|
memcg->use_hierarchy = val;
|
|
|
else
|
|
|
retval = -EBUSY;
|