From a25f206a49d8a3111ac42791b2eca8a3c9af4991 Mon Sep 17 00:00:00 2001 From: licunlong Date: Thu, 6 May 2021 09:38:55 +0800 Subject: [PATCH] core-cgroup: support default slice for all units. With this patch, users can specify a default slice for all units by adding DefaultUnitSlice=xxx.slice in /etc/systemd/system.conf. --- src/core/main.c | 22 +++++++++++ src/core/manager.h | 3 ++ src/core/unit.c | 98 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 115 insertions(+), 8 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index c4379cf..e9f56fa 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -147,6 +147,7 @@ static sd_id128_t arg_machine_id; static EmergencyAction arg_cad_burst_action; static CPUSet arg_cpu_affinity; static NUMAPolicy arg_numa_policy; +static char *arg_default_unit_slice = NULL; static usec_t arg_clock_usec; static void *arg_random_seed; static size_t arg_random_seed_size; @@ -688,6 +689,7 @@ static int parse_config_file(void) { { "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, arg_runtime_scope, &arg_cad_burst_action }, { "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_defaults.oom_policy }, { "Manager", "DefaultOOMScoreAdjust", config_parse_oom_score_adjust, 0, NULL }, + { "Manager", "DefaultUnitSlice", config_parse_string, 0, &arg_default_unit_slice }, { "Manager", "ReloadLimitIntervalSec", config_parse_sec, 0, &arg_reload_limit_interval_sec }, { "Manager", "ReloadLimitBurst", config_parse_unsigned, 0, &arg_reload_limit_burst }, #if ENABLE_SMACK @@ -756,6 +758,26 @@ static void set_manager_defaults(Manager *m) { r = manager_transient_environment_add(m, arg_default_environment); if (r < 0) log_warning_errno(r, "Failed to add to transient environment, ignoring: %m"); + if (m->default_unit_slice) + { + free(m->default_unit_slice); + m->default_unit_slice = NULL; + } + + if (arg_default_unit_slice) + { + char *default_unit_slice_tmp = NULL; + + default_unit_slice_tmp = strdup(arg_default_unit_slice); + if (!default_unit_slice_tmp) + log_oom(); + + m->default_unit_slice = default_unit_slice_tmp; + + /* free */ + free(arg_default_unit_slice); + arg_default_unit_slice = NULL; + } } static void set_manager_settings(Manager *m) { diff --git a/src/core/manager.h b/src/core/manager.h index 6dd1a18..3c954af 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -23,6 +23,7 @@ typedef struct Unit Unit; /* Enforce upper limit how many names we allow */ #define MANAGER_MAX_NAMES 131072 /* 128K */ +#define DEFAULT_UNIT_NAME_LEN_MAX 32 /* On sigrtmin+18, private commands */ enum { @@ -481,6 +482,8 @@ struct Manager { unsigned sigchldgen; unsigned notifygen; + char *default_unit_slice; + VarlinkServer *varlink_server; /* When we're a system manager, this object manages the subscription from systemd-oomd to PID1 that's * used to report changes in ManagedOOM settings (systemd server - oomd client). When diff --git a/src/core/unit.c b/src/core/unit.c index c069018..24d7060 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3545,6 +3545,58 @@ int unit_set_slice(Unit *u, Unit *slice) { return 1; } +/* system-xxx.slice, xxx must be (a b c/A B C...and 0 1 2...) */ +static bool slicename_is_valid(const char *slicename) { + const char *str_start = "system-"; + const char *str_end = ".slice"; + const char *str_tmp = NULL; + size_t len_in = 0; + size_t len_start = 0; + size_t len_end = 0; + size_t i = 0; + + if (isempty(slicename)) + return false; + + len_in = strlen(slicename); + len_start = strlen(str_start); + len_end = strlen(str_end); + + if (len_in > DEFAULT_UNIT_NAME_LEN_MAX) + return false; + + if (len_in <= len_start + len_end) + return false; + + /* system- */ + if (strncmp(slicename, str_start, len_start) != 0) + return false; + + str_tmp = slicename + len_start; + + len_in = strlen(str_tmp); + if (len_in <= len_end) + return false; + + /* .slice */ + if (!strneq(str_tmp + len_in - len_end, str_end, len_end)) + return false; + + /* a b c/A B C...and 0 1 2... */ + for (i = 0; i < (len_in - len_end); i++) { + char c = *(str_tmp + i); + + if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9')) + continue; + else + return false; + } + + return true; +} + int unit_set_default_slice(Unit *u) { const char *slice_name; Unit *slice; @@ -3558,6 +3610,20 @@ int unit_set_default_slice(Unit *u) { if (UNIT_GET_SLICE(u)) return 0; + bool isdefaultslice = false; + char *default_unit_slice = u->manager->default_unit_slice; + + if (default_unit_slice) { + isdefaultslice = true; + + if (streq(default_unit_slice, SPECIAL_SYSTEM_SLICE)) + isdefaultslice = false; + else if (!slicename_is_valid(default_unit_slice)) { + log_error("default unit slice is error. slice name '%s' is invalid.", default_unit_slice); + isdefaultslice = false; + } + } + if (u->instance) { _cleanup_free_ char *prefix = NULL, *escaped = NULL; @@ -3575,24 +3641,40 @@ int unit_set_default_slice(Unit *u) { if (!escaped) return -ENOMEM; - if (MANAGER_IS_SYSTEM(u->manager)) - slice_name = strjoina("system-", escaped, ".slice"); - else + if (MANAGER_IS_SYSTEM(u->manager)) { + if (isdefaultslice) { + _cleanup_free_ char *default_unit_slice_tmp = NULL; + + default_unit_slice_tmp = strreplace(default_unit_slice, ".slice", "-"); + if (!default_unit_slice_tmp) + return -ENOMEM; + + slice_name = strjoina(default_unit_slice_tmp, escaped, ".slice"); + } else + slice_name = strjoina("system-", escaped, ".slice"); + } else slice_name = strjoina("app-", escaped, ".slice"); - } else if (unit_is_extrinsic(u)) + } else if (unit_is_extrinsic(u)) { /* Keep all extrinsic units (e.g. perpetual units and swap and mount units in user mode) in * the root slice. They don't really belong in one of the subslices. */ slice_name = SPECIAL_ROOT_SLICE; - - else if (MANAGER_IS_SYSTEM(u->manager)) - slice_name = SPECIAL_SYSTEM_SLICE; - else + isdefaultslice = false; + } else if (MANAGER_IS_SYSTEM(u->manager)) { + if (isdefaultslice) + slice_name = default_unit_slice; + else + slice_name = SPECIAL_SYSTEM_SLICE; + } else { slice_name = SPECIAL_APP_SLICE; + isdefaultslice = false; + } r = manager_load_unit(u->manager, slice_name, NULL, NULL, &slice); if (r < 0) return r; + if (isdefaultslice) + slice->default_dependencies=false; return unit_set_slice(u, slice); } -- 2.33.0