]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: add a new UserTasksMax= setting to logind.conf
authorLennart Poettering <lennart@poettering.net>
Fri, 13 Nov 2015 17:25:02 +0000 (18:25 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 13 Nov 2015 18:50:52 +0000 (19:50 +0100)
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
src/login/logind-dbus.c
src/login/logind-gperf.gperf
src/login/logind-session.c
src/login/logind-user.c
src/login/logind.c
src/login/logind.conf
src/login/logind.h

index 43d1ffbd3cf75cdb24645af1f1fe5358a4783afb..3cde267119816d59a4272851403e2686f53f211a 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 
         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. </para></listitem>
+        memory as is needed.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>UserTasksMax=</varname></term>
+
+        <listitem><para>Sets the maximum number of OS tasks each user
+        may run concurrently. This controls the
+        <varname>TasksMax=</varname> setting of the per-user slice
+        unit, see
+        <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+        for details.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 7890d68aa0f6227c6c0cdfd6e04c68a6e16772d7..1b460b3bb047824653388fd3197cb3c698a28acd 100644 (file)
@@ -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;
index 9218d098e024aa9f87b5fa1750247fd5ea229209..8552c464ccaf4cdb8a7d4226554452f5d6acb12e 100644 (file)
@@ -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)
index ef3d46f3fb5424811bd668acb3324cfc15cef12f..6c4ada29fbeb8f493ea790f14eac384fa69b6988 100644 (file)
@@ -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;
 }
index 56bc5a010c6710bbdeef7da18a705a7df6902965..7bdbe6583c240f3e4b2275eccb21501ff078d557 100644 (file)
@@ -25,6 +25,7 @@
 #include <unistd.h>
 
 #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;
 }
index be6bbe5b5cdba987d0218f37ba1add4e90e8d5cb..c3a2fb5acd8e7335f6425cd8970ec1415644186e 100644 (file)
@@ -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);
index 6df6f04c775b125b0e9f02198a842e0374c3b5d9..e8f148773478b95d1dfbde3b26f043b32549165e 100644 (file)
@@ -32,3 +32,4 @@
 #IdleActionSec=30min
 #RuntimeDirectorySize=10%
 #RemoveIPC=yes
+#UserTasksMax=
index 44e05d8b01a6412bf2f9c20e5f0b5b5608360a5e..f34544e64ceacea9dcea687521e92225733881c6 100644 (file)
@@ -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);