From 8ebfd50aaf5503de0e77e7786095760030458e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Mon, 22 Feb 2021 22:09:38 +0100 Subject: [PATCH] shared/condition: add ConditionControlGroupController=v1|v2 Before, we only allowed conditionalizing on controllers, not the hierarchy. This commit extends this to allow a simple check for v1 (i.e. classic or hybrid), and v2 (full unified). An alternative approach would be to add a separate Condition for this, but I'm not too keen on that, considering that v1 is already being deprecrecated (c.f. 82f3063218). --- man/systemd.unit.xml | 27 +++++++++++++++++++-------- src/shared/condition.c | 9 +++++++++ src/test/test-condition.c | 21 +++++++++++++++++++-- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 333449097f4..cd9437c509d 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -1456,14 +1456,25 @@ ConditionControlGroupController= - Verify that the given cgroup controller (eg. cpu) is available - for use on the system. For example, a particular controller may not be available if it was disabled - on the kernel command line with cgroup_disable=controller. Multiple controllers - may be passed with a space separating them; in this case the condition will only pass if all listed - controllers are available for use. Controllers unknown to systemd are ignored. Valid controllers - are cpu, cpuacct, io, - blkio, memory, devices, and - pids. + Check whether given cgroup controllers (eg. cpu) are available + for use on the system or whether the legacy v1 cgroup or the modern v2 cgroup hierarchy is used. + + + Multiple controllers may be passed with a space separating them; in this case the condition + will only pass if all listed controllers are available for use. Controllers unknown to systemd are + ignored. Valid controllers are cpu, cpuacct, + io, blkio, memory, + devices, and pids. Even if available in the kernel, a + particular controller may not be available if it was disabled on the kernel command line with + cgroup_disable=controller. + + Alternatively, two special strings v1 and v2 may be + specified (without any controller names). v2 will pass if the unified v2 cgroup + hierachy is used, and v1 will pass if the legacy v1 hierarchy or the hybrid + hierarchy are used (see the discussion of systemd.unified_cgroup_hierarchy and + systemd.legacy_systemd_cgroup_controller in + systemd.service5 + for more information). diff --git a/src/shared/condition.c b/src/shared/condition.c index 1e63956c05f..d84377c269e 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -354,6 +354,15 @@ static int condition_test_control_group_controller(Condition *c, char **env) { assert(c->parameter); assert(c->type == CONDITION_CONTROL_GROUP_CONTROLLER); + if (streq(c->parameter, "v2")) + return cg_all_unified(); + if (streq(c->parameter, "v1")) { + r = cg_all_unified(); + if (r < 0) + return r; + return !r; + } + r = cg_mask_supported(&system_mask); if (r < 0) return log_debug_errno(r, "Failed to determine supported controllers: %m"); diff --git a/src/test/test-condition.c b/src/test/test-condition.c index 25483d015b3..3fe961f60b5 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -124,10 +124,26 @@ static void test_condition_test_path(void) { condition_free(condition); } +static void test_condition_test_control_group_hierarchy(void) { + Condition *condition; + int r; + + r = cg_unified(); + + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "v1", false, false); + assert_se(condition); + assert_se(condition_test(condition, environ) == (r < CGROUP_UNIFIED_ALL)); + condition_free(condition); + + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "v2", false, false); + assert_se(condition); + assert_se(condition_test(condition, environ) == (r >= CGROUP_UNIFIED_ALL)); + condition_free(condition); +} + static void test_condition_test_control_group_controller(void) { Condition *condition; CGroupMask system_mask; - CGroupController controller; _cleanup_free_ char *controller_name = NULL; int r; @@ -151,7 +167,7 @@ static void test_condition_test_control_group_controller(void) { assert_se(cg_mask_supported(&system_mask) >= 0); /* Individual valid controllers one by one */ - for (controller = 0; controller < _CGROUP_CONTROLLER_MAX; controller++) { + for (CGroupController controller = 0; controller < _CGROUP_CONTROLLER_MAX; controller++) { const char *local_controller_name = cgroup_controller_to_string(controller); log_info("chosen controller is '%s'", local_controller_name); if (system_mask & CGROUP_CONTROLLER_TO_MASK(controller)) { @@ -881,6 +897,7 @@ int main(int argc, char *argv[]) { test_condition_test_virtualization(); test_condition_test_user(); test_condition_test_group(); + test_condition_test_control_group_hierarchy(); test_condition_test_control_group_controller(); test_condition_test_cpus(); test_condition_test_memory();