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).
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2021-02-22 22:09:38 +01:00
parent 6c3f7ca036
commit 8ebfd50aaf
3 changed files with 47 additions and 10 deletions

View file

@ -1456,14 +1456,25 @@
<varlistentry> <varlistentry>
<term><varname>ConditionControlGroupController=</varname></term> <term><varname>ConditionControlGroupController=</varname></term>
<listitem><para>Verify that the given cgroup controller (eg. <literal>cpu</literal>) is available <listitem><para>Check whether given cgroup controllers (eg. <literal>cpu</literal>) are available
for use on the system. For example, a particular controller may not be available if it was disabled for use on the system or whether the legacy v1 cgroup or the modern v2 cgroup hierarchy is used.
on the kernel command line with <varname>cgroup_disable=controller</varname>. Multiple controllers </para>
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 <para>Multiple controllers may be passed with a space separating them; in this case the condition
are <literal>cpu</literal>, <literal>cpuacct</literal>, <literal>io</literal>, will only pass if all listed controllers are available for use. Controllers unknown to systemd are
<literal>blkio</literal>, <literal>memory</literal>, <literal>devices</literal>, and ignored. Valid controllers are <literal>cpu</literal>, <literal>cpuacct</literal>,
<literal>pids</literal>.</para> <literal>io</literal>, <literal>blkio</literal>, <literal>memory</literal>,
<literal>devices</literal>, and <literal>pids</literal>. Even if available in the kernel, a
particular controller may not be available if it was disabled on the kernel command line with
<varname>cgroup_disable=controller</varname>.</para>
<para>Alternatively, two special strings <literal>v1</literal> and <literal>v2</literal> may be
specified (without any controller names). <literal>v2</literal> will pass if the unified v2 cgroup
hierachy is used, and <literal>v1</literal> will pass if the legacy v1 hierarchy or the hybrid
hierarchy are used (see the discussion of <varname>systemd.unified_cgroup_hierarchy</varname> and
<varname>systemd.legacy_systemd_cgroup_controller</varname> in
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for more information).</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View file

@ -354,6 +354,15 @@ static int condition_test_control_group_controller(Condition *c, char **env) {
assert(c->parameter); assert(c->parameter);
assert(c->type == CONDITION_CONTROL_GROUP_CONTROLLER); 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); r = cg_mask_supported(&system_mask);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to determine supported controllers: %m"); return log_debug_errno(r, "Failed to determine supported controllers: %m");

View file

@ -124,10 +124,26 @@ static void test_condition_test_path(void) {
condition_free(condition); 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) { static void test_condition_test_control_group_controller(void) {
Condition *condition; Condition *condition;
CGroupMask system_mask; CGroupMask system_mask;
CGroupController controller;
_cleanup_free_ char *controller_name = NULL; _cleanup_free_ char *controller_name = NULL;
int r; int r;
@ -151,7 +167,7 @@ static void test_condition_test_control_group_controller(void) {
assert_se(cg_mask_supported(&system_mask) >= 0); assert_se(cg_mask_supported(&system_mask) >= 0);
/* Individual valid controllers one by one */ /* 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); const char *local_controller_name = cgroup_controller_to_string(controller);
log_info("chosen controller is '%s'", local_controller_name); log_info("chosen controller is '%s'", local_controller_name);
if (system_mask & CGROUP_CONTROLLER_TO_MASK(controller)) { 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_virtualization();
test_condition_test_user(); test_condition_test_user();
test_condition_test_group(); test_condition_test_group();
test_condition_test_control_group_hierarchy();
test_condition_test_control_group_controller(); test_condition_test_control_group_controller();
test_condition_test_cpus(); test_condition_test_cpus();
test_condition_test_memory(); test_condition_test_memory();