diff options
| -rw-r--r-- | include/linux/cgroup-defs.h | 13 | ||||
| -rw-r--r-- | kernel/cgroup.c | 38 |
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 */ |
| 187 | static u16 cgrp_dfl_inhibit_ss_mask; | 187 | static u16 cgrp_dfl_inhibit_ss_mask; |
| 188 | 188 | ||
| 189 | /* some controllers are implicitly enabled on the default hierarchy */ | ||
| 190 | static unsigned long cgrp_dfl_implicit_ss_mask; | ||
| 191 | |||
| 189 | /* The list of hierarchy roots */ | 192 | /* The list of hierarchy roots */ |
| 190 | 193 | ||
| 191 | static LIST_HEAD(cgroup_roots); | 194 | static 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 | ||
| 3052 | static 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) { |
