Skip to content

Commit f6d635a

Browse files
committed
cgroup: implement cgroup_subsys->implicit_on_dfl
Some controllers, perf_event for now and possibly freezer in the future, don't really make sense to control explicitly through "cgroup.subtree_control". For example, the primary role of perf_event is identifying the cgroups of tasks; however, because the controller also keeps a small amount of state per cgroup, it can't be replaced with simple cgroup membership tests. This patch implements cgroup_subsys->implicit_on_dfl flag. When set, the controller is implicitly enabled on all cgroups on the v2 hierarchy so that utility type controllers such as perf_event can be enabled and function transparently. An implicit controller doesn't show up in "cgroup.controllers" or "cgroup.subtree_control", is exempt from no internal process rule and can be stolen from the default hierarchy even if there are non-root csses. v2: Reimplemented on top of the recent updates to css handling and subsystem rebinding. Rebinding implicit subsystems is now a simple matter of exempting it from the busy subsystem check. Signed-off-by: Tejun Heo <tj@kernel.org>
1 parent e485798 commit f6d635a

File tree

2 files changed

+44
-7
lines changed

2 files changed

+44
-7
lines changed

include/linux/cgroup-defs.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,19 @@ struct cgroup_subsys {
450450

451451
bool early_init:1;
452452

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+
453466
/*
454467
* If %false, this subsystem is properly hierarchical -
455468
* configuration, resource accounting and restriction on a parent

kernel/cgroup.c

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ static u16 cgroup_no_v1_mask;
186186
/* some controllers are not supported in the default hierarchy */
187187
static u16 cgrp_dfl_inhibit_ss_mask;
188188

189+
/* some controllers are implicitly enabled on the default hierarchy */
190+
static unsigned long cgrp_dfl_implicit_ss_mask;
191+
189192
/* The list of hierarchy roots */
190193

191194
static LIST_HEAD(cgroup_roots);
@@ -359,8 +362,8 @@ static u16 cgroup_control(struct cgroup *cgrp)
359362
return parent->subtree_control;
360363

361364
if (cgroup_on_dfl(cgrp))
362-
root_ss_mask &= ~cgrp_dfl_inhibit_ss_mask;
363-
365+
root_ss_mask &= ~(cgrp_dfl_inhibit_ss_mask |
366+
cgrp_dfl_implicit_ss_mask);
364367
return root_ss_mask;
365368
}
366369

@@ -1327,6 +1330,8 @@ static u16 cgroup_calc_subtree_ss_mask(u16 subtree_control, u16 this_ss_mask)
13271330

13281331
lockdep_assert_held(&cgroup_mutex);
13291332

1333+
cur_ss_mask |= cgrp_dfl_implicit_ss_mask;
1334+
13301335
while (true) {
13311336
u16 new_ss_mask = cur_ss_mask;
13321337

@@ -1512,8 +1517,13 @@ static int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
15121517
lockdep_assert_held(&cgroup_mutex);
15131518

15141519
do_each_subsys_mask(ss, ssid, ss_mask) {
1515-
/* if @ss has non-root csses attached to it, can't move */
1516-
if (css_next_child(NULL, cgroup_css(&ss->root->cgrp, ss)))
1520+
/*
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)
15171527
return -EBUSY;
15181528

15191529
/* can't move between two non-dummy roots either */
@@ -3039,6 +3049,18 @@ static void cgroup_restore_control(struct cgroup *cgrp)
30393049
}
30403050
}
30413051

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+
30423064
/**
30433065
* cgroup_apply_control_enable - enable or show csses according to control
30443066
* @cgrp: root of the target subtree
@@ -3074,7 +3096,7 @@ static int cgroup_apply_control_enable(struct cgroup *cgrp)
30743096
return PTR_ERR(css);
30753097
}
30763098

3077-
if (cgroup_control(dsct) & (1 << ss->id)) {
3099+
if (css_visible(css)) {
30783100
ret = css_populate_dir(css);
30793101
if (ret)
30803102
return ret;
@@ -3117,7 +3139,7 @@ static void cgroup_apply_control_disable(struct cgroup *cgrp)
31173139
if (css->parent &&
31183140
!(cgroup_ss_mask(dsct) & (1 << ss->id))) {
31193141
kill_css(css);
3120-
} else if (!(cgroup_control(dsct) & (1 << ss->id))) {
3142+
} else if (!css_visible(css)) {
31213143
css_clear_dir(css);
31223144
if (ss->css_reset)
31233145
ss->css_reset(css);
@@ -5455,7 +5477,9 @@ int __init cgroup_init(void)
54555477

54565478
cgrp_dfl_root.subsys_mask |= 1 << ss->id;
54575479

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)
54595483
cgrp_dfl_inhibit_ss_mask |= 1 << ss->id;
54605484

54615485
if (ss->dfl_cftypes == ss->legacy_cftypes) {

0 commit comments

Comments
 (0)