diff options
Diffstat (limited to 'core-cgroup-support-cpuset.patch')
-rw-r--r-- | core-cgroup-support-cpuset.patch | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/core-cgroup-support-cpuset.patch b/core-cgroup-support-cpuset.patch new file mode 100644 index 0000000..84560b6 --- /dev/null +++ b/core-cgroup-support-cpuset.patch @@ -0,0 +1,615 @@ +From 8fc496f1e5b6d71d29eb446e02f6317bdc45c7c2 Mon Sep 17 00:00:00 2001 +From: licunlong <licunlong1@huawei.com> +Date: Thu, 6 May 2021 09:38:54 +0800 +Subject: [PATCH] core-cgroup: support cpuset + +This patch add support for cpuset subsystem. +--- + meson.build | 2 + + meson_options.txt | 3 + + src/basic/cgroup-util.h | 8 ++- + src/basic/string-util.c | 42 +++++++++++ + src/basic/string-util.h | 1 + + src/core/cgroup.c | 62 ++++++++++++++++- + src/core/cgroup.h | 6 ++ + src/core/dbus-cgroup.c | 42 +++++++++++ + src/core/dbus-manager.c | 1 + + src/core/load-fragment-gperf.gperf.in | 5 ++ + src/core/load-fragment.c | 69 +++++++++++++++++++ + src/core/load-fragment.h | 1 + + src/core/main.c | 1 + + src/core/manager.c | 2 + + src/core/manager.h | 1 + + src/core/system.conf.in | 1 + + src/core/unit.c | 1 + + src/shared/bus-unit-util.c | 15 +++- + src/shared/cpu-set-util.c | 1 + + src/test/test-cgroup-mask.c | 1 + + .../fuzz-unit-file/directives-all.service | 5 ++ + 21 files changed, 264 insertions(+), 6 deletions(-) + +diff --git a/meson.build b/meson.build +index 7419e2b..614013b 100644 +--- a/meson.build ++++ b/meson.build +@@ -1578,6 +1578,7 @@ foreach term : ['analyze', + 'binfmt', + 'compat-mutable-uid-boundaries', + 'coredump', ++ 'cpuset-cgv1', + 'efi', + 'environment-d', + 'firstboot', +@@ -2853,6 +2854,7 @@ foreach tuple : [ + ['fexecve'], + ['standalone-binaries', get_option('standalone-binaries')], + ['coverage', get_option('b_coverage')], ++ ['cpuset-cgv1'], + ] + + if tuple.length() >= 2 +diff --git a/meson_options.txt b/meson_options.txt +index e708745..5fda5d9 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -514,3 +514,6 @@ option('bpf-compiler', type : 'combo', choices : ['clang', 'gcc'], + description: 'compiler used to build BPF programs') + option('bpf-framework', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' }, + description: 'build BPF programs from source code in restricted C') ++ ++option('cpuset-cgv1', type : 'boolean', value : 'true', ++ description : 'enable cgroup v1 cpuset support') +diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h +index 6ab14c7..831f8ce 100644 +--- a/src/basic/cgroup-util.h ++++ b/src/basic/cgroup-util.h +@@ -22,7 +22,7 @@ typedef enum CGroupController { + /* Original cgroup controllers */ + CGROUP_CONTROLLER_CPU, + CGROUP_CONTROLLER_CPUACCT, /* v1 only */ +- CGROUP_CONTROLLER_CPUSET, /* v2 only */ ++ CGROUP_CONTROLLER_CPUSET, + CGROUP_CONTROLLER_IO, /* v2 only */ + CGROUP_CONTROLLER_BLKIO, /* v1 only */ + CGROUP_CONTROLLER_MEMORY, +@@ -62,7 +62,11 @@ typedef enum CGroupMask { + CGROUP_MASK_BPF_RESTRICT_NETWORK_INTERFACES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_RESTRICT_NETWORK_INTERFACES), + + /* All real cgroup v1 controllers */ +- CGROUP_MASK_V1 = CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT|CGROUP_MASK_BLKIO|CGROUP_MASK_MEMORY|CGROUP_MASK_DEVICES|CGROUP_MASK_PIDS, ++ CGROUP_MASK_V1 = CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT|CGROUP_MASK_BLKIO|CGROUP_MASK_MEMORY|CGROUP_MASK_DEVICES|CGROUP_MASK_PIDS ++#if ENABLE_CPUSET_CGV1 ++ | CGROUP_MASK_CPUSET ++#endif ++ , + + /* All real cgroup v2 controllers */ + CGROUP_MASK_V2 = CGROUP_MASK_CPU|CGROUP_MASK_CPUSET|CGROUP_MASK_IO|CGROUP_MASK_MEMORY|CGROUP_MASK_PIDS, +diff --git a/src/basic/string-util.c b/src/basic/string-util.c +index 7329bfa..0fecb40 100644 +--- a/src/basic/string-util.c ++++ b/src/basic/string-util.c +@@ -1295,6 +1295,48 @@ int string_contains_word_strv(const char *string, const char *separators, char * + return !!found; + } + ++int string_isvalid_interval(const char *instr) ++{ ++ const char *pstr = instr; /* tmp */ ++ const char *pstr_front = instr; /* front char */ ++ const char *pstr_behind = instr; /* behind char */ ++ ++ if (isempty(instr)) ++ { ++ return 1; ++ } ++ ++ while (*pstr != '\0') ++ { ++ /* behind */ ++ pstr_behind = pstr + 1; ++ ++ /* 0-3,4,6,7-10 */ ++ if (((*pstr < '0') || (*pstr > '9')) && ++ (*pstr != '-') && ++ (*pstr != ',')) ++ { ++ return 2; ++ } ++ ++ /* - , must is a num */ ++ if (('-' == *pstr) || (',' == *pstr)) ++ { ++ if ((*pstr_front < '0') || (*pstr_front > '9') || ++ (*pstr_behind < '0') || (*pstr_behind > '9')) ++ { ++ return 3; ++ } ++ } ++ ++ /* front */ ++ pstr_front = pstr; ++ pstr++; ++ } ++ ++ return 0; ++} ++ + bool streq_skip_trailing_chars(const char *s1, const char *s2, const char *ok) { + if (!s1 && !s2) + return true; +diff --git a/src/basic/string-util.h b/src/basic/string-util.h +index b6d8be3..c6773d3 100644 +--- a/src/basic/string-util.h ++++ b/src/basic/string-util.h +@@ -270,6 +270,7 @@ static inline int string_contains_word(const char *string, const char *separator + return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL); + } + ++int string_isvalid_interval(const char *instr); + bool streq_skip_trailing_chars(const char *s1, const char *s2, const char *ok); + + char *string_replace_char(char *str, char old_char, char new_char); +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 78bc551..3154fd3 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -293,6 +293,12 @@ void cgroup_context_done(CGroupContext *c) { + + c->restrict_network_interfaces = set_free_free(c->restrict_network_interfaces); + ++ if (c->cpuset_cpus_v1) ++ c->cpuset_cpus_v1 = mfree(c->cpuset_cpus_v1); ++ ++ if (c->cpuset_mems_v1) ++ c->cpuset_mems_v1 = mfree(c->cpuset_mems_v1); ++ + cpu_set_reset(&c->cpuset_cpus); + cpu_set_reset(&c->startup_cpuset_cpus); + cpu_set_reset(&c->cpuset_mems); +@@ -535,6 +541,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { + "%sIOAccounting: %s\n" + "%sBlockIOAccounting: %s\n" + "%sMemoryAccounting: %s\n" ++ "%sCPUSetAccounting: %s\n" + "%sTasksAccounting: %s\n" + "%sIPAccounting: %s\n" + "%sCPUWeight: %" PRIu64 "\n" +@@ -565,6 +572,10 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { + "%sMemoryZSwapMax: %" PRIu64 "%s\n" + "%sStartupMemoryZSwapMax: %" PRIu64 "%s\n" + "%sMemoryLimit: %" PRIu64 "\n" ++ "%sCPUSetCpus=%s\n" ++ "%sCPUSetMems=%s\n" ++ "%sCPUSetCloneChildren=%s\n" ++ "%sCPUSetMemMigrate=%s\n" + "%sTasksMax: %" PRIu64 "\n" + "%sDevicePolicy: %s\n" + "%sDisableControllers: %s\n" +@@ -579,6 +590,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { + prefix, yes_no(c->io_accounting), + prefix, yes_no(c->blockio_accounting), + prefix, yes_no(c->memory_accounting), ++ prefix, yes_no(c->cpuset_accounting), + prefix, yes_no(c->tasks_accounting), + prefix, yes_no(c->ip_accounting), + prefix, c->cpu_weight, +@@ -609,6 +621,10 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { + prefix, c->memory_zswap_max, format_cgroup_memory_limit_comparison(cdj, sizeof(cdj), u, "MemoryZSwapMax"), + prefix, c->startup_memory_zswap_max, format_cgroup_memory_limit_comparison(cdk, sizeof(cdk), u, "StartupMemoryZSwapMax"), + prefix, c->memory_limit, ++ prefix, c->cpuset_cpus_v1, ++ prefix, c->cpuset_mems_v1, ++ prefix, yes_no(c->cpuset_clone_children), ++ prefix, yes_no(c->cpuset_memory_migrate), + prefix, cgroup_tasks_max_resolve(&c->tasks_max), + prefix, cgroup_device_policy_to_string(c->device_policy), + prefix, strempty(disable_controllers_str), +@@ -1728,8 +1744,47 @@ static void cgroup_context_apply( + } + + if ((apply_mask & CGROUP_MASK_CPUSET) && !is_local_root) { +- 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"); ++ if (cg_all_unified() == 0) { ++ (void) set_attribute_and_warn(u, "cpuset", "cgroup.clone_children", one_zero(c->cpuset_clone_children)); ++ (void) set_attribute_and_warn(u, "cpuset", "cpuset.memory_migrate", one_zero(c->cpuset_memory_migrate)); ++ if (c->cpuset_cpus_v1) { ++ if (streq(c->cpuset_cpus_v1, "all")) { ++ _cleanup_free_ char *str_cpuset_cpus = NULL; ++ _cleanup_free_ char *cg_root_path_cpus = NULL; ++ r = cg_get_root_path(&cg_root_path_cpus); ++ if (r < 0) ++ log_info_errno(r, "Failed to determine root cgroup, ignoring cgroup cpuset cpus: %m"); ++ if (cg_root_path_cpus) { ++ r = cg_get_attribute("cpuset", cg_root_path_cpus, "cpuset.cpus", &str_cpuset_cpus); ++ if (r < 0) ++ log_error("cgroup context apply: cg get attribute is error(%d), path=%s.", r, cg_root_path_cpus); ++ if (str_cpuset_cpus) ++ (void) set_attribute_and_warn(u, "cpuset", "cpuset.cpus", str_cpuset_cpus); ++ } ++ } else ++ (void) set_attribute_and_warn(u, "cpuset", "cpuset.cpus", c->cpuset_cpus_v1); ++ } ++ if (c->cpuset_mems_v1) { ++ if (streq(c->cpuset_mems_v1, "all")) { ++ _cleanup_free_ char *str_cpuset_mems = NULL; ++ _cleanup_free_ char *cg_root_path_mems = NULL; ++ r = cg_get_root_path(&cg_root_path_mems); ++ if (r < 0) ++ log_info_errno(r, "Failed to determine root cgroup, ignoring cgroup cpuset mems: %m"); ++ if (cg_root_path_mems) { ++ r = cg_get_attribute("cpuset", cg_root_path_mems, "cpuset.mems", &str_cpuset_mems); ++ if (r < 0) ++ log_error("cgroup context apply: cg get attribute is error(%d), path=%s.", r, cg_root_path_mems); ++ if (str_cpuset_mems) ++ (void) set_attribute_and_warn(u, "cpuset", "cpuset.mems", str_cpuset_mems); ++ } ++ } else ++ (void) set_attribute_and_warn(u, "cpuset", "cpuset.mems", c->cpuset_mems_v1); ++ } ++ } else { ++ 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 +@@ -2044,7 +2099,8 @@ static CGroupMask unit_get_cgroup_mask(Unit *u) { + c->cpu_quota_per_sec_usec != USEC_INFINITY) + mask |= CGROUP_MASK_CPU; + +- if (cgroup_context_has_allowed_cpus(c) || cgroup_context_has_allowed_mems(c)) ++ if (cgroup_context_has_allowed_cpus(c) || cgroup_context_has_allowed_mems(c) || ++ c->cpuset_accounting || c->cpuset_cpus_v1 || c->cpuset_mems_v1) + mask |= CGROUP_MASK_CPUSET; + + if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c)) +diff --git a/src/core/cgroup.h b/src/core/cgroup.h +index f1b674b..a4bd959 100644 +--- a/src/core/cgroup.h ++++ b/src/core/cgroup.h +@@ -134,6 +134,7 @@ struct CGroupContext { + bool io_accounting; + bool blockio_accounting; + bool memory_accounting; ++ bool cpuset_accounting; + bool tasks_accounting; + bool ip_accounting; + +@@ -177,6 +178,11 @@ struct CGroupContext { + uint64_t memory_zswap_max; + uint64_t startup_memory_zswap_max; + ++ char *cpuset_cpus_v1; ++ char *cpuset_mems_v1; ++ bool cpuset_clone_children; ++ bool cpuset_memory_migrate; ++ + bool default_memory_min_set:1; + bool default_memory_low_set:1; + bool default_startup_memory_low_set:1; +diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c +index 4237e69..e82d56e 100644 +--- a/src/core/dbus-cgroup.c ++++ b/src/core/dbus-cgroup.c +@@ -488,6 +488,11 @@ const sd_bus_vtable bus_cgroup_vtable[] = { + SD_BUS_PROPERTY("MemoryZSwapMax", "t", NULL, offsetof(CGroupContext, memory_zswap_max), 0), + SD_BUS_PROPERTY("StartupMemoryZSwapMax", "t", NULL, offsetof(CGroupContext, startup_memory_zswap_max), 0), + SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0), ++ SD_BUS_PROPERTY("CPUSetAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpuset_accounting), 0), ++ SD_BUS_PROPERTY("CPUSetCpus", "s", NULL, offsetof(CGroupContext, cpuset_cpus_v1), 0), ++ SD_BUS_PROPERTY("CPUSetMems", "s", NULL, offsetof(CGroupContext, cpuset_mems_v1), 0), ++ SD_BUS_PROPERTY("CPUSetCloneChildren", "b", bus_property_get_bool, offsetof(CGroupContext, cpuset_clone_children), 0), ++ SD_BUS_PROPERTY("CPUSetMemMigrate", "b", bus_property_get_bool, offsetof(CGroupContext, cpuset_memory_migrate), 0), + SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0), + SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0), + SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0), +@@ -1279,6 +1284,43 @@ int bus_cgroup_set_property( + if (streq(name, "MemoryLimitScale")) + return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error); + ++ if (streq(name, "CPUSetAccounting")) ++ return bus_cgroup_set_boolean(u, name, &c->cpuset_accounting, CGROUP_MASK_CPUSET, message, flags, error); ++ ++ if (STR_IN_SET(name, "CPUSetCpus", "CPUSetMems")) { ++ const char *cpuset_str = NULL; ++ ++ r = sd_bus_message_read(message, "s", &cpuset_str); ++ if (r < 0) ++ return r; ++ ++ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { ++ unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET); ++ if (streq(name, "CPUSetCpus")) { ++ if (c->cpuset_cpus_v1) ++ c->cpuset_cpus_v1 = mfree(c->cpuset_cpus_v1); ++ c->cpuset_cpus_v1 = strdup(cpuset_str); ++ if (!c->cpuset_cpus_v1) ++ return -ENOMEM; ++ unit_write_settingf(u, flags, name, "CPUSetCpus=%s", cpuset_str); ++ } else { ++ if (c->cpuset_mems_v1) ++ c->cpuset_mems_v1 = mfree(c->cpuset_mems_v1); ++ c->cpuset_mems_v1 = strdup(cpuset_str); ++ if (!c->cpuset_mems_v1) ++ return -ENOMEM; ++ unit_write_settingf(u, flags, name, "CPUSetMems=%s", cpuset_str); ++ } ++ } ++ return 1; ++ } ++ ++ if (streq(name, "CPUSetCloneChildren")) ++ return bus_cgroup_set_boolean(u, name, &c->cpuset_clone_children, CGROUP_MASK_CPUSET, message, flags, error); ++ ++ if (streq(name, "CPUSetMemMigrate")) ++ return bus_cgroup_set_boolean(u, name, &c->cpuset_memory_migrate, CGROUP_MASK_CPUSET, message, flags, error); ++ + if (streq(name, "TasksAccounting")) + return bus_cgroup_set_boolean(u, name, &c->tasks_accounting, CGROUP_MASK_PIDS, message, flags, error); + +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index 745f5cc..fc49e7d 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -3005,6 +3005,7 @@ const sd_bus_vtable bus_manager_vtable[] = { + SD_BUS_PROPERTY("DefaultIOAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.io_accounting), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultIPAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.ip_accounting), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("DefaultCpusetAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.cpuset_accounting), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, defaults.tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitCPU", "t", bus_property_get_rlimit, offsetof(Manager, defaults.rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitCPUSoft", "t", bus_property_get_rlimit, offsetof(Manager, defaults.rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), +diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in +index 45f9ab0..62c4027 100644 +--- a/src/core/load-fragment-gperf.gperf.in ++++ b/src/core/load-fragment-gperf.gperf.in +@@ -221,6 +221,11 @@ + {{type}}.MemoryZSwapMax, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) + {{type}}.StartupMemoryZSwapMax, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) + {{type}}.MemoryLimit, config_parse_memory_limit, 0, offsetof({{type}}, cgroup_context) ++{{type}}.CPUSetAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.cpuset_accounting) ++{{type}}.CPUSetCpus, config_parse_cpuset_cpumems, 0, offsetof({{type}}, cgroup_context.cpuset_cpus_v1) ++{{type}}.CPUSetMems, config_parse_cpuset_cpumems, 0, offsetof({{type}}, cgroup_context.cpuset_mems_v1) ++{{type}}.CPUSetCloneChildren, config_parse_bool, 0, offsetof({{type}}, cgroup_context.cpuset_clone_children) ++{{type}}.CPUSetMemMigrate, config_parse_bool, 0, offsetof({{type}}, cgroup_context.cpuset_memory_migrate) + {{type}}.DeviceAllow, config_parse_device_allow, 0, offsetof({{type}}, cgroup_context) + {{type}}.DevicePolicy, config_parse_device_policy, 0, offsetof({{type}}, cgroup_context.device_policy) + {{type}}.IOAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.io_accounting) +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 6e3a22b..cbc75e1 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -3904,6 +3904,75 @@ int config_parse_memory_limit( + return 0; + } + ++int config_parse_cpuset_cpumems( ++ 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) ++{ ++ char **pcpumems = data; ++ char *pinstr = NULL; ++ int iret = 0; ++ ++ assert(filename); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ (void)section; ++ (void)section_line; ++ (void)ltype; ++ (void)userdata; ++ ++ if (!utf8_is_valid(rvalue)) ++ { ++ log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); ++ return 0; ++ } ++ ++ if (0 == strcmp(rvalue, "all")) ++ { ++ pinstr = strdup(rvalue); ++ if (!pinstr) ++ { ++ return log_oom(); ++ } ++ ++ free(*pcpumems); ++ *pcpumems = pinstr; ++ ++ return 0; ++ } ++ ++ /* 0-2,4 */ ++ iret = string_isvalid_interval(rvalue); ++ if (0 != iret) ++ { ++ pinstr = NULL; ++ log_syntax(unit, LOG_ERR, filename, line, EINVAL, ++ "cpuset cpumems '%s' is invalid, Ignoring(%d).", ++ rvalue, iret); ++ } ++ else ++ { ++ pinstr = strdup(rvalue); ++ if (!pinstr) ++ { ++ return log_oom(); ++ } ++ } ++ ++ free(*pcpumems); ++ *pcpumems = pinstr; ++ ++ return 0; ++} ++ + int config_parse_tasks_max( + const char *unit, + const char *filename, +diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h +index 6919805..0b77c8b 100644 +--- a/src/core/load-fragment.h ++++ b/src/core/load-fragment.h +@@ -84,6 +84,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_cg_weight); + CONFIG_PARSER_PROTOTYPE(config_parse_cg_cpu_weight); + CONFIG_PARSER_PROTOTYPE(config_parse_cpu_shares); + CONFIG_PARSER_PROTOTYPE(config_parse_memory_limit); ++CONFIG_PARSER_PROTOTYPE(config_parse_cpuset_cpumems); + CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max); + CONFIG_PARSER_PROTOTYPE(config_parse_delegate); + CONFIG_PARSER_PROTOTYPE(config_parse_delegate_subgroup); +diff --git a/src/core/main.c b/src/core/main.c +index bfdcc13..724593a 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -678,6 +678,7 @@ static int parse_config_file(void) { + { "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_defaults.ip_accounting }, + { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_defaults.blockio_accounting }, + { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_defaults.memory_accounting }, ++ { "Manager", "DefaultCpusetAccounting", config_parse_bool, 0, &arg_defaults.cpuset_accounting }, + { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_defaults.tasks_accounting }, + { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_defaults.tasks_max }, + { "Manager", "DefaultMemoryPressureThresholdSec", config_parse_sec, 0, &arg_defaults.memory_pressure_threshold_usec }, +diff --git a/src/core/manager.c b/src/core/manager.c +index ce20d6b..ef22fed 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -4192,6 +4192,7 @@ int manager_set_unit_defaults(Manager *m, const UnitDefaults *defaults) { + + m->defaults.cpu_accounting = defaults->cpu_accounting; + m->defaults.memory_accounting = defaults->memory_accounting; ++ m->defaults.cpuset_accounting = defaults->cpuset_accounting; + m->defaults.io_accounting = defaults->io_accounting; + m->defaults.blockio_accounting = defaults->blockio_accounting; + m->defaults.tasks_accounting = defaults->tasks_accounting; +@@ -4961,6 +4962,7 @@ void unit_defaults_init(UnitDefaults *defaults, RuntimeScope scope) { + * controller to be enabled, so the default is to enable it unless we got told otherwise. */ + .cpu_accounting = cpu_accounting_is_cheap(), + .memory_accounting = MEMORY_ACCOUNTING_DEFAULT, ++ .cpuset_accounting = false, + .io_accounting = false, + .blockio_accounting = false, + .tasks_accounting = true, +diff --git a/src/core/manager.h b/src/core/manager.h +index d96eb7b..e560811 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -165,6 +165,7 @@ typedef struct UnitDefaults { + bool memory_accounting; + bool io_accounting; + bool blockio_accounting; ++ bool cpuset_accounting; + bool tasks_accounting; + bool ip_accounting; + +diff --git a/src/core/system.conf.in b/src/core/system.conf.in +index 90109ad..69ea5d6 100644 +--- a/src/core/system.conf.in ++++ b/src/core/system.conf.in +@@ -57,6 +57,7 @@ + #DefaultIOAccounting=no + #DefaultIPAccounting=no + #DefaultMemoryAccounting={{ 'yes' if MEMORY_ACCOUNTING_DEFAULT else 'no' }} ++#DefaultCpusetAccounting= + #DefaultTasksAccounting=yes + #DefaultTasksMax=80% + #DefaultLimitCPU= +diff --git a/src/core/unit.c b/src/core/unit.c +index 3d60904..e38a535 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -188,6 +188,7 @@ static void unit_init(Unit *u) { + cc->io_accounting = u->manager->defaults.io_accounting; + cc->blockio_accounting = u->manager->defaults.blockio_accounting; + cc->memory_accounting = u->manager->defaults.memory_accounting; ++ cc->cpuset_accounting = u->manager->defaults.cpuset_accounting; + cc->tasks_accounting = u->manager->defaults.tasks_accounting; + cc->ip_accounting = u->manager->defaults.ip_accounting; + +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 4ee9706..a8f493e 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -566,7 +566,10 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons + "BlockIOAccounting", + "TasksAccounting", + "IPAccounting", +- "CoredumpReceive")) ++ "CoredumpReceive", ++ "CPUSetAccounting", ++ "CPUSetCloneChildren", ++ "CPUSetMemMigrate")) + return bus_append_parse_boolean(m, field, eq); + + if (STR_IN_SET(field, "CPUWeight", +@@ -672,6 +675,16 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons + return bus_append_parse_size(m, field, eq, 1024); + } + ++ if (STR_IN_SET(field, "CPUSetCpus", "CPUSetMems")) { ++ if (string_isvalid_interval(eq) == 0 || streq(eq, "all")) ++ r = sd_bus_message_append(m, "(sv)", field, "s", eq); ++ else ++ r = -EINVAL; ++ if (r < 0) ++ return bus_log_create_error(r); ++ return 1; ++ } ++ + if (streq(field, "CPUQuota")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", USEC_INFINITY); +diff --git a/src/shared/cpu-set-util.c b/src/shared/cpu-set-util.c +index d096576..356a46a 100644 +--- a/src/shared/cpu-set-util.c ++++ b/src/shared/cpu-set-util.c +@@ -7,6 +7,7 @@ + + #include "alloc-util.h" + #include "cpu-set-util.h" ++#include "cgroup-util.h" + #include "dirent-util.h" + #include "errno-util.h" + #include "extract-word.h" +diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c +index bfc8fac..5dd569f 100644 +--- a/src/test/test-cgroup-mask.c ++++ b/src/test/test-cgroup-mask.c +@@ -55,6 +55,7 @@ TEST_RET(cgroup_mask, .sd_booted = true) { + * else. */ + m->defaults.cpu_accounting = + m->defaults.memory_accounting = ++ m->defaults.cpuset_accounting = + m->defaults.blockio_accounting = + m->defaults.io_accounting = + m->defaults.tasks_accounting = false; +diff --git a/test/fuzz/fuzz-unit-file/directives-all.service b/test/fuzz/fuzz-unit-file/directives-all.service +index 4bdc48a..0e953f2 100644 +--- a/test/fuzz/fuzz-unit-file/directives-all.service ++++ b/test/fuzz/fuzz-unit-file/directives-all.service +@@ -52,6 +52,11 @@ BusName= + CoredumpFilter= + CPUAccounting= + CPUQuota= ++CPUSetAccounting= ++CPUSetCloneChildren= ++CPUSetCpus= ++CPUSetMemMigrate= ++CPUSetMems= + CPUShares= + CPUWeight= + CapabilityBoundingSet= +-- +2.23.0 + |