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) {
}
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;
(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"
"%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"
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,
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)
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.
}
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
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))
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;
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),
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 = {};
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)
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;
{%- 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)
return 0;
}
-int config_parse_allowed_cpus(
+int config_parse_allowed_cpuset(
const char *unit,
const char *filename,
unsigned line,
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;
}
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);
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;