diff options
author | Zefan Li <lizefan@huawei.com> | 2014-09-19 04:51:00 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-09-19 09:29:32 -0400 |
commit | a25eb52e81a40e986179a790fbb5a1f02f482b7a (patch) | |
tree | 1d88c2bfdd17f168a5c21b4038d697148187d958 /kernel/cgroup.c | |
parent | 4e2ba65068ac1d0e8c9df78a4ad787cf39640418 (diff) |
cgroup: remove CGRP_RELEASABLE flag
We call put_css_set() after setting CGRP_RELEASABLE flag in
cgroup_task_migrate(), but in other places we call it without setting
the flag. I don't see the necessity of this flag.
Moreover once the flag is set, it will never be cleared, unless writing
to the notify_on_release control file, so it can be quite confusing
if we look at the output of debug.releasable.
# mount -t cgroup -o debug xxx /cgroup
# mkdir /cgroup/child
# cat /cgroup/child/debug.releasable
0 <-- shows 0 though the cgroup is empty
# echo $$ > /cgroup/child/tasks
# cat /cgroup/child/debug.releasable
0
# echo $$ > /cgroup/tasks && echo $$ > /cgroup/child/tasks
# cat /proc/child/debug.releasable
1 <-- shows 1 though the cgroup is not empty
This patch removes the flag, and now debug.releasable shows if the
cgroup is empty or not.
Signed-off-by: Zefan Li <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 40 |
1 files changed, 13 insertions, 27 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index df7733b48d2e..16e3a4f5c9dc 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -329,14 +329,6 @@ bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor) | |||
329 | return false; | 329 | return false; |
330 | } | 330 | } |
331 | 331 | ||
332 | static int cgroup_is_releasable(const struct cgroup *cgrp) | ||
333 | { | ||
334 | const int bits = | ||
335 | (1 << CGRP_RELEASABLE) | | ||
336 | (1 << CGRP_NOTIFY_ON_RELEASE); | ||
337 | return (cgrp->flags & bits) == bits; | ||
338 | } | ||
339 | |||
340 | static int notify_on_release(const struct cgroup *cgrp) | 332 | static int notify_on_release(const struct cgroup *cgrp) |
341 | { | 333 | { |
342 | return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | 334 | return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); |
@@ -491,7 +483,7 @@ static unsigned long css_set_hash(struct cgroup_subsys_state *css[]) | |||
491 | return key; | 483 | return key; |
492 | } | 484 | } |
493 | 485 | ||
494 | static void put_css_set_locked(struct css_set *cset, bool taskexit) | 486 | static void put_css_set_locked(struct css_set *cset) |
495 | { | 487 | { |
496 | struct cgrp_cset_link *link, *tmp_link; | 488 | struct cgrp_cset_link *link, *tmp_link; |
497 | struct cgroup_subsys *ss; | 489 | struct cgroup_subsys *ss; |
@@ -517,11 +509,7 @@ static void put_css_set_locked(struct css_set *cset, bool taskexit) | |||
517 | /* @cgrp can't go away while we're holding css_set_rwsem */ | 509 | /* @cgrp can't go away while we're holding css_set_rwsem */ |
518 | if (list_empty(&cgrp->cset_links)) { | 510 | if (list_empty(&cgrp->cset_links)) { |
519 | cgroup_update_populated(cgrp, false); | 511 | cgroup_update_populated(cgrp, false); |
520 | if (notify_on_release(cgrp)) { | 512 | check_for_release(cgrp); |
521 | if (taskexit) | ||
522 | set_bit(CGRP_RELEASABLE, &cgrp->flags); | ||
523 | check_for_release(cgrp); | ||
524 | } | ||
525 | } | 513 | } |
526 | 514 | ||
527 | kfree(link); | 515 | kfree(link); |
@@ -530,7 +518,7 @@ static void put_css_set_locked(struct css_set *cset, bool taskexit) | |||
530 | kfree_rcu(cset, rcu_head); | 518 | kfree_rcu(cset, rcu_head); |
531 | } | 519 | } |
532 | 520 | ||
533 | static void put_css_set(struct css_set *cset, bool taskexit) | 521 | static void put_css_set(struct css_set *cset) |
534 | { | 522 | { |
535 | /* | 523 | /* |
536 | * Ensure that the refcount doesn't hit zero while any readers | 524 | * Ensure that the refcount doesn't hit zero while any readers |
@@ -541,7 +529,7 @@ static void put_css_set(struct css_set *cset, bool taskexit) | |||
541 | return; | 529 | return; |
542 | 530 | ||
543 | down_write(&css_set_rwsem); | 531 | down_write(&css_set_rwsem); |
544 | put_css_set_locked(cset, taskexit); | 532 | put_css_set_locked(cset); |
545 | up_write(&css_set_rwsem); | 533 | up_write(&css_set_rwsem); |
546 | } | 534 | } |
547 | 535 | ||
@@ -2037,8 +2025,7 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp, | |||
2037 | * task. As trading it for new_cset is protected by cgroup_mutex, | 2025 | * task. As trading it for new_cset is protected by cgroup_mutex, |
2038 | * we're safe to drop it here; it will be freed under RCU. | 2026 | * we're safe to drop it here; it will be freed under RCU. |
2039 | */ | 2027 | */ |
2040 | set_bit(CGRP_RELEASABLE, &old_cgrp->flags); | 2028 | put_css_set_locked(old_cset); |
2041 | put_css_set_locked(old_cset, false); | ||
2042 | } | 2029 | } |
2043 | 2030 | ||
2044 | /** | 2031 | /** |
@@ -2059,7 +2046,7 @@ static void cgroup_migrate_finish(struct list_head *preloaded_csets) | |||
2059 | cset->mg_src_cgrp = NULL; | 2046 | cset->mg_src_cgrp = NULL; |
2060 | cset->mg_dst_cset = NULL; | 2047 | cset->mg_dst_cset = NULL; |
2061 | list_del_init(&cset->mg_preload_node); | 2048 | list_del_init(&cset->mg_preload_node); |
2062 | put_css_set_locked(cset, false); | 2049 | put_css_set_locked(cset); |
2063 | } | 2050 | } |
2064 | up_write(&css_set_rwsem); | 2051 | up_write(&css_set_rwsem); |
2065 | } | 2052 | } |
@@ -2153,8 +2140,8 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, | |||
2153 | if (src_cset == dst_cset) { | 2140 | if (src_cset == dst_cset) { |
2154 | src_cset->mg_src_cgrp = NULL; | 2141 | src_cset->mg_src_cgrp = NULL; |
2155 | list_del_init(&src_cset->mg_preload_node); | 2142 | list_del_init(&src_cset->mg_preload_node); |
2156 | put_css_set(src_cset, false); | 2143 | put_css_set(src_cset); |
2157 | put_css_set(dst_cset, false); | 2144 | put_css_set(dst_cset); |
2158 | continue; | 2145 | continue; |
2159 | } | 2146 | } |
2160 | 2147 | ||
@@ -2163,7 +2150,7 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, | |||
2163 | if (list_empty(&dst_cset->mg_preload_node)) | 2150 | if (list_empty(&dst_cset->mg_preload_node)) |
2164 | list_add(&dst_cset->mg_preload_node, &csets); | 2151 | list_add(&dst_cset->mg_preload_node, &csets); |
2165 | else | 2152 | else |
2166 | put_css_set(dst_cset, false); | 2153 | put_css_set(dst_cset); |
2167 | } | 2154 | } |
2168 | 2155 | ||
2169 | list_splice_tail(&csets, preloaded_csets); | 2156 | list_splice_tail(&csets, preloaded_csets); |
@@ -4159,7 +4146,6 @@ static u64 cgroup_read_notify_on_release(struct cgroup_subsys_state *css, | |||
4159 | static int cgroup_write_notify_on_release(struct cgroup_subsys_state *css, | 4146 | static int cgroup_write_notify_on_release(struct cgroup_subsys_state *css, |
4160 | struct cftype *cft, u64 val) | 4147 | struct cftype *cft, u64 val) |
4161 | { | 4148 | { |
4162 | clear_bit(CGRP_RELEASABLE, &css->cgroup->flags); | ||
4163 | if (val) | 4149 | if (val) |
4164 | set_bit(CGRP_NOTIFY_ON_RELEASE, &css->cgroup->flags); | 4150 | set_bit(CGRP_NOTIFY_ON_RELEASE, &css->cgroup->flags); |
4165 | else | 4151 | else |
@@ -4806,7 +4792,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
4806 | */ | 4792 | */ |
4807 | kernfs_remove(cgrp->kn); | 4793 | kernfs_remove(cgrp->kn); |
4808 | 4794 | ||
4809 | set_bit(CGRP_RELEASABLE, &cgroup_parent(cgrp)->flags); | ||
4810 | check_for_release(cgroup_parent(cgrp)); | 4795 | check_for_release(cgroup_parent(cgrp)); |
4811 | 4796 | ||
4812 | /* put the base reference */ | 4797 | /* put the base reference */ |
@@ -5244,12 +5229,12 @@ void cgroup_exit(struct task_struct *tsk) | |||
5244 | } | 5229 | } |
5245 | 5230 | ||
5246 | if (put_cset) | 5231 | if (put_cset) |
5247 | put_css_set(cset, true); | 5232 | put_css_set(cset); |
5248 | } | 5233 | } |
5249 | 5234 | ||
5250 | static void check_for_release(struct cgroup *cgrp) | 5235 | static void check_for_release(struct cgroup *cgrp) |
5251 | { | 5236 | { |
5252 | if (cgroup_is_releasable(cgrp) && !cgroup_has_tasks(cgrp) && | 5237 | if (notify_on_release(cgrp) && !cgroup_has_tasks(cgrp) && |
5253 | !css_has_online_children(&cgrp->self) && !cgroup_is_dead(cgrp)) | 5238 | !css_has_online_children(&cgrp->self) && !cgroup_is_dead(cgrp)) |
5254 | schedule_work(&cgrp->release_agent_work); | 5239 | schedule_work(&cgrp->release_agent_work); |
5255 | } | 5240 | } |
@@ -5496,7 +5481,8 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v) | |||
5496 | 5481 | ||
5497 | static u64 releasable_read(struct cgroup_subsys_state *css, struct cftype *cft) | 5482 | static u64 releasable_read(struct cgroup_subsys_state *css, struct cftype *cft) |
5498 | { | 5483 | { |
5499 | return test_bit(CGRP_RELEASABLE, &css->cgroup->flags); | 5484 | return (!cgroup_has_tasks(css->cgroup) && |
5485 | !css_has_online_children(&css->cgroup->self)); | ||
5500 | } | 5486 | } |
5501 | 5487 | ||
5502 | static struct cftype debug_files[] = { | 5488 | static struct cftype debug_files[] = { |