aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-04-01 15:09:56 -0400
committerTejun Heo <tj@kernel.org>2012-04-01 15:09:56 -0400
commit28b4c27b8e6bb6d7ff2875281a8484f8898a87ef (patch)
tree8da3eefc6b98c46a4dbd0fd6e6d6dec6220382df /include
parent79578621b4847afdef48d19a28d00e3b188c37e1 (diff)
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.h12
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)
115 * the css has been destroyed. 115 * the css has been destroyed.
116 */ 116 */
117 117
118extern bool __css_tryget(struct cgroup_subsys_state *css);
118static inline bool css_tryget(struct cgroup_subsys_state *css) 119static inline bool css_tryget(struct cgroup_subsys_state *css)
119{ 120{
120 if (test_bit(CSS_ROOT, &css->flags)) 121 if (test_bit(CSS_ROOT, &css->flags))
121 return true; 122 return true;
122 while (!atomic_inc_not_zero(&css->refcnt)) { 123 return __css_tryget(css);
123 if (test_bit(CSS_REMOVED, &css->flags))
124 return false;
125 cpu_relax();
126 }
127 return true;
128} 124}
129 125
130/* 126/*
@@ -132,11 +128,11 @@ static inline bool css_tryget(struct cgroup_subsys_state *css)
132 * css_get() or css_tryget() 128 * css_get() or css_tryget()
133 */ 129 */
134 130
135extern void __css_put(struct cgroup_subsys_state *css, int count); 131extern void __css_put(struct cgroup_subsys_state *css);
136static inline void css_put(struct cgroup_subsys_state *css) 132static inline void css_put(struct cgroup_subsys_state *css)
137{ 133{
138 if (!test_bit(CSS_ROOT, &css->flags)) 134 if (!test_bit(CSS_ROOT, &css->flags))
139 __css_put(css, 1); 135 __css_put(css);
140} 136}
141 137
142/* bits in struct cgroup flags field */ 138/* bits in struct cgroup flags field */