hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/8424 ---------------------------------------- To support both cgroup v1 and v2 while adhering to the CGROUP_SUBSYS_COUNT limit (16), this patch introduces a mechanism to share the same SUBSYS(xcu) slot between the 'xcu' and 'freezer' subsystems. Since 'xcu' is a cgroup v2-only controller and 'freezer' is a cgroup v1-only controller, they are mutually exclusive at runtime. We introduce a new kernel command line parameter, "xcu", to control this behavior dynamically. This approach allows us to enable both CONFIG_CGROUP_XCU and CONFIG_CGROUP_FREEZER simultaneously without exceeding the subsystem limit. The behavior based on the "xcu" cmdline parameter is as follows: 1. xcu=disable, cgroup v1: - The legacy 'frezzer' subsystem is active and functional. - The 'xcu' subsystem remains dormant. 2. xcu=enable, cgroup v1: - The 'freezer' subsystem is effectively disabled/blocked. - (Note: 'xcu' is not usable in v1 mode as it is v2-only). 3. xcu=disable, cgroup v2: - The 'xcu' subsystem is not enabled in the hierarchy. 4. xcu=enable, cgroup v2: - The 'xcu' subsystem is active and usable. - The 'freezer' logic is bypassed. This ensures backward compatibility for v1 users while enabling the new functionality for v2, all within the constraints of the kernel subsystem limit. Fixes: 43bbefc53356 ("xsched: Add XCU control group implementation and its backend in xsched CFS") Signed-off-by: Liu Kai <liukai284@huawei.com> --- Documentation/scheduler/xsched.md | 6 +- arch/arm64/configs/openeuler_defconfig | 3 +- arch/x86/configs/openeuler_defconfig | 3 +- include/linux/cgroup_subsys.h | 8 +- include/linux/freezer.h | 24 ++++ kernel/cgroup/cgroup.c | 2 +- kernel/cgroup/legacy_freezer.c | 25 ++-- kernel/xsched/cgroup.c | 166 +++++++++++++++++++++++-- 8 files changed, 209 insertions(+), 28 deletions(-) diff --git a/Documentation/scheduler/xsched.md b/Documentation/scheduler/xsched.md index 11dc0c964e0a..c5e643ab35f0 100644 --- a/Documentation/scheduler/xsched.md +++ b/Documentation/scheduler/xsched.md @@ -64,11 +64,11 @@ CONFIG_CGROUP_XCU=y # 修改内核引导文件,根据实际情况编辑 vim /etc/grub2-efi.cfg -# 在XSched内核新增 cmdline 配置,关闭驱动签名校验、开启cgroup-v2 -module.sig_enforce=0 systemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all +# 在XSched内核新增 cmdline 配置,关闭驱动签名校验、开启cgroup-v2,使能 xcu cgroup 子系统 +module.sig_enforce=0 systemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all xcu=enable ``` -保存引导文件后,重启切换内核 +保存引导文件后,重启切换内核,**注意!!!,xcu 子系统仅支持 cgroup-v2** ### 1.3 重编驱动 diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index fc581adb563b..622d44e6d9ff 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -101,7 +101,8 @@ CONFIG_XCU_SCHEDULER=y CONFIG_XCU_VSTREAM=y CONFIG_XSCHED_NR_CUS=128 CONFIG_XCU_SCHED_RT=y -# CONFIG_XCU_SCHED_CFS is not set +CONFIG_XCU_SCHED_CFS=y +CONFIG_CGROUP_XCU=y # # CPU/Task time and stats accounting diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index d493dbf6b8a1..e66724b15bb4 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -121,7 +121,8 @@ CONFIG_XCU_SCHEDULER=y CONFIG_XCU_VSTREAM=y CONFIG_XSCHED_NR_CUS=128 CONFIG_XCU_SCHED_RT=y -# CONFIG_XCU_SCHED_CFS is not set +CONFIG_XCU_SCHED_CFS=y +CONFIG_CGROUP_XCU=y # # CPU/Task time and stats accounting diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index e65ae90946c2..9ee14c9cab33 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -33,7 +33,9 @@ SUBSYS(memory) SUBSYS(devices) #endif -#if IS_ENABLED(CONFIG_CGROUP_FREEZER) +#if IS_ENABLED(CONFIG_CGROUP_XCU) +SUBSYS(xcu) +#elif IS_ENABLED(CONFIG_CGROUP_FREEZER) SUBSYS(freezer) #endif @@ -61,10 +63,6 @@ SUBSYS(pids) SUBSYS(rdma) #endif -#if IS_ENABLED(CONFIG_CGROUP_XCU) -SUBSYS(xcu) -#endif - #if IS_ENABLED(CONFIG_CGROUP_MISC) SUBSYS(misc) #endif diff --git a/include/linux/freezer.h b/include/linux/freezer.h index b303472255be..0c7a6da03d43 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -10,6 +10,10 @@ #include <linux/atomic.h> #include <linux/jump_label.h> +#ifdef CONFIG_CGROUP_XCU +#include <linux/cgroup-defs.h> +#endif + #ifdef CONFIG_FREEZER DECLARE_STATIC_KEY_FALSE(freezer_active); @@ -87,4 +91,24 @@ static inline void set_freezable(void) {} #endif /* !CONFIG_FREEZER */ +/* + * When CONFIG_CGROUP_XCU is enabled, freezer_cgrp_subsys and xcu_cgrp_subsys + * share the same set of cgroup_subsys hook functions. Consequently, the hooks for + * freezer_cgrp_subsys must be exposed externally to allow linkage with the XCU + * cgroup_subsys. + * + */ +#ifdef CONFIG_CGROUP_XCU +#define freezer_cgrp_id xcu_cgrp_id + +extern struct cftype files[]; +struct cgroup_subsys_state * +freezer_css_alloc(struct cgroup_subsys_state *parent_css); +int freezer_css_online(struct cgroup_subsys_state *css); +void freezer_css_offline(struct cgroup_subsys_state *css); +void freezer_css_free(struct cgroup_subsys_state *css); +void freezer_attach(struct cgroup_taskset *tset); +void freezer_fork(struct task_struct *task); +#endif /* CONFIG_CGROUP_XCU */ + #endif /* FREEZER_H_INCLUDED */ diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 17521bc192ee..04301432e84a 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -6256,7 +6256,7 @@ int __init cgroup_init(void) struct cgroup_subsys *ss; int ssid; - BUILD_BUG_ON(CGROUP_SUBSYS_COUNT > 17); + BUILD_BUG_ON(CGROUP_SUBSYS_COUNT > 16); BUG_ON(cgroup_init_cftypes(NULL, cgroup_base_files)); BUG_ON(cgroup_init_cftypes(NULL, cgroup_psi_files)); BUG_ON(cgroup_init_cftypes(NULL, cgroup1_base_files)); diff --git a/kernel/cgroup/legacy_freezer.c b/kernel/cgroup/legacy_freezer.c index bee2f9ea5e4a..9ef242b73947 100644 --- a/kernel/cgroup/legacy_freezer.c +++ b/kernel/cgroup/legacy_freezer.c @@ -24,6 +24,17 @@ #include <linux/mutex.h> #include <linux/cpu.h> +/* + * The STATIC macro is used to handle this conditional visibility: + * - Enabled: interfaces are defined as non-static (exported). + * - Disabled: interfaces remain static (file-local). + */ +#ifdef CONFIG_CGROUP_XCU +#define STATIC +#else +#define STATIC static +#endif + /* * A cgroup is freezing if any FREEZING flags are set. FREEZING_SELF is * set if "FROZEN" is written to freezer.state cgroupfs file, and cleared @@ -83,7 +94,7 @@ static const char *freezer_state_strs(unsigned int state) return "THAWED"; }; -static struct cgroup_subsys_state * +STATIC struct cgroup_subsys_state * freezer_css_alloc(struct cgroup_subsys_state *parent_css) { struct freezer *freezer; @@ -103,7 +114,7 @@ freezer_css_alloc(struct cgroup_subsys_state *parent_css) * parent's freezing state while holding both parent's and our * freezer->lock. */ -static int freezer_css_online(struct cgroup_subsys_state *css) +STATIC int freezer_css_online(struct cgroup_subsys_state *css) { struct freezer *freezer = css_freezer(css); struct freezer *parent = parent_freezer(freezer); @@ -130,7 +141,7 @@ static int freezer_css_online(struct cgroup_subsys_state *css) * @css is going away. Mark it dead and decrement system_freezing_count if * it was holding one. */ -static void freezer_css_offline(struct cgroup_subsys_state *css) +STATIC void freezer_css_offline(struct cgroup_subsys_state *css) { struct freezer *freezer = css_freezer(css); @@ -146,7 +157,7 @@ static void freezer_css_offline(struct cgroup_subsys_state *css) cpus_read_unlock(); } -static void freezer_css_free(struct cgroup_subsys_state *css) +STATIC void freezer_css_free(struct cgroup_subsys_state *css) { kfree(css_freezer(css)); } @@ -160,7 +171,7 @@ static void freezer_css_free(struct cgroup_subsys_state *css) * @freezer->lock. freezer_attach() makes the new tasks conform to the * current state and all following state changes can see the new tasks. */ -static void freezer_attach(struct cgroup_taskset *tset) +STATIC void freezer_attach(struct cgroup_taskset *tset) { struct task_struct *task; struct cgroup_subsys_state *new_css; @@ -205,7 +216,7 @@ static void freezer_attach(struct cgroup_taskset *tset) * to do anything as freezer_attach() will put @task into the appropriate * state. */ -static void freezer_fork(struct task_struct *task) +STATIC void freezer_fork(struct task_struct *task) { struct freezer *freezer; @@ -449,7 +460,7 @@ static u64 freezer_parent_freezing_read(struct cgroup_subsys_state *css, return (bool)(freezer->state & CGROUP_FREEZING_PARENT); } -static struct cftype files[] = { +STATIC struct cftype files[] = { { .name = "state", .flags = CFTYPE_NOT_ON_ROOT, diff --git a/kernel/xsched/cgroup.c b/kernel/xsched/cgroup.c index 73f044475939..8a85faaa8dc4 100644 --- a/kernel/xsched/cgroup.c +++ b/kernel/xsched/cgroup.c @@ -21,6 +21,10 @@ #include <linux/xsched.h> #include <linux/delay.h> +#ifdef CONFIG_CGROUP_FREEZER +#include <linux/freezer.h> +#endif + static struct xsched_group root_xsched_group; struct xsched_group *root_xcg = &root_xsched_group; @@ -39,6 +43,61 @@ static const char xcu_sched_name[XSCHED_TYPE_NUM][SCHED_CLASS_MAX_LENGTH] = { [XSCHED_TYPE_CFS] = "cfs" }; +/* + * xcu_mode: + * 0 = disable (freezer cgroup) + * 1 = enable (xcu cgroup) + */ +static int xcu_mode; + +/** + * Parse the "xcu=" kernel command line parameter. + * + * Usage: + * xcu=enable → enable xcu_cgrp_subsys + * Otherwise → enable freezer_cgrp_subsys + * + * Returns: + * 1 (handled), 0 (not handled) + */ +static int __init xcu_setup(char *str) +{ + if (!str) + return 0; + + if (strcmp(str, "enable") == 0) + xcu_mode = 1; + + return 1; +} +__setup("xcu=", xcu_setup); + +static bool xcu_cgroup_enabled(void) +{ + return xcu_mode; +} + +/** + * xcu_cgroup_check_compat - Verify XCU mode matches the cgroup hierarchy version. + * + * Checks if the current xcu_mode aligns with the cgroup subsystem's default + * hierarchy status. + * + * IMPORTANT: cgroup_subsys_on_dfl() only returns a valid version indicator + * after the cgroup filesystem has been mounted at the root node. Calling + * this function prior to mount may yield incorrect results. + * + * Return: true if compatible, false otherwise (with a warning logged). + */ +static bool xcu_cgroup_check_compat(void) +{ + if (xcu_mode != cgroup_subsys_on_dfl(xcu_cgrp_subsys)) { + XSCHED_WARN("XCU cgrp is incompatible with the cgroup version\n"); + return false; + } + return true; +} + static int xcu_cg_set_file_show(struct xsched_group *xg, int sched_class) { if (!xg) { @@ -742,6 +801,7 @@ static struct cftype xcu_cg_files[] = { }, { .name = "stat", + .flags = CFTYPE_NOT_ON_ROOT, .seq_show = xcu_stat, }, { @@ -753,17 +813,103 @@ static struct cftype xcu_cg_files[] = { {} /* terminate */ }; +static struct cgroup_subsys_state * +xcu_freezer_compat_css_alloc(struct cgroup_subsys_state *parent_css) +{ + /* Skip allocation if XCU cmdline mismatches the cgroup version. */ + if (parent_css && !xcu_cgroup_check_compat()) + return ERR_PTR(-EPERM); + + if (xcu_cgroup_enabled()) + return xcu_css_alloc(parent_css); + +#ifdef CONFIG_CGROUP_FREEZER + return freezer_css_alloc(parent_css); +#else /* CONFIG_CGROUP_FREEZER=n xcu=disable cgroup=v1 */ + if (!parent_css) + return &root_xsched_group.css; + else + return ERR_PTR(-EPERM); +#endif +} + +static int xcu_freezer_compat_css_online(struct cgroup_subsys_state *css) +{ + if (xcu_cgroup_enabled()) + return xcu_css_online(css); + +#ifdef CONFIG_CGROUP_FREEZER + return freezer_css_online(css); +#else + return 0; +#endif +} + +static void xcu_freezer_compat_css_offline(struct cgroup_subsys_state *css) +{ + if (xcu_cgroup_enabled()) + return xcu_css_offline(css); + +#ifdef CONFIG_CGROUP_FREEZER + return freezer_css_offline(css); +#endif +} + +static void xcu_freezer_compat_css_released(struct cgroup_subsys_state *css) +{ + if (xcu_cgroup_enabled()) + return xcu_css_released(css); +} + +static void xcu_freezer_compat_css_free(struct cgroup_subsys_state *css) +{ + if (xcu_cgroup_enabled()) + return xcu_css_free(css); + +#ifdef CONFIG_CGROUP_FREEZER + return freezer_css_free(css); +#endif +} + +static int xcu_freezer_compat_can_attach(struct cgroup_taskset *tset) +{ + if (xcu_cgroup_enabled()) + return xcu_can_attach(tset); + + return 0; +} + +static void xcu_freezer_compat_cancel_attach(struct cgroup_taskset *tset) +{ + if (xcu_cgroup_enabled()) + return xcu_cancel_attach(tset); +} + +static void xcu_freezer_compat_attach(struct cgroup_taskset *tset) +{ + if (xcu_cgroup_enabled()) + return xcu_attach(tset); + +#ifdef CONFIG_CGROUP_FREEZER + return freezer_attach(tset); +#endif +} + struct cgroup_subsys xcu_cgrp_subsys = { - .css_alloc = xcu_css_alloc, - .css_online = xcu_css_online, - .css_offline = xcu_css_offline, - .css_released = xcu_css_released, - .css_free = xcu_css_free, - .can_attach = xcu_can_attach, - .cancel_attach = xcu_cancel_attach, - .attach = xcu_attach, + .css_alloc = xcu_freezer_compat_css_alloc, + .css_online = xcu_freezer_compat_css_online, + .css_offline = xcu_freezer_compat_css_offline, + .css_released = xcu_freezer_compat_css_released, + .css_free = xcu_freezer_compat_css_free, + .can_attach = xcu_freezer_compat_can_attach, + .cancel_attach = xcu_freezer_compat_cancel_attach, + .attach = xcu_freezer_compat_attach, .dfl_cftypes = xcu_cg_files, +#ifdef CONFIG_CGROUP_FREEZER + .fork = freezer_fork, + .legacy_cftypes = files, + .legacy_name = "freezer", +#else .legacy_cftypes = xcu_cg_files, - .early_init = false, - .threaded = true +#endif }; -- 2.34.1