This can be useful when we have some controllers enabled on cgroup with sole purpose of enabling those controllers for descendant cgroups and we don't really use controller files in the intermediate cgroup. With this new infrastructure we can mark such a controller hidden and decrease number of populated files in the cgroup directory.
Let's use this to hide ve cgroup controller files on cgroup-v2 by default. Note that ve0 cgroup files remain shown, and on "container" cgroups we can un-hide ve controller files via "cgroup.controllers_hidden". The interface is similar to cgroup.subtree_control, if you write "+controller" to cgroup.controllers_hidden it would be hidden, if you write "-controller" it would be shown again. https://virtuozzo.atlassian.net/browse/VSTOR-119803 Signed-off-by: Pavel Tikhomirov <[email protected]> Feature: ve: ve generic structures --- include/linux/cgroup-defs.h | 1 + kernel/cgroup/cgroup.c | 129 ++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index d8c489a40881..8f1d15582f99 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -498,6 +498,7 @@ struct cgroup { u16 subtree_ss_mask; u16 old_subtree_control; u16 old_subtree_ss_mask; + u16 hidden_ss_mask; /* Private pointers for each registered subsystem */ struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT]; diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 26ad3faf2e21..753721edb642 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -494,6 +494,11 @@ static u16 cgroup_ss_mask(struct cgroup *cgrp) return cgrp->root->subsys_mask; } +static u16 cgroup_hidden_ss_mask(struct cgroup *cgrp) +{ + return cgrp->hidden_ss_mask; +} + /** * cgroup_css - obtain a cgroup's css for the specified subsystem * @cgrp: the cgroup of interest @@ -3420,6 +3425,15 @@ static int cgroup_subtree_control_show(struct seq_file *seq, void *v) return 0; } +/* list hidden controllers */ +static int cgroup_controllers_hidden_show(struct seq_file *seq, void *v) +{ + struct cgroup *cgrp = seq_css(seq)->cgroup; + + cgroup_print_ss_mask(seq, cgroup_hidden_ss_mask(cgrp)); + return 0; +} + /** * cgroup_update_dfl_csses - update css assoc of a subtree in default hierarchy * @cgrp: root of the subtree to update csses for @@ -3598,6 +3612,8 @@ static bool css_visible(struct cgroup_subsys_state *css) struct cgroup_subsys *ss = css->ss; struct cgroup *cgrp = css->cgroup; + if (cgroup_hidden_ss_mask(cgrp) & (1 << ss->id)) + return false; if (cgroup_control(cgrp) & (1 << ss->id)) return true; if (!(cgroup_ss_mask(cgrp) & (1 << ss->id))) @@ -3880,6 +3896,111 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, return ret ?: nbytes; } +static int cgroup_apply_hidden(struct cgroup *cgrp) +{ + struct cgroup_subsys *ss; + int ssid; + + for_each_subsys(ss, ssid) { + struct cgroup_subsys_state *css = cgroup_css(cgrp, ss); + + if (!(cgroup_ss_mask(cgrp) & (1 << ss->id))) + continue; + + if (!css) + continue; + + if (css_visible(css)) { + int ret; + + ret = css_populate_dir(css); + if (ret) + return ret; + } else { + css_clear_dir(css); + if (ss->css_reset) + ss->css_reset(css); + } + } + + return 0; +} + +/* change the hidden controllers for a cgroup in the default hierarchy */ +static ssize_t cgroup_controllers_hidden_write(struct kernfs_open_file *of, + char *buf, size_t nbytes, + loff_t off) +{ + struct cgroup_subsys *ss; + u16 hide = 0, show = 0; + struct cgroup *cgrp; + int ssid, ret; + char *tok; + + /* + * Parse input - space separated list of subsystem names prefixed + * with either + or -. + */ + buf = strstrip(buf); + while ((tok = strsep(&buf, " "))) { + if (tok[0] == '\0') + continue; + do_each_subsys_mask(ss, ssid, ~cgrp_dfl_inhibit_ss_mask) { + if (!cgroup_ssid_enabled(ssid) || + strcmp(tok + 1, ss->name)) + continue; + + if (*tok == '+') { + hide |= 1 << ssid; + show &= ~(1 << ssid); + } else if (*tok == '-') { + show |= 1 << ssid; + hide &= ~(1 << ssid); + } else { + return -EINVAL; + } + break; + } while_each_subsys_mask(); + if (ssid == CGROUP_SUBSYS_COUNT) + return -EINVAL; + } + + cgrp = cgroup_kn_lock_live(of->kn, true); + if (!cgrp) + return -ENODEV; + + for_each_subsys(ss, ssid) { + if (hide & (1 << ssid)) { + if (cgrp->hidden_ss_mask & (1 << ssid)) { + hide &= ~(1 << ssid); + continue; + } + } else if (show & (1 << ssid)) { + if (!(cgrp->hidden_ss_mask & (1 << ssid))) { + show &= ~(1 << ssid); + continue; + } + } + } + + if (!hide && !show) { + ret = 0; + goto out_unlock; + } + + cgrp->hidden_ss_mask |= hide; + cgrp->hidden_ss_mask &= ~show; + + ret = cgroup_apply_hidden(cgrp); + if (ret) + goto out_unlock; + + kernfs_activate(cgrp->kn); +out_unlock: + cgroup_kn_unlock(of->kn); + return ret ?: nbytes; +} + /** * cgroup_enable_threaded - make @cgrp threaded * @cgrp: the target cgroup @@ -5788,6 +5909,12 @@ static struct cftype cgroup_base_files[] = { .seq_show = cgroup_subtree_control_show, .write = cgroup_subtree_control_write, }, + { + .name = "cgroup.controllers_hidden", + .flags = CFTYPE_NOT_ON_ROOT | CFTYPE_NS_DELEGATABLE, + .seq_show = cgroup_controllers_hidden_show, + .write = cgroup_controllers_hidden_write, + }, { .name = "cgroup.events", .flags = CFTYPE_NOT_ON_ROOT, @@ -6266,6 +6393,8 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name, */ if (!cgroup_on_dfl(cgrp)) cgrp->subtree_control = cgroup_control(cgrp); + else + cgrp->hidden_ss_mask = 1 << ve_cgrp_id; cgroup_propagate_control(cgrp); -- 2.52.0 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
