From 38599489e49e840291516488a3ef1b4a56198c58 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 18:47:02 +0100 Subject: logind: don't assert if the slice is missing After all, we don't actually really need the slice to work, it's just nice to have it. --- src/login/logind-session.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/login') diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 1d561a6f8a..ef3d46f3fb 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -513,7 +513,6 @@ static int session_start_scope(Session *s) { assert(s); assert(s->user); - assert(s->user->slice); if (!s->scope) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; -- cgit v1.2.3-54-g00ecf From 90558f315844ec35e3fd4f1a19ac38c8721c9354 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 18:25:02 +0100 Subject: logind: add a new UserTasksMax= setting to logind.conf This new setting configures the TasksMax= field for the slice objects we create for each user. This alters logind to create the slice unit as transient unit explicitly instead of relying on implicit generation of slice units by simply starting them. This also enables us to set a friendly description for slice units that way. --- man/logind.conf.xml | 15 ++++++- src/login/logind-dbus.c | 94 +++++++++++++++++++++++++++++++++++++++++++- src/login/logind-gperf.gperf | 1 + src/login/logind-session.c | 25 +++++++----- src/login/logind-user.c | 54 ++++++++++++++++++------- src/login/logind.c | 1 + src/login/logind.conf | 1 + src/login/logind.h | 4 +- 8 files changed, 167 insertions(+), 28 deletions(-) (limited to 'src/login') diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 43d1ffbd3c..3cde267119 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -1,4 +1,4 @@ - + @@ -277,7 +277,18 @@ limit relative to the amount of physical RAM. Defaults to 10%. Note that this size is a safety limit only. As each runtime directory is a tmpfs file system, it will only consume as much - memory as is needed. + memory as is needed. + + + + UserTasksMax= + + Sets the maximum number of OS tasks each user + may run concurrently. This controls the + TasksMax= setting of the per-user slice + unit, see + systemd.resource-control5 + for details. diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 7890d68aa0..1b460b3bb0 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2740,13 +2740,101 @@ int manager_send_changed(Manager *manager, const char *property, ...) { l); } +int manager_start_slice( + Manager *manager, + const char *slice, + const char *description, + const char *after, + const char *after2, + uint64_t tasks_max, + sd_bus_error *error, + char **job) { + + _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; + int r; + + assert(manager); + assert(slice); + + r = sd_bus_message_new_method_call( + manager->bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "ss", strempty(slice), "fail"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return r; + + if (!isempty(description)) { + r = sd_bus_message_append(m, "(sv)", "Description", "s", description); + if (r < 0) + return r; + } + + if (!isempty(after)) { + r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after); + if (r < 0) + return r; + } + + if (!isempty(after2)) { + r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2); + if (r < 0) + return r; + } + + r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "a(sa(sv))", 0); + if (r < 0) + return r; + + r = sd_bus_call(manager->bus, m, 0, error, &reply); + if (r < 0) + return r; + + if (job) { + const char *j; + char *copy; + + r = sd_bus_message_read(reply, "o", &j); + if (r < 0) + return r; + + copy = strdup(j); + if (!copy) + return -ENOMEM; + + *job = copy; + } + + return 1; +} + int manager_start_scope( Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, - const char *after, const char *after2, + const char *after, + const char *after2, + uint64_t tasks_max, sd_bus_error *error, char **job) { @@ -2814,6 +2902,10 @@ int manager_start_scope( if (r < 0) return r; + r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max); + if (r < 0) + return r; + r = sd_bus_message_close_container(m); if (r < 0) return r; diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf index 9218d098e0..8552c464cc 100644 --- a/src/login/logind-gperf.gperf +++ b/src/login/logind-gperf.gperf @@ -34,3 +34,4 @@ Login.IdleAction, config_parse_handle_action, 0, offsetof(Manag Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec) Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size) Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc) +Login.UserTasksMax, config_parse_uint64, 0, offsetof(Manager, user_tasks_max) diff --git a/src/login/logind-session.c b/src/login/logind-session.c index ef3d46f3fb..6c4ada29fb 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -516,21 +516,28 @@ static int session_start_scope(Session *s) { if (!s->scope) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *description = NULL; char *scope, *job = NULL; - - description = strjoin("Session ", s->id, " of user ", s->user->name, NULL); - if (!description) - return log_oom(); + const char *description; scope = strjoin("session-", s->id, ".scope", NULL); if (!scope) return log_oom(); - r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job); + description = strjoina("Session ", s->id, " of user ", s->user->name, NULL); + + r = manager_start_scope( + s->manager, + scope, + s->leader, + s->user->slice, + description, + "systemd-logind.service", + "systemd-user-sessions.service", + (uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */ + &error, + &job); if (r < 0) { - log_error("Failed to start session scope %s: %s %s", - scope, bus_error_message(&error, r), error.name); + log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r)); free(scope); return r; } else { @@ -542,7 +549,7 @@ static int session_start_scope(Session *s) { } if (s->scope) - hashmap_put(s->manager->session_units, s->scope, s); + (void) hashmap_put(s->manager->session_units, s->scope, s); return 0; } diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 56bc5a010c..7bdbe6583c 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -25,6 +25,7 @@ #include #include "alloc-util.h" +#include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" #include "clean-ipc.h" @@ -44,6 +45,7 @@ #include "rm-rf.h" #include "smack-util.h" #include "special.h" +#include "stdio-util.h" #include "string-table.h" #include "unit-name.h" #include "user-util.h" @@ -392,34 +394,51 @@ fail: } static int user_start_slice(User *u) { - char *job; int r; assert(u); if (!u->slice) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice; - sprintf(lu, UID_FMT, u->uid); + char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice, *job; + const char *description; + + u->slice_job = mfree(u->slice_job); + xsprintf(lu, UID_FMT, u->uid); r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &slice); if (r < 0) - return r; - - r = manager_start_unit(u->manager, slice, &error, &job); + return log_error_errno(r, "Failed to build slice name: %m"); + + description = strjoina("User Slice of ", u->name); + + r = manager_start_slice( + u->manager, + slice, + description, + "systemd-logind.service", + "systemd-user-sessions.service", + u->manager->user_tasks_max, + &error, + &job); if (r < 0) { - log_error("Failed to start user slice: %s", bus_error_message(&error, r)); - free(slice); + + if (sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS)) + /* The slice already exists? If so, that's fine, let's just reuse it */ + u->slice = slice; + else { + log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)", slice, bus_error_message(&error, r), error.name); + free(slice); + /* we don't fail due to this, let's try to continue */ + } } else { u->slice = slice; - - free(u->slice_job); u->slice_job = job; } } if (u->slice) - hashmap_put(u->manager->user_units, u->slice, u); + (void) hashmap_put(u->manager->user_units, u->slice, u); return 0; } @@ -433,16 +452,21 @@ static int user_start_service(User *u) { if (!u->service) { char lu[DECIMAL_STR_MAX(uid_t) + 1], *service; - sprintf(lu, UID_FMT, u->uid); + xsprintf(lu, UID_FMT, u->uid); r = unit_name_build("user", lu, ".service", &service); if (r < 0) return log_error_errno(r, "Failed to build service name: %m"); - r = manager_start_unit(u->manager, service, &error, &job); + r = manager_start_unit( + u->manager, + service, + &error, + &job); if (r < 0) { - log_error("Failed to start user service: %s", bus_error_message(&error, r)); + log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r)); free(service); + /* we don't fail due to this, let's try to continue */ } else { u->service = service; @@ -452,7 +476,7 @@ static int user_start_service(User *u) { } if (u->service) - hashmap_put(u->manager->user_units, u->service, u); + (void) hashmap_put(u->manager->user_units, u->service, u); return 0; } diff --git a/src/login/logind.c b/src/login/logind.c index be6bbe5b5c..c3a2fb5acd 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -70,6 +70,7 @@ static Manager *manager_new(void) { m->idle_action_not_before_usec = now(CLOCK_MONOTONIC); m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */ + m->user_tasks_max = (uint64_t) -1; m->devices = hashmap_new(&string_hash_ops); m->seats = hashmap_new(&string_hash_ops); diff --git a/src/login/logind.conf b/src/login/logind.conf index 6df6f04c77..e8f1487734 100644 --- a/src/login/logind.conf +++ b/src/login/logind.conf @@ -32,3 +32,4 @@ #IdleActionSec=30min #RuntimeDirectorySize=10% #RemoveIPC=yes +#UserTasksMax= diff --git a/src/login/logind.h b/src/login/logind.h index 44e05d8b01..f34544e64c 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -134,6 +134,7 @@ struct Manager { sd_event_source *lid_switch_ignore_event_source; size_t runtime_dir_size; + uint64_t user_tasks_max; }; int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device); @@ -171,7 +172,8 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_; -int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job); +int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job); +int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job); int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); -- cgit v1.2.3-54-g00ecf From a5bc6e5450981e1f3f88e083f5070038a0211b74 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 19:32:37 +0100 Subject: logind: change default to UserTasksMax= to 4096 --- man/logind.conf.xml | 2 +- src/login/logind.c | 2 +- src/login/logind.conf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/login') diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 3cde267119..94376656d5 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -288,7 +288,7 @@ TasksMax= setting of the per-user slice unit, see systemd.resource-control5 - for details. + for details. Defaults to 4096. diff --git a/src/login/logind.c b/src/login/logind.c index c3a2fb5acd..7b41174c64 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -70,7 +70,7 @@ static Manager *manager_new(void) { m->idle_action_not_before_usec = now(CLOCK_MONOTONIC); m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */ - m->user_tasks_max = (uint64_t) -1; + m->user_tasks_max = UINT64_C(4096); m->devices = hashmap_new(&string_hash_ops); m->seats = hashmap_new(&string_hash_ops); diff --git a/src/login/logind.conf b/src/login/logind.conf index e8f1487734..81f6695434 100644 --- a/src/login/logind.conf +++ b/src/login/logind.conf @@ -32,4 +32,4 @@ #IdleActionSec=30min #RuntimeDirectorySize=10% #RemoveIPC=yes -#UserTasksMax= +#UserTasksMax=4096 -- cgit v1.2.3-54-g00ecf