diff options
author | Tejun Heo <tj@kernel.org> | 2012-04-01 12:09:56 -0700 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-04-01 12:09:56 -0700 |
commit | 28b4c27b8e6bb6d7ff2875281a8484f8898a87ef (patch) | |
tree | 8da3eefc6b98c46a4dbd0fd6e6d6dec6220382df /include | |
parent | 79578621b4847afdef48d19a28d00e3b188c37e1 (diff) | |
download | linux-28b4c27b8e6bb6d7ff2875281a8484f8898a87ef.tar.gz linux-28b4c27b8e6bb6d7ff2875281a8484f8898a87ef.tar.bz2 linux-28b4c27b8e6bb6d7ff2875281a8484f8898a87ef.zip |
cgroup: use negative bias on css->refcnt to block css_tryget()
When a cgroup is about to be removed, cgroup_clear_css_refs() is
called to check and ensure that there are no active css references.
This is currently achieved by dropping the refcnt to zero iff it has
only the base ref. If all css refs could be dropped to zero, ref
clearing is successful and CSS_REMOVED is set on all css. If not, the
base ref is restored. While css ref is zero w/o CSS_REMOVED set, any
css_tryget() attempt on it busy loops so that they are atomic
w.r.t. the whole css ref clearing.
This does work but dropping and re-instating the base ref is somewhat
hairy and makes it difficult to add more logic to the put path as
there are two of them - the regular css_put() and the reversible base
ref clearing.
This patch updates css ref clearing such that blocking new
css_tryget() and putting the base ref are separate operations.
CSS_DEACT_BIAS, defined as INT_MIN, is added to css->refcnt and
css_tryget() busy loops while refcnt is negative. After all css refs
are deactivated, if they were all one, ref clearing succeeded and
CSS_REMOVED is set and the base ref is put using the regular
css_put(); otherwise, CSS_DEACT_BIAS is subtracted from the refcnts
and the original postive values are restored.
css_refcnt() accessor which always returns the unbiased positive
reference counts is added and used to simplify refcnt usages. While
at it, relocate and reformat comments in cgroup_has_css_refs().
This separates css->refcnt deactivation and putting the base ref,
which enables the next patch to make ref clearing optional.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/cgroup.h | 12 |
1 files changed, 4 insertions, 8 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 028478c6e0c5..be81fafae11f 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -115,16 +115,12 @@ static inline bool css_is_removed(struct cgroup_subsys_state *css) * the css has been destroyed. */ +extern bool __css_tryget(struct cgroup_subsys_state *css); static inline bool css_tryget(struct cgroup_subsys_state *css) { if (test_bit(CSS_ROOT, &css->flags)) return true; - while (!atomic_inc_not_zero(&css->refcnt)) { - if (test_bit(CSS_REMOVED, &css->flags)) - return false; - cpu_relax(); - } - return true; + return __css_tryget(css); } /* @@ -132,11 +128,11 @@ static inline bool css_tryget(struct cgroup_subsys_state *css) * css_get() or css_tryget() */ -extern void __css_put(struct cgroup_subsys_state *css, int count); +extern void __css_put(struct cgroup_subsys_state *css); static inline void css_put(struct cgroup_subsys_state *css) { if (!test_bit(CSS_ROOT, &css->flags)) - __css_put(css, 1); + __css_put(css); } /* bits in struct cgroup flags field */ |