aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-05-16 13:22:48 -0400
committerTejun Heo <tj@kernel.org>2014-05-16 13:22:48 -0400
commitea280e7b408ca0dad195ce9836feccdd1dc32131 (patch)
tree524a648df41fbd7dc270c225212d96d10b5a7815 /mm/memcontrol.c
parentf61c42a7d9119a8b72b9607ba8e3a34111f81d8c (diff)
memcg: update memcg_has_children() to use css_next_child()
Currently, memcg_has_children() and mem_cgroup_hierarchy_write() directly test cgroup->children for list emptiness. It's semantically correct in traditional hierarchies as it actually wants to test for any children dead or alive; however, cgroup->children is not a published field and scheduled to go away. This patch moves out .use_hierarchy test out of memcg_has_children() and updates it to use css_next_child() to test whether there exists any children. With .use_hierarchy test moved out, it can also be used by mem_cgroup_hierarchy_write(). A side note: As .use_hierarchy is going away, it doesn't really matter but I'm not sure about how it's used in __memcg_activate_kmem(). The condition tested by memcg_has_children() is mushy when seen from userland as its result is affected by dead csses which aren't visible from userland. I think the rule would be a lot clearer if we have a dedicated "freshly minted" flag which gets cleared when the first task is migrated into it or the first child is created and then gate activation with that. v2: Added comment noting that testing use_hierarchy is the responsibility of the callers of memcg_has_children() as suggested by Michal Hocko. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Michal Hocko <mhocko@suse.cz> Acked-by: Li Zefan <lizefan@huawei.com> Cc: Johannes Weiner <hannes@cmpxchg.org>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 6144a8e7283f..b6f91d61b3af 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -4834,18 +4834,28 @@ static void mem_cgroup_reparent_charges(struct mem_cgroup *memcg)
4834 } while (usage > 0); 4834 } while (usage > 0);
4835} 4835}
4836 4836
4837/*
4838 * Test whether @memcg has children, dead or alive. Note that this
4839 * function doesn't care whether @memcg has use_hierarchy enabled and
4840 * returns %true if there are child csses according to the cgroup
4841 * hierarchy. Testing use_hierarchy is the caller's responsiblity.
4842 */
4837static inline bool memcg_has_children(struct mem_cgroup *memcg) 4843static inline bool memcg_has_children(struct mem_cgroup *memcg)
4838{ 4844{
4839 lockdep_assert_held(&memcg_create_mutex); 4845 bool ret;
4846
4840 /* 4847 /*
4841 * The lock does not prevent addition or deletion to the list 4848 * The lock does not prevent addition or deletion of children, but
4842 * of children, but it prevents a new child from being 4849 * it prevents a new child from being initialized based on this
4843 * initialized based on this parent in css_online(), so it's 4850 * parent in css_online(), so it's enough to decide whether
4844 * enough to decide whether hierarchically inherited 4851 * hierarchically inherited attributes can still be changed or not.
4845 * attributes can still be changed or not.
4846 */ 4852 */
4847 return memcg->use_hierarchy && 4853 lockdep_assert_held(&memcg_create_mutex);
4848 !list_empty(&memcg->css.cgroup->children); 4854
4855 rcu_read_lock();
4856 ret = css_next_child(NULL, &memcg->css);
4857 rcu_read_unlock();
4858 return ret;
4849} 4859}
4850 4860
4851/* 4861/*
@@ -4919,7 +4929,7 @@ static int mem_cgroup_hierarchy_write(struct cgroup_subsys_state *css,
4919 */ 4929 */
4920 if ((!parent_memcg || !parent_memcg->use_hierarchy) && 4930 if ((!parent_memcg || !parent_memcg->use_hierarchy) &&
4921 (val == 1 || val == 0)) { 4931 (val == 1 || val == 0)) {
4922 if (list_empty(&memcg->css.cgroup->children)) 4932 if (!memcg_has_children(memcg))
4923 memcg->use_hierarchy = val; 4933 memcg->use_hierarchy = val;
4924 else 4934 else
4925 retval = -EBUSY; 4935 retval = -EBUSY;
@@ -5036,7 +5046,8 @@ static int __memcg_activate_kmem(struct mem_cgroup *memcg,
5036 * of course permitted. 5046 * of course permitted.
5037 */ 5047 */
5038 mutex_lock(&memcg_create_mutex); 5048 mutex_lock(&memcg_create_mutex);
5039 if (cgroup_has_tasks(memcg->css.cgroup) || memcg_has_children(memcg)) 5049 if (cgroup_has_tasks(memcg->css.cgroup) ||
5050 (memcg->use_hierarchy && memcg_has_children(memcg)))
5040 err = -EBUSY; 5051 err = -EBUSY;
5041 mutex_unlock(&memcg_create_mutex); 5052 mutex_unlock(&memcg_create_mutex);
5042 if (err) 5053 if (err)