Commit aec3dfcb2e43892180ee053e8c260dcdeccf4392

Authored by Tejun Heo
1 parent f392e51cd6

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

... ... @@ -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)