aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup-defs.h13
-rw-r--r--kernel/cgroup.c38
2 files changed, 44 insertions, 7 deletions
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 590291d56049..34b42f03fcd8 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -451,6 +451,19 @@ struct cgroup_subsys {
451 bool early_init:1; 451 bool early_init:1;
452 452
453 /* 453 /*
454 * If %true, the controller, on the default hierarchy, doesn't show
455 * up in "cgroup.controllers" or "cgroup.subtree_control", is
456 * implicitly enabled on all cgroups on the default hierarchy, and
457 * bypasses the "no internal process" constraint. This is for
458 * utility type controllers which is transparent to userland.
459 *
460 * An implicit controller can be stolen from the default hierarchy
461 * anytime and thus must be okay with offline csses from previous
462 * hierarchies coexisting with csses for the current one.
463 */
464 bool implicit_on_dfl:1;
465
466 /*
454 * If %false, this subsystem is properly hierarchical - 467 * If %false, this subsystem is properly hierarchical -
455 * configuration, resource accounting and restriction on a parent 468 * configuration, resource accounting and restriction on a parent
456 * cgroup cover those of its children. If %true, hierarchy support 469 * cgroup cover those of its children. If %true, hierarchy support
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index fbd3e99a4e98..e22df5d81e59 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -186,6 +186,9 @@ static u16 cgroup_no_v1_mask;
186/* some controllers are not supported in the default hierarchy */ 186/* some controllers are not supported in the default hierarchy */
187static u16 cgrp_dfl_inhibit_ss_mask; 187static u16 cgrp_dfl_inhibit_ss_mask;
188 188
189/* some controllers are implicitly enabled on the default hierarchy */
190static unsigned long cgrp_dfl_implicit_ss_mask;
191
189/* The list of hierarchy roots */ 192/* The list of hierarchy roots */
190 193
191static LIST_HEAD(cgroup_roots); 194static LIST_HEAD(cgroup_roots);
@@ -359,8 +362,8 @@ static u16 cgroup_control(struct cgroup *cgrp)
359 return parent->subtree_control; 362 return parent->subtree_control;
360 363
361 if (cgroup_on_dfl(cgrp)) 364 if (cgroup_on_dfl(cgrp))
362 root_ss_mask &= ~cgrp_dfl_inhibit_ss_mask; 365 root_ss_mask &= ~(cgrp_dfl_inhibit_ss_mask |
363 366 cgrp_dfl_implicit_ss_mask);
364 return root_ss_mask; 367 return root_ss_mask;
365} 368}
366 369
@@ -1327,6 +1330,8 @@ static u16 cgroup_calc_subtree_ss_mask(u16 subtree_control, u16 this_ss_mask)
1327 1330
1328 lockdep_assert_held(&cgroup_mutex); 1331 lockdep_assert_held(&cgroup_mutex);
1329 1332
1333 cur_ss_mask |= cgrp_dfl_implicit_ss_mask;
1334
1330 while (true) { 1335 while (true) {
1331 u16 new_ss_mask = cur_ss_mask; 1336 u16 new_ss_mask = cur_ss_mask;
1332 1337
@@ -1512,8 +1517,13 @@ static int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
1512 lockdep_assert_held(&cgroup_mutex); 1517 lockdep_assert_held(&cgroup_mutex);
1513 1518
1514 do_each_subsys_mask(ss, ssid, ss_mask) { 1519 do_each_subsys_mask(ss, ssid, ss_mask) {
1515 /* if @ss has non-root csses attached to it, can't move */ 1520 /*
1516 if (css_next_child(NULL, cgroup_css(&ss->root->cgrp, ss))) 1521 * If @ss has non-root csses attached to it, can't move.
1522 * If @ss is an implicit controller, it is exempt from this
1523 * rule and can be stolen.
1524 */
1525 if (css_next_child(NULL, cgroup_css(&ss->root->cgrp, ss)) &&
1526 !ss->implicit_on_dfl)
1517 return -EBUSY; 1527 return -EBUSY;
1518 1528
1519 /* can't move between two non-dummy roots either */ 1529 /* can't move between two non-dummy roots either */
@@ -3039,6 +3049,18 @@ static void cgroup_restore_control(struct cgroup *cgrp)
3039 } 3049 }
3040} 3050}
3041 3051
3052static bool css_visible(struct cgroup_subsys_state *css)
3053{
3054 struct cgroup_subsys *ss = css->ss;
3055 struct cgroup *cgrp = css->cgroup;
3056
3057 if (cgroup_control(cgrp) & (1 << ss->id))
3058 return true;
3059 if (!(cgroup_ss_mask(cgrp) & (1 << ss->id)))
3060 return false;
3061 return cgroup_on_dfl(cgrp) && ss->implicit_on_dfl;
3062}
3063
3042/** 3064/**
3043 * cgroup_apply_control_enable - enable or show csses according to control 3065 * cgroup_apply_control_enable - enable or show csses according to control
3044 * @cgrp: root of the target subtree 3066 * @cgrp: root of the target subtree
@@ -3074,7 +3096,7 @@ static int cgroup_apply_control_enable(struct cgroup *cgrp)
3074 return PTR_ERR(css); 3096 return PTR_ERR(css);
3075 } 3097 }
3076 3098
3077 if (cgroup_control(dsct) & (1 << ss->id)) { 3099 if (css_visible(css)) {
3078 ret = css_populate_dir(css); 3100 ret = css_populate_dir(css);
3079 if (ret) 3101 if (ret)
3080 return ret; 3102 return ret;
@@ -3117,7 +3139,7 @@ static void cgroup_apply_control_disable(struct cgroup *cgrp)
3117 if (css->parent && 3139 if (css->parent &&
3118 !(cgroup_ss_mask(dsct) & (1 << ss->id))) { 3140 !(cgroup_ss_mask(dsct) & (1 << ss->id))) {
3119 kill_css(css); 3141 kill_css(css);
3120 } else if (!(cgroup_control(dsct) & (1 << ss->id))) { 3142 } else if (!css_visible(css)) {
3121 css_clear_dir(css); 3143 css_clear_dir(css);
3122 if (ss->css_reset) 3144 if (ss->css_reset)
3123 ss->css_reset(css); 3145 ss->css_reset(css);
@@ -5455,7 +5477,9 @@ int __init cgroup_init(void)
5455 5477
5456 cgrp_dfl_root.subsys_mask |= 1 << ss->id; 5478 cgrp_dfl_root.subsys_mask |= 1 << ss->id;
5457 5479
5458 if (!ss->dfl_cftypes) 5480 if (ss->implicit_on_dfl)
5481 cgrp_dfl_implicit_ss_mask |= 1 << ss->id;
5482 else if (!ss->dfl_cftypes)
5459 cgrp_dfl_inhibit_ss_mask |= 1 << ss->id; 5483 cgrp_dfl_inhibit_ss_mask |= 1 << ss->id;
5460 5484
5461 if (ss->dfl_cftypes == ss->legacy_cftypes) { 5485 if (ss->dfl_cftypes == ss->legacy_cftypes) {