diff options
-rw-r--r-- | man/systemd-system.conf.xml | 23 | ||||
-rw-r--r-- | src/core/main.c | 6 | ||||
-rw-r--r-- | src/core/mount-setup.c | 150 | ||||
-rw-r--r-- | src/core/mount-setup.h | 2 | ||||
-rw-r--r-- | src/core/system.conf.in | 1 | ||||
-rw-r--r-- | src/shared/conf-parser.c | 115 | ||||
-rw-r--r-- | src/shared/conf-parser.h | 1 | ||||
-rw-r--r-- | src/test/test-conf-parser.c | 40 | ||||
-rw-r--r-- | test/fuzz/fuzz-unit-file/directives.service | 1 |
9 files changed, 82 insertions, 257 deletions
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 5ce2c6fb96..ea17111bc5 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -107,29 +107,6 @@ </varlistentry> <varlistentry> - <term><varname>JoinControllers=cpu,cpuacct net_cls,netprio</varname></term> - - <listitem><para>Configures controllers that shall be mounted - in a single hierarchy. By default, systemd will mount all - controllers which are enabled in the kernel in individual - hierarchies, with the exception of those listed in this - setting. Takes a space-separated list of comma-separated - controller names, in order to allow multiple joined - hierarchies. Defaults to 'cpu,cpuacct'. Pass an empty string - to ensure that systemd mounts all controllers in separate - hierarchies.</para> - - <para>Note that this option is only applied once, at very - early boot. If you use an initial RAM disk (initrd) that uses - systemd, it might hence be necessary to rebuild the initrd if - this option is changed, and make sure the new configuration - file is included in it. Otherwise, the initrd might mount the - controller hierarchies in a different configuration than - intended, and the main system cannot remount them - anymore.</para></listitem> - </varlistentry> - - <varlistentry> <term><varname>RuntimeWatchdogSec=</varname></term> <term><varname>ShutdownWatchdogSec=</varname></term> diff --git a/src/core/main.c b/src/core/main.c index 11537c8140..cabcb9ec16 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -100,7 +100,6 @@ static ShowStatus arg_show_status = _SHOW_STATUS_INVALID; static bool arg_switched_root = false; static PagerFlags arg_pager_flags = 0; static bool arg_service_watchdogs = true; -static char ***arg_join_controllers = NULL; static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL; static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT; static usec_t arg_default_restart_usec = DEFAULT_RESTART_USEC; @@ -667,7 +666,7 @@ static int parse_config_file(void) { { "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot }, { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status }, { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL }, - { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, + { "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL }, { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog }, { "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device }, @@ -1956,7 +1955,7 @@ static int initialize_runtime( install_crash_handler(); if (!skip_setup) { - r = mount_cgroup_controllers(arg_join_controllers); + r = mount_cgroup_controllers(); if (r < 0) { *ret_error_message = "Failed to mount cgroup hierarchies"; return r; @@ -2081,7 +2080,6 @@ static void free_arguments(void) { arg_default_unit = mfree(arg_default_unit); arg_confirm_spawn = mfree(arg_confirm_spawn); - arg_join_controllers = strv_free_free(arg_join_controllers); arg_default_environment = strv_free(arg_default_environment); arg_syscall_archs = set_free(arg_syscall_archs); } diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index 16880e6157..e15d94d98a 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -229,76 +229,105 @@ int mount_setup_early(void) { return mount_points_setup(N_EARLY_MOUNT, false); } -int mount_cgroup_controllers(char ***join_controllers) { +static const char *join_with(const char *controller) { + + static const char* const pairs[] = { + "cpu", "cpuacct", + "net_cls", "net_prio", + NULL + }; + + const char *const *x, *const *y; + + assert(controller); + + /* This will lookup which controller to mount another controller with. Input is a controller name, and output + * is the other controller name. The function works both ways: you can input one and get the other, and input + * the other to get the one. */ + + STRV_FOREACH_PAIR(x, y, pairs) { + if (streq(controller, *x)) + return *y; + if (streq(controller, *y)) + return *x; + } + + return NULL; +} + +static int symlink_controller(const char *target, const char *alias) { + const char *a; + int r; + + assert(target); + assert(alias); + + a = strjoina("/sys/fs/cgroup/", alias); + + r = symlink_idempotent(target, a, false); + if (r < 0) + return log_error_errno(r, "Failed to create symlink %s: %m", a); + +#ifdef SMACK_RUN_LABEL + const char *p; + + p = strjoina("/sys/fs/cgroup/", target); + + r = mac_smack_copy(a, p); + if (r < 0 && r != -EOPNOTSUPP) + return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", p, a); +#endif + + return 0; +} + +int mount_cgroup_controllers(void) { _cleanup_set_free_free_ Set *controllers = NULL; - bool has_argument = !!join_controllers; int r; if (!cg_is_legacy_wanted()) return 0; /* Mount all available cgroup controllers that are built into the kernel. */ - - if (!has_argument) - /* The defaults: - * mount "cpu" + "cpuacct" together, and "net_cls" + "net_prio". - * - * We'd like to add "cpuset" to the mix, but "cpuset" doesn't really - * work for groups with no initialized attributes. - */ - join_controllers = (char**[]) { - STRV_MAKE("cpu", "cpuacct"), - STRV_MAKE("net_cls", "net_prio"), - NULL, - }; - r = cg_kernel_controllers(&controllers); if (r < 0) return log_error_errno(r, "Failed to enumerate cgroup controllers: %m"); for (;;) { _cleanup_free_ char *options = NULL, *controller = NULL, *where = NULL; + const char *other_controller; MountPoint p = { .what = "cgroup", .type = "cgroup", .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV, .mode = MNT_IN_CONTAINER, }; - char ***k = NULL; controller = set_steal_first(controllers); if (!controller) break; - for (k = join_controllers; *k; k++) - if (strv_find(*k, controller)) - break; - - if (*k) { - char **i, **j; - - for (i = *k, j = *k; *i; i++) { - - if (!streq(*i, controller)) { - _cleanup_free_ char *t; - - t = set_remove(controllers, *i); - if (!t) { - if (has_argument) - free(*i); - continue; - } - } - - *(j++) = *i; + /* Check if we shall mount this together with another controller */ + other_controller = join_with(controller); + if (other_controller) { + _cleanup_free_ char *c = NULL; + + /* Check if the other controller is actually available in the kernel too */ + c = set_remove(controllers, other_controller); + if (c) { + + /* Join the two controllers into one string, and maintain a stable ordering */ + if (strcmp(controller, other_controller) < 0) + options = strjoin(controller, ",", other_controller); + else + options = strjoin(other_controller, ",", controller); + if (!options) + return log_oom(); } + } - *j = NULL; - - options = strv_join(*k, ","); - if (!options) - return log_oom(); - } else + /* The simple case, where there's only one controller to mount together */ + if (!options) options = TAKE_PTR(controller); where = strappend("/sys/fs/cgroup/", options); @@ -312,35 +341,14 @@ int mount_cgroup_controllers(char ***join_controllers) { if (r < 0) return r; - if (r > 0 && *k) { - char **i; - - for (i = *k; *i; i++) { - _cleanup_free_ char *t = NULL; - - t = strappend("/sys/fs/cgroup/", *i); - if (!t) - return log_oom(); - - r = symlink(options, t); - if (r >= 0) { -#ifdef SMACK_RUN_LABEL - _cleanup_free_ char *src; - src = strappend("/sys/fs/cgroup/", options); - if (!src) - return log_oom(); - r = mac_smack_copy(t, src); - if (r < 0 && r != -EOPNOTSUPP) - return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", src, t); -#endif - } else if (errno != EEXIST) - return log_error_errno(errno, "Failed to create symlink %s: %m", t); - } - } + /* Create symlinks from the individual controller names, in case we have a joined mount */ + if (controller) + (void) symlink_controller(options, controller); + if (other_controller) + (void) symlink_controller(options, other_controller); } - /* Now that we mounted everything, let's make the tmpfs the - * cgroup file systems are mounted into read-only. */ + /* Now that we mounted everything, let's make the tmpfs the cgroup file systems are mounted into read-only. */ (void) mount("tmpfs", "/sys/fs/cgroup", "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); return 0; diff --git a/src/core/mount-setup.h b/src/core/mount-setup.h index 43cd8908de..b4ca2cf4b4 100644 --- a/src/core/mount-setup.h +++ b/src/core/mount-setup.h @@ -6,7 +6,7 @@ int mount_setup_early(void); int mount_setup(bool loaded_policy); -int mount_cgroup_controllers(char ***join_controllers); +int mount_cgroup_controllers(void); bool mount_point_is_api(const char *path); bool mount_point_ignore(const char *path); diff --git a/src/core/system.conf.in b/src/core/system.conf.in index ef1bbbd948..0a58737b82 100644 --- a/src/core/system.conf.in +++ b/src/core/system.conf.in @@ -23,7 +23,6 @@ #CrashReboot=no #CtrlAltDelBurstAction=reboot-force #CPUAffinity=1 2 -#JoinControllers=cpu,cpuacct net_cls,net_prio #RuntimeWatchdogSec=0 #ShutdownWatchdogSec=10min #WatchdogDevice= diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 493ece9d09..b417ac2d6d 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -1013,121 +1013,6 @@ int config_parse_ip_port( return 0; } -int config_parse_join_controllers( - 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 ****ret = data; - const char *whole_rvalue = rvalue; - unsigned n = 0; - _cleanup_(strv_free_freep) char ***controllers = NULL; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(ret); - - for (;;) { - _cleanup_free_ char *word = NULL; - char **l; - int r; - - r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue); - return r; - } - if (r == 0) - break; - - l = strv_split(word, ","); - if (!l) - return log_oom(); - strv_uniq(l); - - if (strv_length(l) <= 1) { - strv_free(l); - continue; - } - - if (!controllers) { - controllers = new(char**, 2); - if (!controllers) { - strv_free(l); - return log_oom(); - } - - controllers[0] = l; - controllers[1] = NULL; - - n = 1; - } else { - char ***a; - char ***t; - - t = new0(char**, n+2); - if (!t) { - strv_free(l); - return log_oom(); - } - - n = 0; - - for (a = controllers; *a; a++) - if (strv_overlap(*a, l)) { - if (strv_extend_strv(&l, *a, false) < 0) { - strv_free(l); - strv_free_free(t); - return log_oom(); - } - - } else { - char **c; - - c = strv_copy(*a); - if (!c) { - strv_free(l); - strv_free_free(t); - return log_oom(); - } - - t[n++] = c; - } - - t[n++] = strv_uniq(l); - - strv_free_free(controllers); - controllers = t; - } - } - if (!isempty(rvalue)) - log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); - - /* As a special case, return a single empty strv, to override the default */ - if (!controllers) { - controllers = new(char**, 2); - if (!controllers) - return log_oom(); - controllers[0] = strv_new(NULL); - if (!controllers[0]) - return log_oom(); - controllers[1] = NULL; - } - - strv_free_free(*ret); - *ret = TAKE_PTR(controllers); - - return 0; -} - int config_parse_mtu( const char *unit, const char *filename, diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 16f042d894..865db4278b 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -137,7 +137,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_personality); CONFIG_PARSER_PROTOTYPE(config_parse_permille); CONFIG_PARSER_PROTOTYPE(config_parse_ifname); CONFIG_PARSER_PROTOTYPE(config_parse_ip_port); -CONFIG_PARSER_PROTOTYPE(config_parse_join_controllers); CONFIG_PARSER_PROTOTYPE(config_parse_mtu); CONFIG_PARSER_PROTOTYPE(config_parse_rlimit); diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c index 368e02cb33..497becff73 100644 --- a/src/test/test-conf-parser.c +++ b/src/test/test-conf-parser.c @@ -210,45 +210,6 @@ static void test_config_parse_iec_uint64(void) { assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0); } -static void test_config_parse_join_controllers(void) { - int r; - _cleanup_(strv_free_freep) char ***c = NULL; - char ***c2; - - /* Test normal operation */ - r = config_parse_join_controllers(NULL, "example.conf", 11, "Section", 10, "JoinControllers", 0, "cpu,cpuacct net_cls,netprio", &c, NULL); - assert_se(r == 0); - assert_se(c); - assert_se(strv_length(c[0]) == 2); - assert_se(strv_equal(c[0], STRV_MAKE("cpu", "cpuacct"))); - assert_se(strv_length(c[1]) == 2); - assert_se(strv_equal(c[1], STRV_MAKE("net_cls", "netprio"))); - assert_se(c[2] == NULL); - - /* Test special case of no mounted controllers */ - r = config_parse_join_controllers(NULL, "example.conf", 12, "Section", 10, "JoinControllers", 0, "", &c, NULL); - assert_se(r == 0); - assert_se(c); - assert_se(strv_equal(c[0], STRV_MAKE_EMPTY)); - assert_se(c[1] == NULL); - - /* Test merging of overlapping lists */ - r = config_parse_join_controllers(NULL, "example.conf", 13, "Section", 10, "JoinControllers", 0, "a,b b,c", &c, NULL); - assert_se(r == 0); - assert_se(c); - assert_se(strv_length(c[0]) == 3); - assert_se(strv_contains(c[0], "a")); - assert_se(strv_contains(c[0], "b")); - assert_se(strv_contains(c[0], "c")); - assert_se(c[1] == NULL); - - /* Test ignoring of bad lines */ - c2 = c; - r = config_parse_join_controllers(NULL, "example.conf", 14, "Section", 10, "JoinControllers", 0, "a,\"b ", &c, NULL); - assert_se(r < 0); - assert_se(c == c2); -} - #define x10(x) x x x x x x x x x x #define x100(x) x10(x10(x)) #define x1000(x) x10(x100(x)) @@ -407,7 +368,6 @@ int main(int argc, char **argv) { test_config_parse_sec(); test_config_parse_nsec(); test_config_parse_iec_uint64(); - test_config_parse_join_controllers(); for (i = 0; i < ELEMENTSOF(config_file); i++) test_config_parse(i, config_file[i]); diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service index fd830dde41..f454fd313e 100644 --- a/test/fuzz/fuzz-unit-file/directives.service +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -690,7 +690,6 @@ HibernateMode= HibernateState= HybridSleepMode= HybridSleepState= -JoinControllers= LogColor= LogLevel= LogLocation= |