]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cgroup: add support for StartupAllowedCPUs and StartupAllowedMemoryNodes
authorPeter Morrow <pemorrow@linux.microsoft.com>
Tue, 14 Sep 2021 16:14:53 +0000 (17:14 +0100)
committerPeter Morrow <pemorrow@linux.microsoft.com>
Wed, 15 Sep 2021 08:30:12 +0000 (09:30 +0100)
Add new settings which can be used to control cpuset based cpu affinity
during the startup phase only.

Signed-off-by: Peter Morrow <pemorrow@linux.microsoft.com>
src/core/cgroup.c
src/core/cgroup.h
src/core/dbus-cgroup.c
src/core/load-fragment-gperf.gperf.in
src/core/load-fragment.c
src/core/load-fragment.h
src/shared/bus-unit-util.c

index 2d136793f90dee1365f1ff2e3abc500f5609a72a..17e93d7af17731e1dd881a73f262649b49352af0 100644 (file)
@@ -251,7 +251,9 @@ void cgroup_context_done(CGroupContext *c) {
         c->restrict_network_interfaces = set_free(c->restrict_network_interfaces);
 
         cpu_set_reset(&c->cpuset_cpus);
+        cpu_set_reset(&c->startup_cpuset_cpus);
         cpu_set_reset(&c->cpuset_mems);
+        cpu_set_reset(&c->startup_cpuset_mems);
 }
 
 static int unit_get_kernel_memory_limit(Unit *u, const char *file, uint64_t *ret) {
@@ -386,7 +388,7 @@ static char *format_cgroup_memory_limit_comparison(char *buf, size_t l, Unit *u,
 }
 
 void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
-        _cleanup_free_ char *disable_controllers_str = NULL, *cpuset_cpus = NULL, *cpuset_mems = NULL;
+        _cleanup_free_ char *disable_controllers_str = NULL, *cpuset_cpus = NULL, *cpuset_mems = NULL, *startup_cpuset_cpus = NULL, *startup_cpuset_mems = NULL;
         CGroupIODeviceLimit *il;
         CGroupIODeviceWeight *iw;
         CGroupIODeviceLatency *l;
@@ -415,7 +417,9 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
         (void) cg_mask_to_string(c->disable_controllers, &disable_controllers_str);
 
         cpuset_cpus = cpu_set_to_range_string(&c->cpuset_cpus);
+        startup_cpuset_cpus = cpu_set_to_range_string(&c->startup_cpuset_cpus);
         cpuset_mems = cpu_set_to_range_string(&c->cpuset_mems);
+        startup_cpuset_mems = cpu_set_to_range_string(&c->startup_cpuset_mems);
 
         fprintf(f,
                 "%sCPUAccounting: %s\n"
@@ -431,7 +435,9 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
                 "%sCPUQuotaPerSecSec: %s\n"
                 "%sCPUQuotaPeriodSec: %s\n"
                 "%sAllowedCPUs: %s\n"
+                "%sStartupAllowedCPUs: %s\n"
                 "%sAllowedMemoryNodes: %s\n"
+                "%sStartupAllowedMemoryNodes: %s\n"
                 "%sIOWeight: %" PRIu64 "\n"
                 "%sStartupIOWeight: %" PRIu64 "\n"
                 "%sBlockIOWeight: %" PRIu64 "\n"
@@ -465,7 +471,9 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
                 prefix, FORMAT_TIMESPAN(c->cpu_quota_per_sec_usec, 1),
                 prefix, FORMAT_TIMESPAN(c->cpu_quota_period_usec, 1),
                 prefix, strempty(cpuset_cpus),
+                prefix, strempty(startup_cpuset_cpus),
                 prefix, strempty(cpuset_mems),
+                prefix, strempty(startup_cpuset_mems),
                 prefix, c->io_weight,
                 prefix, c->startup_io_weight,
                 prefix, c->blockio_weight,
@@ -827,6 +835,14 @@ static bool cgroup_context_has_cpu_shares(CGroupContext *c) {
                 c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID;
 }
 
+static bool cgroup_context_has_allowed_cpus(CGroupContext *c) {
+        return c->cpuset_cpus.set || c->startup_cpuset_cpus.set;
+}
+
+static bool cgroup_context_has_allowed_mems(CGroupContext *c) {
+        return c->cpuset_mems.set || c->startup_cpuset_mems.set;
+}
+
 static uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state) {
         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
             c->startup_cpu_weight != CGROUP_WEIGHT_INVALID)
@@ -847,6 +863,22 @@ static uint64_t cgroup_context_cpu_shares(CGroupContext *c, ManagerState state)
                 return CGROUP_CPU_SHARES_DEFAULT;
 }
 
+static CPUSet *cgroup_context_allowed_cpus(CGroupContext *c, ManagerState state) {
+        if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
+            c->startup_cpuset_cpus.set)
+                return &c->startup_cpuset_cpus;
+        else
+                return &c->cpuset_cpus;
+}
+
+static CPUSet *cgroup_context_allowed_mems(CGroupContext *c, ManagerState state) {
+        if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
+            c->startup_cpuset_mems.set)
+                return &c->startup_cpuset_mems;
+        else
+                return &c->cpuset_mems;
+}
+
 usec_t cgroup_cpu_adjust_period(usec_t period, usec_t quota, usec_t resolution, usec_t max_period) {
         /* kernel uses a minimum resolution of 1ms, so both period and (quota * period)
          * need to be higher than that boundary. quota is specified in USecPerSec.
@@ -1302,8 +1334,8 @@ static void cgroup_context_apply(
         }
 
         if ((apply_mask & CGROUP_MASK_CPUSET) && !is_local_root) {
-                cgroup_apply_unified_cpuset(u, &c->cpuset_cpus, "cpuset.cpus");
-                cgroup_apply_unified_cpuset(u, &c->cpuset_mems, "cpuset.mems");
+                cgroup_apply_unified_cpuset(u, cgroup_context_allowed_cpus(c, state), "cpuset.cpus");
+                cgroup_apply_unified_cpuset(u, cgroup_context_allowed_mems(c, state), "cpuset.mems");
         }
 
         /* The 'io' controller attributes are not exported on the host's root cgroup (being a pure cgroup v2
@@ -1627,7 +1659,7 @@ static CGroupMask unit_get_cgroup_mask(Unit *u) {
             c->cpu_quota_per_sec_usec != USEC_INFINITY)
                 mask |= CGROUP_MASK_CPU;
 
-        if (c->cpuset_cpus.set || c->cpuset_mems.set)
+        if (cgroup_context_has_allowed_cpus(c) || cgroup_context_has_allowed_mems(c))
                 mask |= CGROUP_MASK_CPUSET;
 
         if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c))
index 9bb968b6c15d1cd8efdac90290f4706df85a8023..951ddda525a92bc3b01ba295626a5941cacd1c67 100644 (file)
@@ -131,7 +131,9 @@ struct CGroupContext {
         usec_t cpu_quota_period_usec;
 
         CPUSet cpuset_cpus;
+        CPUSet startup_cpuset_cpus;
         CPUSet cpuset_mems;
+        CPUSet startup_cpuset_mems;
 
         uint64_t io_weight;
         uint64_t startup_io_weight;
index ef7d529de9bef509e999b558f0aed8fd58d3205f..f0d8759e8517fcca53607fc805b82f595d31db61 100644 (file)
@@ -461,7 +461,9 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
         SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
         SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_period_usec), 0),
         SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_cpus), 0),
+        SD_BUS_PROPERTY("StartupAllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, startup_cpuset_cpus), 0),
         SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_mems), 0),
+        SD_BUS_PROPERTY("StartupAllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, startup_cpuset_mems), 0),
         SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
         SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
         SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
@@ -1169,7 +1171,7 @@ int bus_cgroup_set_property(
 
                 return 1;
 
-        } else if (STR_IN_SET(name, "AllowedCPUs", "AllowedMemoryNodes")) {
+        } else if (STR_IN_SET(name, "AllowedCPUs", "StartupAllowedCPUs", "AllowedMemoryNodes", "StartupAllowedMemoryNodes")) {
                 const void *a;
                 size_t n;
                 _cleanup_(cpu_set_reset) CPUSet new_set = {};
@@ -1184,7 +1186,7 @@ int bus_cgroup_set_property(
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *setstr = NULL;
-                        CPUSet *set;
+                        CPUSet *set = NULL;
 
                         setstr = cpu_set_to_range_string(&new_set);
                         if (!setstr)
@@ -1192,8 +1194,14 @@ int bus_cgroup_set_property(
 
                         if (streq(name, "AllowedCPUs"))
                                 set = &c->cpuset_cpus;
-                        else
+                        else if (streq(name, "StartupAllowedCPUs"))
+                                set = &c->startup_cpuset_cpus;
+                        else if (streq(name, "AllowedMemoryNodes"))
                                 set = &c->cpuset_mems;
+                        else if (streq(name, "StartupAllowedMemoryNodes"))
+                                set = &c->startup_cpuset_mems;
+
+                        assert(set);
 
                         cpu_set_reset(set);
                         *set = new_set;
index b3dc3bc0fcb10c9921f80d68a44fd921bce1aa7c..17c43005bcae7bc67641422d5e2b9bfeda2c94cf 100644 (file)
 
 {%- macro CGROUP_CONTEXT_CONFIG_ITEMS(type) -%}
 {{type}}.Slice,                            config_parse_unit_slice,                     0,                                  0
-{{type}}.AllowedCPUs,                      config_parse_allowed_cpus,                   0,                                  offsetof({{type}}, cgroup_context)
-{{type}}.AllowedMemoryNodes,               config_parse_allowed_mems,                   0,                                  offsetof({{type}}, cgroup_context)
+{{type}}.AllowedCPUs,                      config_parse_allowed_cpuset,                 0,                                  offsetof({{type}}, cgroup_context.cpuset_cpus)
+{{type}}.StartupAllowedCPUs,               config_parse_allowed_cpuset,                 0,                                  offsetof({{type}}, cgroup_context.startup_cpuset_cpus)
+{{type}}.AllowedMemoryNodes,               config_parse_allowed_cpuset,                 0,                                  offsetof({{type}}, cgroup_context.cpuset_mems)
+{{type}}.StartupAllowedMemoryNodes,        config_parse_allowed_cpuset,                 0,                                  offsetof({{type}}, cgroup_context.startup_cpuset_mems)
 {{type}}.CPUAccounting,                    config_parse_bool,                           0,                                  offsetof({{type}}, cgroup_context.cpu_accounting)
 {{type}}.CPUWeight,                        config_parse_cg_weight,                      0,                                  offsetof({{type}}, cgroup_context.cpu_weight)
 {{type}}.StartupCPUWeight,                 config_parse_cg_weight,                      0,                                  offsetof({{type}}, cgroup_context.startup_cpu_weight)
index 1c8159a235506730e4b62e5ea688690bf4fc98df..220f11f8259cf3587d83986355aecddeb2db17de 100644 (file)
@@ -3616,7 +3616,7 @@ int config_parse_cpu_quota(
         return 0;
 }
 
-int config_parse_allowed_cpus(
+int config_parse_allowed_cpuset(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -3628,29 +3628,9 @@ int config_parse_allowed_cpus(
                 void *data,
                 void *userdata) {
 
-        CGroupContext *c = data;
-
-        (void) parse_cpu_set_extend(rvalue, &c->cpuset_cpus, true, unit, filename, line, lvalue);
-
-        return 0;
-}
-
-int config_parse_allowed_mems(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        CGroupContext *c = data;
-
-        (void) parse_cpu_set_extend(rvalue, &c->cpuset_mems, true, unit, filename, line, lvalue);
+        CPUSet *c = data;
 
+        (void) parse_cpu_set_extend(rvalue, c, true, unit, filename, line, lvalue);
         return 0;
 }
 
index fe98091ee47c4cf50b0c599dd774977ae0445f5e..0d8863aa6353fe128988b819e98da60e769ceaa7 100644 (file)
@@ -101,8 +101,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_set_status);
 CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv);
 CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems);
 CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
-CONFIG_PARSER_PROTOTYPE(config_parse_allowed_cpus);
-CONFIG_PARSER_PROTOTYPE(config_parse_allowed_mems);
+CONFIG_PARSER_PROTOTYPE(config_parse_allowed_cpuset);
 CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
 CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
 CONFIG_PARSER_PROTOTYPE(config_parse_bus_name);
index 669d0df0589b319444cdbbf5835c765fa1d6fbce..f9637ac0cce872173a6cd3d75061d484ca7da40f 100644 (file)
@@ -474,7 +474,9 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
                 return bus_append_cg_cpu_shares_parse(m, field, eq);
 
         if (STR_IN_SET(field, "AllowedCPUs",
-                              "AllowedMemoryNodes")) {
+                              "StartupAllowedCPUs",
+                              "AllowedMemoryNodes",
+                              "StartupAllowedMemoryNodes")) {
                 _cleanup_(cpu_set_reset) CPUSet cpuset = {};
                 _cleanup_free_ uint8_t *array = NULL;
                 size_t allocated;