From d3acd5b49a6a321dc3b1512416132b8724b2fd20 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 6 Nov 2018 11:51:26 +0100 Subject: [PATCH] logind: keep backward compatibility with UserTasksMax= in logind.conf Since commit 284149392755f086d0a71, UserTasksMax= support has been simply dropped. A generator is used to automatically create an appropriate dropin that has the same effect. However since the snippet is generated in /run, sysadmin is encouraged to copy it in /etc to make it persistent. The main advantages to use a generator are: - sysadmin is aware of this backward incompatible change - he will be the one who will fix logind.conf manually (to remove the use of UserTasksMax=) - he will decide how to name the snippet and possibly merge it with an existing one Expect this generator to be dropped in the future. --- meson.build | 8 ++++ src/login/compat-tasks-max-generator.c | 66 ++++++++++++++++++++++++++ src/login/logind-user.c | 43 +++++++++++++++-- 3 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 src/login/compat-tasks-max-generator.c diff --git a/meson.build b/meson.build index 5c7c165ba..7e3e8ca16 100644 --- a/meson.build +++ b/meson.build @@ -1701,6 +1701,14 @@ if conf.get('ENABLE_LOGIND') == 1 endif endif +executable('logind-compat-tasks-max-generator', + 'src/login/compat-tasks-max-generator.c', + include_directories : includes, + link_with : [libshared, liblogind_core], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + executable('systemd-user-runtime-dir', user_runtime_dir_sources, include_directories : includes, diff --git a/src/login/compat-tasks-max-generator.c b/src/login/compat-tasks-max-generator.c new file mode 100644 index 000000000..404ca5f23 --- /dev/null +++ b/src/login/compat-tasks-max-generator.c @@ -0,0 +1,66 @@ +#include + +#include "alloc-util.h" +#include "dropin.h" +#include "logind.h" +#include "path-util.h" + +static const char *arg_dest = "/tmp"; + +static int read_manager_configuration(uint64_t *user_tasks_max) { + Manager m = {}; + int r; + + manager_reset_config(&m); + m.user_tasks_max = 0; + + r = manager_parse_config_file(&m); + if (r < 0) + return log_warning_errno(r, "Failed to parse logind.conf: %m"); + + if (m.user_tasks_max == 0) + return 0; + + *user_tasks_max = m.user_tasks_max; + return 1; +} + +int main(int argc, char *argv[]) { + _cleanup_free_ char *p = NULL; + uint64_t user_tasks_max; + int r = 0; + + if (argc > 1 && argc != 4) { + log_error("This program takes three or no arguments."); + return EXIT_FAILURE; + } + + if (argc > 1) + arg_dest = argv[1]; + + log_set_prohibit_ipc(true); + log_set_target(LOG_TARGET_AUTO); + log_parse_environment(); + log_open(); + + umask(0022); + + r = read_manager_configuration(&user_tasks_max); + if (r == 0) + return EXIT_SUCCESS; + if (r < 0) + return EXIT_FAILURE; + + p = path_join(arg_dest, "user-.slice.d", "50-limits.conf"); + if (!p) + return EXIT_FAILURE; + + log_warning("Creating %s to keep compability\n" + "Consider copying the snippet in /etc/systemd/system/user-.slice.d/\n", p); + + r = write_drop_in_format(arg_dest, "user-.slice", 50, "limits", + "# Automatically generated by logind-compat-tasks-max-generator\n\n" + "[Slice]\nTasksMax=%" PRIu64, user_tasks_max); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 66f5c896d..fe58b0398 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -743,17 +743,50 @@ int config_parse_compat_user_tasks_max( void *data, void *userdata) { + uint64_t *m = data; + uint64_t k; + int r; + assert(filename); assert(lvalue); assert(rvalue); assert(data); - log_syntax(unit, LOG_NOTICE, filename, line, 0, + log_syntax(unit, LOG_WARNING, filename, line, 0, "Support for option %s= has been removed.", lvalue); - log_info("Hint: try creating /etc/systemd/system/user-.slice.d/50-limits.conf with:\n" - " [Slice]\n" - " TasksMax=%s", - rvalue); + + if (isempty(rvalue)) { + *m = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); + return 0; + } + + if (streq(rvalue, "infinity")) { + *m = CGROUP_LIMIT_MAX; + return 0; + } + + /* Try to parse as percentage */ + r = parse_percent(rvalue); + if (r >= 0) + k = system_tasks_max_scale(r, 100U); + else { + + /* If the passed argument was not a percentage, or out of range, parse as byte size */ + + r = safe_atou64(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse tasks maximum, ignoring: %s", rvalue); + return 0; + } + } + + if (k <= 0 || k >= UINT64_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Tasks maximum out of range, ignoring: %s", rvalue); + return 0; + } + + *m = k; + return 0; } -- 2.19.0