cgroup: replace cgroup_has_tasks() with cgroup_is_populated()
authorTejun Heo <tj@kernel.org>
Thu, 15 Oct 2015 20:41:50 +0000 (16:41 -0400)
committerTejun Heo <tj@kernel.org>
Thu, 15 Oct 2015 20:41:50 +0000 (16:41 -0400)
Currently, cgroup_has_tasks() tests whether the target cgroup has any
css_set linked to it.  This works because a css_set's refcnt converges
with the number of tasks linked to it and thus there's no css_set
linked to a cgroup if it doesn't have any live tasks.

To help tracking resource usage of zombie tasks, putting the ref of
css_set will be separated from disassociating the task from the
css_set which means that a cgroup may have css_sets linked to it even
when it doesn't have any live tasks.

This patch replaces cgroup_has_tasks() with cgroup_is_populated()
which tests cgroup->nr_populated instead which locally counts the
number of populated css_sets.  Unlike cgroup_has_tasks(),
cgroup_is_populated() is recursive - if any of the descendants is
populated, the cgroup is populated too.  While this changes the
meaning of the test, all the existing users are okay with the change.

While at it, replace the open-coded ->populated_cnt test in
cgroup_events_show() with cgroup_is_populated().

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Li Zefan <lizefan@huawei.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
include/linux/cgroup.h
kernel/cgroup.c
kernel/cpuset.c
mm/memcontrol.c

index e9c3eac074e224b9c1484e7f5983c37927577060..bdfdb3a1a83ce3831c6aee3fc211a330bd8a0b53 100644 (file)
@@ -456,9 +456,9 @@ static inline struct cgroup *task_cgroup(struct task_struct *task,
 }
 
 /* no synchronization, the result can only be used as a hint */
-static inline bool cgroup_has_tasks(struct cgroup *cgrp)
+static inline bool cgroup_is_populated(struct cgroup *cgrp)
 {
-       return !list_empty(&cgrp->cset_links);
+       return cgrp->populated_cnt;
 }
 
 /* returns ino associated with a cgroup */
index e5231d045eb9579c7205d68b7061d4a9e83e66c1..435aa686567b235d268267a182aa729acb87cf6f 100644 (file)
@@ -3121,7 +3121,7 @@ err_undo_css:
 static int cgroup_events_show(struct seq_file *seq, void *v)
 {
        seq_printf(seq, "populated %d\n",
-                  (bool)seq_css(seq)->cgroup->populated_cnt);
+                  cgroup_is_populated(seq_css(seq)->cgroup));
        return 0;
 }
 
@@ -5558,7 +5558,7 @@ void cgroup_exit(struct task_struct *tsk)
 
 static void check_for_release(struct cgroup *cgrp)
 {
-       if (notify_on_release(cgrp) && !cgroup_has_tasks(cgrp) &&
+       if (notify_on_release(cgrp) && !cgroup_is_populated(cgrp) &&
            !css_has_online_children(&cgrp->self) && !cgroup_is_dead(cgrp))
                schedule_work(&cgrp->release_agent_work);
 }
@@ -5806,7 +5806,7 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v)
 
 static u64 releasable_read(struct cgroup_subsys_state *css, struct cftype *cft)
 {
-       return (!cgroup_has_tasks(css->cgroup) &&
+       return (!cgroup_is_populated(css->cgroup) &&
                !css_has_online_children(&css->cgroup->self));
 }
 
index e4d999929903b72ff75fba0e20297fb1a6d617db..d7ccb87a6714b17cb5b4a86232428cb7b5253799 100644 (file)
@@ -498,7 +498,7 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
         * be changed to have empty cpus_allowed or mems_allowed.
         */
        ret = -ENOSPC;
-       if ((cgroup_has_tasks(cur->css.cgroup) || cur->attach_in_progress)) {
+       if ((cgroup_is_populated(cur->css.cgroup) || cur->attach_in_progress)) {
                if (!cpumask_empty(cur->cpus_allowed) &&
                    cpumask_empty(trial->cpus_allowed))
                        goto out;
index 33c8dad6830f86b36eb8fca89f734e1b16f139a9..0ddd0ff2b52ecb0811f87dff872d9db8b4ce3579 100644 (file)
@@ -2920,7 +2920,7 @@ static int memcg_activate_kmem(struct mem_cgroup *memcg,
         * of course permitted.
         */
        mutex_lock(&memcg_create_mutex);
-       if (cgroup_has_tasks(memcg->css.cgroup) ||
+       if (cgroup_is_populated(memcg->css.cgroup) ||
            (memcg->use_hierarchy && memcg_has_children(memcg)))
                err = -EBUSY;
        mutex_unlock(&memcg_create_mutex);