aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-04-23 11:13:14 -0400
committerTejun Heo <tj@kernel.org>2014-04-23 11:13:14 -0400
commitaec3dfcb2e43892180ee053e8c260dcdeccf4392 (patch)
tree525148ea349802915f4918e7d97ca73ab3386d92 /kernel
parentf392e51cd6ae6f6ee5b9b6d611cdc282b4c1711e (diff)
cgroup: introduce effective cgroup_subsys_state
In the planned default unified hierarchy, controllers may get dynamically attached to and detached from a cgroup and a cgroup may not have csses for all the controllers associated with the hierarchy. When a cgroup doesn't have its own css for a given controller, the css of the nearest ancestor with the controller enabled will be used, which is called the effective css. This patch introduces cgroup_e_css() and for_each_e_css() to access the effective csses and convert compare_css_sets(), find_existing_css_set() and cgroup_migrate() to use the effective csses so that they can handle cgroups with partial csses correctly. This means that for two css_sets to be considered identical, they should have both matching csses and cgroups. compare_css_sets() already compares both, not for correctness but for optimization. As this now becomes a matter of correctness, update the comments accordingly. For all !default hierarchies, cgroup_e_css() always equals cgroup_css(), so this patch doesn't change behavior. While at it, fix incorrect locking comment for for_each_css(). Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup.c83
1 files changed, 64 insertions, 19 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index f944619077f4..4eb2dd1bb5b1 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -208,6 +208,34 @@ static struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp,
208 return &cgrp->dummy_css; 208 return &cgrp->dummy_css;
209} 209}
210 210
211/**
212 * cgroup_e_css - obtain a cgroup's effective css for the specified subsystem
213 * @cgrp: the cgroup of interest
214 * @ss: the subsystem of interest (%NULL returns the dummy_css)
215 *
216 * Similar to cgroup_css() but returns the effctive css, which is defined
217 * as the matching css of the nearest ancestor including self which has @ss
218 * enabled. If @ss is associated with the hierarchy @cgrp is on, this
219 * function is guaranteed to return non-NULL css.
220 */
221static struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp,
222 struct cgroup_subsys *ss)
223{
224 lockdep_assert_held(&cgroup_mutex);
225
226 if (!ss)
227 return &cgrp->dummy_css;
228
229 if (!(cgrp->root->subsys_mask & (1 << ss->id)))
230 return NULL;
231
232 while (cgrp->parent &&
233 !(cgrp->parent->child_subsys_mask & (1 << ss->id)))
234 cgrp = cgrp->parent;
235
236 return cgroup_css(cgrp, ss);
237}
238
211/* convenient tests for these bits */ 239/* convenient tests for these bits */
212static inline bool cgroup_is_dead(const struct cgroup *cgrp) 240static inline bool cgroup_is_dead(const struct cgroup *cgrp)
213{ 241{
@@ -273,7 +301,7 @@ static int notify_on_release(const struct cgroup *cgrp)
273 * @ssid: the index of the subsystem, CGROUP_SUBSYS_COUNT after reaching the end 301 * @ssid: the index of the subsystem, CGROUP_SUBSYS_COUNT after reaching the end
274 * @cgrp: the target cgroup to iterate css's of 302 * @cgrp: the target cgroup to iterate css's of
275 * 303 *
276 * Should be called under cgroup_mutex. 304 * Should be called under cgroup_[tree_]mutex.
277 */ 305 */
278#define for_each_css(css, ssid, cgrp) \ 306#define for_each_css(css, ssid, cgrp) \
279 for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \ 307 for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \
@@ -284,6 +312,20 @@ static int notify_on_release(const struct cgroup *cgrp)
284 else 312 else
285 313
286/** 314/**
315 * for_each_e_css - iterate all effective css's of a cgroup
316 * @css: the iteration cursor
317 * @ssid: the index of the subsystem, CGROUP_SUBSYS_COUNT after reaching the end
318 * @cgrp: the target cgroup to iterate css's of
319 *
320 * Should be called under cgroup_[tree_]mutex.
321 */
322#define for_each_e_css(css, ssid, cgrp) \
323 for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \
324 if (!((css) = cgroup_e_css(cgrp, cgroup_subsys[(ssid)]))) \
325 ; \
326 else
327
328/**
287 * for_each_subsys - iterate all enabled cgroup subsystems 329 * for_each_subsys - iterate all enabled cgroup subsystems
288 * @ss: the iteration cursor 330 * @ss: the iteration cursor
289 * @ssid: the index of @ss, CGROUP_SUBSYS_COUNT after reaching the end 331 * @ssid: the index of @ss, CGROUP_SUBSYS_COUNT after reaching the end
@@ -452,20 +494,20 @@ static bool compare_css_sets(struct css_set *cset,
452{ 494{
453 struct list_head *l1, *l2; 495 struct list_head *l1, *l2;
454 496
455 if (memcmp(template, cset->subsys, sizeof(cset->subsys))) { 497 /*
456 /* Not all subsystems matched */ 498 * On the default hierarchy, there can be csets which are
499 * associated with the same set of cgroups but different csses.
500 * Let's first ensure that csses match.
501 */
502 if (memcmp(template, cset->subsys, sizeof(cset->subsys)))
457 return false; 503 return false;
458 }
459 504
460 /* 505 /*
461 * Compare cgroup pointers in order to distinguish between 506 * Compare cgroup pointers in order to distinguish between
462 * different cgroups in heirarchies with no subsystems. We 507 * different cgroups in hierarchies. As different cgroups may
463 * could get by with just this check alone (and skip the 508 * share the same effective css, this comparison is always
464 * memcmp above) but on most setups the memcmp check will 509 * necessary.
465 * avoid the need for this more expensive check on almost all
466 * candidates.
467 */ 510 */
468
469 l1 = &cset->cgrp_links; 511 l1 = &cset->cgrp_links;
470 l2 = &old_cset->cgrp_links; 512 l2 = &old_cset->cgrp_links;
471 while (1) { 513 while (1) {
@@ -530,13 +572,16 @@ static struct css_set *find_existing_css_set(struct css_set *old_cset,
530 */ 572 */
531 for_each_subsys(ss, i) { 573 for_each_subsys(ss, i) {
532 if (root->subsys_mask & (1UL << i)) { 574 if (root->subsys_mask & (1UL << i)) {
533 /* Subsystem is in this hierarchy. So we want 575 /*
534 * the subsystem state from the new 576 * @ss is in this hierarchy, so we want the
535 * cgroup */ 577 * effective css from @cgrp.
536 template[i] = cgroup_css(cgrp, ss); 578 */
579 template[i] = cgroup_e_css(cgrp, ss);
537 } else { 580 } else {
538 /* Subsystem is not in this hierarchy, so we 581 /*
539 * don't want to change the subsystem state */ 582 * @ss is not in this hierarchy, so we don't want
583 * to change the css.
584 */
540 template[i] = old_cset->subsys[i]; 585 template[i] = old_cset->subsys[i];
541 } 586 }
542 } 587 }
@@ -1969,7 +2014,7 @@ static int cgroup_migrate(struct cgroup *cgrp, struct task_struct *leader,
1969 return 0; 2014 return 0;
1970 2015
1971 /* check that we can legitimately attach to the cgroup */ 2016 /* check that we can legitimately attach to the cgroup */
1972 for_each_css(css, i, cgrp) { 2017 for_each_e_css(css, i, cgrp) {
1973 if (css->ss->can_attach) { 2018 if (css->ss->can_attach) {
1974 ret = css->ss->can_attach(css, &tset); 2019 ret = css->ss->can_attach(css, &tset);
1975 if (ret) { 2020 if (ret) {
@@ -1999,7 +2044,7 @@ static int cgroup_migrate(struct cgroup *cgrp, struct task_struct *leader,
1999 */ 2044 */
2000 tset.csets = &tset.dst_csets; 2045 tset.csets = &tset.dst_csets;
2001 2046
2002 for_each_css(css, i, cgrp) 2047 for_each_e_css(css, i, cgrp)
2003 if (css->ss->attach) 2048 if (css->ss->attach)
2004 css->ss->attach(css, &tset); 2049 css->ss->attach(css, &tset);
2005 2050
@@ -2007,7 +2052,7 @@ static int cgroup_migrate(struct cgroup *cgrp, struct task_struct *leader,
2007 goto out_release_tset; 2052 goto out_release_tset;
2008 2053
2009out_cancel_attach: 2054out_cancel_attach:
2010 for_each_css(css, i, cgrp) { 2055 for_each_e_css(css, i, cgrp) {
2011 if (css == failed_css) 2056 if (css == failed_css)
2012 break; 2057 break;
2013 if (css->ss->cancel_attach) 2058 if (css->ss->cancel_attach)