summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalman Qazi <sqazi@google.com>2012-06-07 01:51:35 (GMT)
committerTejun Heo <tj@kernel.org>2012-06-07 01:51:35 (GMT)
commit967db0ea65b0bf8507a7643ac8f296c4f2c0a834 (patch)
tree143a9493c9a81db130b313c0c46d87a909485541
parent71fae7e714749a52cb8be777ec014f82e8a747f4 (diff)
downloadlinux-967db0ea65b0bf8507a7643ac8f296c4f2c0a834.tar.xz
cgroup: make sure that decisions in __css_put are atomic
__css_put is using atomic_dec on the ref count, and then looking at the ref count to make decisions. This is prone to races, as someone else may decrement ref count between our decrement and our decision. Instead, we should base our decisions on the value that we decremented the ref count to. (This results in an actual race on Google's kernel which I haven't been able to reproduce on the upstream kernel. Having said that, it's still incorrect by inspection). Signed-off-by: Salman Qazi <sqazi@google.com> Acked-by: Li Zefan <lizefan@huawei.com> Signed-off-by: Tejun Heo <tj@kernel.org> Cc: stable@vger.kernel.org
-rw-r--r--kernel/cgroup.c3
1 files changed, 1 insertions, 2 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 72fcd30..ceeafe8 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4984,8 +4984,7 @@ void __css_put(struct cgroup_subsys_state *css)
struct cgroup *cgrp = css->cgroup;
rcu_read_lock();
- atomic_dec(&css->refcnt);
- switch (css_refcnt(css)) {
+ switch (atomic_dec_return(&css->refcnt)) {
case 1:
if (notify_on_release(cgrp)) {
set_bit(CGRP_RELEASABLE, &cgrp->flags);