diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e1b3d0fead05f507860426a9dc9393ec078b11d2..2cb4b541985237489ca884cec1d64ada2fde6d8f 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -346,6 +346,32 @@ static struct cgroup *cgroup_parent(struct cgroup *cgrp) return NULL; } +/* subsystems visibly enabled on a cgroup */ +static u16 cgroup_control(struct cgroup *cgrp) +{ + struct cgroup *parent = cgroup_parent(cgrp); + u16 root_ss_mask = cgrp->root->subsys_mask; + + if (parent) + return parent->subtree_control; + + if (cgroup_on_dfl(cgrp)) + root_ss_mask &= ~cgrp_dfl_inhibit_ss_mask; + + return root_ss_mask; +} + +/* subsystems enabled on a cgroup */ +static u16 cgroup_ss_mask(struct cgroup *cgrp) +{ + struct cgroup *parent = cgroup_parent(cgrp); + + if (parent) + return parent->subtree_ss_mask; + + return cgrp->root->subsys_mask; +} + /** * cgroup_css - obtain a cgroup's css for the specified subsystem * @cgrp: the cgroup of interest @@ -385,16 +411,15 @@ static struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp, if (!ss) return &cgrp->self; - if (!(cgrp->root->subsys_mask & (1 << ss->id))) - return NULL; - /* * This function is used while updating css associations and thus - * can't test the csses directly. Use ->subtree_ss_mask. + * can't test the csses directly. Test ss_mask. */ - while (cgroup_parent(cgrp) && - !(cgroup_parent(cgrp)->subtree_ss_mask & (1 << ss->id))) + while (!(cgroup_ss_mask(cgrp) & (1 << ss->id))) { cgrp = cgroup_parent(cgrp); + if (!cgrp) + return NULL; + } return cgroup_css(cgrp, ss); } @@ -1276,7 +1301,6 @@ static umode_t cgroup_file_mode(const struct cftype *cft) */ static u16 cgroup_calc_subtree_ss_mask(struct cgroup *cgrp, u16 subtree_control) { - struct cgroup *parent = cgroup_parent(cgrp); u16 cur_ss_mask = subtree_control; struct cgroup_subsys *ss; int ssid; @@ -1298,10 +1322,7 @@ static u16 cgroup_calc_subtree_ss_mask(struct cgroup *cgrp, u16 subtree_control) * happen only if some depended-upon subsystems were bound * to non-default hierarchies. */ - if (parent) - new_ss_mask &= parent->subtree_ss_mask; - else - new_ss_mask &= cgrp->root->subsys_mask; + new_ss_mask &= cgroup_ss_mask(cgrp); if (new_ss_mask == cur_ss_mask) break; @@ -2864,22 +2885,12 @@ static void cgroup_print_ss_mask(struct seq_file *seq, u16 ss_mask) seq_putc(seq, '\n'); } -/* show controllers which are currently attached to the default hierarchy */ -static int cgroup_root_controllers_show(struct seq_file *seq, void *v) -{ - struct cgroup *cgrp = seq_css(seq)->cgroup; - - cgroup_print_ss_mask(seq, cgrp->root->subsys_mask & - ~cgrp_dfl_inhibit_ss_mask); - return 0; -} - /* show controllers which are enabled from the parent */ static int cgroup_controllers_show(struct seq_file *seq, void *v) { struct cgroup *cgrp = seq_css(seq)->cgroup; - cgroup_print_ss_mask(seq, cgroup_parent(cgrp)->subtree_control); + cgroup_print_ss_mask(seq, cgroup_control(cgrp)); return 0; } @@ -3005,10 +3016,7 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, continue; } - /* unavailable or not enabled on the parent? */ - if (!(cgrp_dfl_root.subsys_mask & (1 << ssid)) || - (cgroup_parent(cgrp) && - !(cgroup_parent(cgrp)->subtree_control & (1 << ssid)))) { + if (!(cgroup_control(cgrp) & (1 << ssid))) { ret = -ENOENT; goto out_unlock; } @@ -4566,12 +4574,6 @@ static struct cftype cgroup_dfl_base_files[] = { }, { .name = "cgroup.controllers", - .flags = CFTYPE_ONLY_ON_ROOT, - .seq_show = cgroup_root_controllers_show, - }, - { - .name = "cgroup.controllers", - .flags = CFTYPE_NOT_ON_ROOT, .seq_show = cgroup_controllers_show, }, { @@ -4945,7 +4947,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent) cgroup_idr_replace(&root->cgroup_idr, cgrp, cgrp->id); /* create the csses */ - do_each_subsys_mask(ss, ssid, parent->subtree_ss_mask) { + do_each_subsys_mask(ss, ssid, cgroup_ss_mask(cgrp)) { struct cgroup_subsys_state *css; css = css_create(cgrp, ss); @@ -4960,7 +4962,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent) * subtree_control from the parent. Each is configured manually. */ if (!cgroup_on_dfl(cgrp)) { - cgrp->subtree_control = parent->subtree_control; + cgrp->subtree_control = cgroup_control(cgrp); cgroup_refresh_subtree_ss_mask(cgrp); } @@ -5020,7 +5022,7 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, if (ret) goto out_destroy; - do_each_subsys_mask(ss, ssid, parent->subtree_control) { + do_each_subsys_mask(ss, ssid, cgroup_control(cgrp)) { ret = css_populate_dir(cgroup_css(cgrp, ss), NULL); if (ret) goto out_destroy;