Commit aec3dfcb2e43892180ee053e8c260dcdeccf4392
1 parent
f392e51cd6
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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>
Showing 1 changed file with 64 additions and 19 deletions Side-by-side Diff
kernel/cgroup.c
... | ... | @@ -208,6 +208,34 @@ |
208 | 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 | + */ | |
221 | +static 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 | 239 | /* convenient tests for these bits */ |
212 | 240 | static inline bool cgroup_is_dead(const struct cgroup *cgrp) |
213 | 241 | { |
... | ... | @@ -273,7 +301,7 @@ |
273 | 301 | * @ssid: the index of the subsystem, CGROUP_SUBSYS_COUNT after reaching the end |
274 | 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 | 306 | #define for_each_css(css, ssid, cgrp) \ |
279 | 307 | for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \ |
... | ... | @@ -284,6 +312,20 @@ |
284 | 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 | 329 | * for_each_subsys - iterate all enabled cgroup subsystems |
288 | 330 | * @ss: the iteration cursor |
289 | 331 | * @ssid: the index of @ss, CGROUP_SUBSYS_COUNT after reaching the end |
290 | 332 | |
291 | 333 | |
292 | 334 | |
... | ... | @@ -452,20 +494,20 @@ |
452 | 494 | { |
453 | 495 | struct list_head *l1, *l2; |
454 | 496 | |
455 | - if (memcmp(template, cset->subsys, sizeof(cset->subsys))) { | |
456 | - /* Not all subsystems matched */ | |
497 | + /* | |
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 | 503 | return false; |
458 | - } | |
459 | 504 | |
460 | 505 | /* |
461 | 506 | * Compare cgroup pointers in order to distinguish between |
462 | - * different cgroups in heirarchies with no subsystems. We | |
463 | - * could get by with just this check alone (and skip the | |
464 | - * memcmp above) but on most setups the memcmp check will | |
465 | - * avoid the need for this more expensive check on almost all | |
466 | - * candidates. | |
507 | + * different cgroups in hierarchies. As different cgroups may | |
508 | + * share the same effective css, this comparison is always | |
509 | + * necessary. | |
467 | 510 | */ |
468 | - | |
469 | 511 | l1 = &cset->cgrp_links; |
470 | 512 | l2 = &old_cset->cgrp_links; |
471 | 513 | while (1) { |
472 | 514 | |
... | ... | @@ -530,13 +572,16 @@ |
530 | 572 | */ |
531 | 573 | for_each_subsys(ss, i) { |
532 | 574 | if (root->subsys_mask & (1UL << i)) { |
533 | - /* Subsystem is in this hierarchy. So we want | |
534 | - * the subsystem state from the new | |
535 | - * cgroup */ | |
536 | - template[i] = cgroup_css(cgrp, ss); | |
575 | + /* | |
576 | + * @ss is in this hierarchy, so we want the | |
577 | + * effective css from @cgrp. | |
578 | + */ | |
579 | + template[i] = cgroup_e_css(cgrp, ss); | |
537 | 580 | } else { |
538 | - /* Subsystem is not in this hierarchy, so we | |
539 | - * don't want to change the subsystem state */ | |
581 | + /* | |
582 | + * @ss is not in this hierarchy, so we don't want | |
583 | + * to change the css. | |
584 | + */ | |
540 | 585 | template[i] = old_cset->subsys[i]; |
541 | 586 | } |
542 | 587 | } |
... | ... | @@ -1969,7 +2014,7 @@ |
1969 | 2014 | return 0; |
1970 | 2015 | |
1971 | 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 | 2018 | if (css->ss->can_attach) { |
1974 | 2019 | ret = css->ss->can_attach(css, &tset); |
1975 | 2020 | if (ret) { |
... | ... | @@ -1999,7 +2044,7 @@ |
1999 | 2044 | */ |
2000 | 2045 | tset.csets = &tset.dst_csets; |
2001 | 2046 | |
2002 | - for_each_css(css, i, cgrp) | |
2047 | + for_each_e_css(css, i, cgrp) | |
2003 | 2048 | if (css->ss->attach) |
2004 | 2049 | css->ss->attach(css, &tset); |
2005 | 2050 | |
... | ... | @@ -2007,7 +2052,7 @@ |
2007 | 2052 | goto out_release_tset; |
2008 | 2053 | |
2009 | 2054 | out_cancel_attach: |
2010 | - for_each_css(css, i, cgrp) { | |
2055 | + for_each_e_css(css, i, cgrp) { | |
2011 | 2056 | if (css == failed_css) |
2012 | 2057 | break; |
2013 | 2058 | if (css->ss->cancel_attach) |