summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2015-11-16 15:09:55 +0100
committerDavid Herrmann <dh.herrmann@googlemail.com>2015-11-16 15:09:55 +0100
commit44690833dfadb523c1f9b6a9e6e1dced44f374e1 (patch)
tree825ddf05390264473ceda190b668f3d501094d5c
parente25b5a8d7380a86ea717b4038c45a8f882b1a2ae (diff)
parent541ec33075f9f2461b5286592312d2b50295ad32 (diff)
Merge pull request #1886 from poettering/tasks-max
Enable TasksMax by default for all units
-rw-r--r--man/logind.conf.xml15
-rw-r--r--man/systemd-system.conf.xml17
-rw-r--r--man/systemd.resource-control.xml5
-rw-r--r--man/systemd.time.xml4
-rw-r--r--src/basic/btrfs-util.c31
-rw-r--r--src/basic/time-util.c71
-rw-r--r--src/core/dbus-manager.c14
-rw-r--r--src/core/load-fragment-gperf.gperf.m42
-rw-r--r--src/core/load-fragment.c7
-rw-r--r--src/core/main.c9
-rw-r--r--src/core/manager.c2
-rw-r--r--src/core/manager.h1
-rw-r--r--src/core/scope.c14
-rw-r--r--src/core/slice.c1
-rw-r--r--src/core/system.conf3
-rw-r--r--src/core/unit.c6
-rw-r--r--src/core/unit.h3
-rw-r--r--src/login/logind-dbus.c94
-rw-r--r--src/login/logind-gperf.gperf1
-rw-r--r--src/login/logind-session.c26
-rw-r--r--src/login/logind-user.c54
-rw-r--r--src/login/logind.c1
-rw-r--r--src/login/logind.conf1
-rw-r--r--src/login/logind.h4
-rw-r--r--src/nspawn/nspawn-register.c4
-rw-r--r--src/test/test-cgroup-mask.c10
-rw-r--r--units/systemd-nspawn@.service.in1
27 files changed, 295 insertions, 106 deletions
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index 43d1ffbd3c..94376656d5 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -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">
@@ -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. </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. Defaults to 4096.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index 54ce992b85..ead52951da 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -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">
@@ -317,7 +317,20 @@
<varname>MemoryAccounting=</varname> and
<varname>TasksAccounting=</varname>. See
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details on the per-unit settings.</para></listitem>
+ for details on the per-unit
+ settings. <varname>DefaulTasksAccounting=</varname> defaults
+ to on, the other three settings to off.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>DefaultTasksMax=</varname></term>
+
+ <listitem><para>Configure the default value for the per-unit
+ <varname>TasksMax=</varname> setting. See
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for details. This setting applies to all unit types that
+ support resource control settings, with the exception of slice
+ units. Defaults to 512.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index 0497f60546..b1106c759d 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -241,7 +241,10 @@
see <ulink
url="https://www.kernel.org/doc/Documentation/cgroups/pids.txt">pids.txt</ulink>.</para>
- <para>Implies <literal>TasksAccounting=true</literal>.</para>
+ <para>Implies <literal>TasksAccounting=true</literal>. The
+ system default for this setting may be controlled with
+ <varname>DefaultTasksMax=</varname> in
+ <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
diff --git a/man/systemd.time.xml b/man/systemd.time.xml
index 135eb35f1b..a6fcc95e4c 100644
--- a/man/systemd.time.xml
+++ b/man/systemd.time.xml
@@ -82,8 +82,8 @@
<listitem><para>hours, hour, hr, h</para></listitem>
<listitem><para>days, day, d</para></listitem>
<listitem><para>weeks, week, w</para></listitem>
- <listitem><para>months, month</para></listitem>
- <listitem><para>years, year, y</para></listitem>
+ <listitem><para>months, month, M (defined as 30.44 days)</para></listitem>
+ <listitem><para>years, year, y (define as 365.25 days)</para></listitem>
</itemizedlist>
<para>If no time unit is specified, generally seconds are assumed,
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index 290fabdeff..8c2d76b8aa 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -1423,12 +1423,16 @@ static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_sub
return n_old_qgroups;
r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id);
- if (r < 0)
+ if (r == -ENXIO)
+ /* We have no parent, hence nothing to copy. */
+ n_old_parent_qgroups = 0;
+ else if (r < 0)
return r;
-
- n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
- if (n_old_parent_qgroups < 0)
- return n_old_parent_qgroups;
+ else {
+ n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
+ if (n_old_parent_qgroups < 0)
+ return n_old_parent_qgroups;
+ }
for (i = 0; i < n_old_qgroups; i++) {
uint64_t id;
@@ -1885,14 +1889,19 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed
if (n > 0) /* already parent qgroups set up, let's bail */
return 0;
+ qgroups = mfree(qgroups);
+
r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol);
- if (r < 0)
+ if (r == -ENXIO)
+ /* No parent, hence no qgroup memberships */
+ n = 0;
+ else if (r < 0)
return r;
-
- qgroups = mfree(qgroups);
- n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
- if (n < 0)
- return n;
+ else {
+ n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
+ if (n < 0)
+ return n;
+ }
if (insert_intermediary_qgroup) {
uint64_t lowest = 256, new_qgroupid;
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index b36fbe4f09..647763a230 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -323,15 +323,15 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
const char *suffix;
usec_t usec;
} table[] = {
- { "y", USEC_PER_YEAR },
- { "month", USEC_PER_MONTH },
- { "w", USEC_PER_WEEK },
- { "d", USEC_PER_DAY },
- { "h", USEC_PER_HOUR },
- { "min", USEC_PER_MINUTE },
- { "s", USEC_PER_SEC },
- { "ms", USEC_PER_MSEC },
- { "us", 1 },
+ { "y", USEC_PER_YEAR },
+ { "month", USEC_PER_MONTH },
+ { "w", USEC_PER_WEEK },
+ { "d", USEC_PER_DAY },
+ { "h", USEC_PER_HOUR },
+ { "min", USEC_PER_MINUTE },
+ { "s", USEC_PER_SEC },
+ { "ms", USEC_PER_MSEC },
+ { "us", 1 },
};
unsigned i;
@@ -711,33 +711,34 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
const char *suffix;
usec_t usec;
} table[] = {
- { "seconds", USEC_PER_SEC },
- { "second", USEC_PER_SEC },
- { "sec", USEC_PER_SEC },
- { "s", USEC_PER_SEC },
+ { "seconds", USEC_PER_SEC },
+ { "second", USEC_PER_SEC },
+ { "sec", USEC_PER_SEC },
+ { "s", USEC_PER_SEC },
{ "minutes", USEC_PER_MINUTE },
- { "minute", USEC_PER_MINUTE },
- { "min", USEC_PER_MINUTE },
- { "months", USEC_PER_MONTH },
- { "month", USEC_PER_MONTH },
- { "msec", USEC_PER_MSEC },
- { "ms", USEC_PER_MSEC },
- { "m", USEC_PER_MINUTE },
- { "hours", USEC_PER_HOUR },
- { "hour", USEC_PER_HOUR },
- { "hr", USEC_PER_HOUR },
- { "h", USEC_PER_HOUR },
- { "days", USEC_PER_DAY },
- { "day", USEC_PER_DAY },
- { "d", USEC_PER_DAY },
- { "weeks", USEC_PER_WEEK },
- { "week", USEC_PER_WEEK },
- { "w", USEC_PER_WEEK },
- { "years", USEC_PER_YEAR },
- { "year", USEC_PER_YEAR },
- { "y", USEC_PER_YEAR },
- { "usec", 1ULL },
- { "us", 1ULL },
+ { "minute", USEC_PER_MINUTE },
+ { "min", USEC_PER_MINUTE },
+ { "months", USEC_PER_MONTH },
+ { "month", USEC_PER_MONTH },
+ { "M", USEC_PER_MONTH },
+ { "msec", USEC_PER_MSEC },
+ { "ms", USEC_PER_MSEC },
+ { "m", USEC_PER_MINUTE },
+ { "hours", USEC_PER_HOUR },
+ { "hour", USEC_PER_HOUR },
+ { "hr", USEC_PER_HOUR },
+ { "h", USEC_PER_HOUR },
+ { "days", USEC_PER_DAY },
+ { "day", USEC_PER_DAY },
+ { "d", USEC_PER_DAY },
+ { "weeks", USEC_PER_WEEK },
+ { "week", USEC_PER_WEEK },
+ { "w", USEC_PER_WEEK },
+ { "years", USEC_PER_YEAR },
+ { "year", USEC_PER_YEAR },
+ { "y", USEC_PER_YEAR },
+ { "usec", 1ULL },
+ { "us", 1ULL },
};
const char *p, *s;
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index d3bcc795ae..67e4e8b218 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -655,7 +655,18 @@ static int transient_unit_from_message(
if (r < 0)
return r;
- if (u->load_state != UNIT_NOT_FOUND ||
+ /* Check if the unit already exists or is already referenced,
+ * in a number of different ways. Note that to cater for unit
+ * types such as slice, we are generally fine with units that
+ * are marked UNIT_LOADED even even though nothing was
+ * actually loaded, as those unit types don't require a file
+ * on disk to validly load. */
+
+ if (!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) ||
+ u->fragment_path ||
+ u->source_path ||
+ !strv_isempty(u->dropin_paths) ||
+ u->refs ||
set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
@@ -1960,6 +1971,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultTasksMax", "t", NULL, offsetof(Manager, default_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 4c5376d601..799418033d 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -126,7 +126,7 @@ $1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0,
$1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
$1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context)
$1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting)
-$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context)
+$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context.tasks_max)
$1.Delegate, config_parse_bool, 0, offsetof($1, cgroup_context.delegate)
$1.NetClass, config_parse_netclass, 0, offsetof($1, cgroup_context)'
)m4_dnl
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 62cad0a0c0..5d013de2e8 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -2991,12 +2991,11 @@ int config_parse_tasks_max(
void *data,
void *userdata) {
- CGroupContext *c = data;
- uint64_t u;
+ uint64_t *tasks_max = data, u;
int r;
if (isempty(rvalue) || streq(rvalue, "infinity")) {
- c->tasks_max = (uint64_t) -1;
+ *tasks_max = (uint64_t) -1;
return 0;
}
@@ -3006,7 +3005,7 @@ int config_parse_tasks_max(
return 0;
}
- c->tasks_max = u;
+ *tasks_max = u;
return 0;
}
diff --git a/src/core/main.c b/src/core/main.c
index 33529c3e76..a09ce0f083 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -125,7 +125,8 @@ static FILE* arg_serialization = NULL;
static bool arg_default_cpu_accounting = false;
static bool arg_default_blockio_accounting = false;
static bool arg_default_memory_accounting = false;
-static bool arg_default_tasks_accounting = false;
+static bool arg_default_tasks_accounting = true;
+static uint64_t arg_default_tasks_max = UINT64_C(512);
static void pager_open_if_enabled(void) {
@@ -657,7 +658,7 @@ static int parse_config_file(void) {
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
- { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
+ { "Manager", "DefaultLimitCPU", config_parse_sec_limit, 0, &arg_default_rlimit[RLIMIT_CPU] },
{ "Manager", "DefaultLimitFSIZE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE] },
{ "Manager", "DefaultLimitDATA", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_DATA] },
{ "Manager", "DefaultLimitSTACK", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_STACK] },
@@ -672,11 +673,12 @@ static int parse_config_file(void) {
{ "Manager", "DefaultLimitMSGQUEUE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE] },
{ "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE] },
{ "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO] },
- { "Manager", "DefaultLimitRTTIME", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME] },
+ { "Manager", "DefaultLimitRTTIME", config_parse_usec_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME] },
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
{ "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
+ { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
{}
};
@@ -712,6 +714,7 @@ static void manager_set_defaults(Manager *m) {
m->default_blockio_accounting = arg_default_blockio_accounting;
m->default_memory_accounting = arg_default_memory_accounting;
m->default_tasks_accounting = arg_default_tasks_accounting;
+ m->default_tasks_max = arg_default_tasks_max;
manager_set_default_rlimits(m, arg_default_rlimit);
manager_environment_add(m, NULL, arg_default_environment);
diff --git a/src/core/manager.c b/src/core/manager.c
index f695b8a66c..edff6758c5 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -577,6 +577,8 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
m->running_as = running_as;
m->exit_code = _MANAGER_EXIT_CODE_INVALID;
m->default_timer_accuracy_usec = USEC_PER_MINUTE;
+ m->default_tasks_accounting = true;
+ m->default_tasks_max = UINT64_C(512);
/* Prepare log fields we can use for structured logging */
m->unit_log_field = unit_log_fields[running_as];
diff --git a/src/core/manager.h b/src/core/manager.h
index bc3f02f872..b5b258f909 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -260,6 +260,7 @@ struct Manager {
bool default_blockio_accounting;
bool default_tasks_accounting;
+ uint64_t default_tasks_max;
usec_t default_timer_accuracy_usec;
struct rlimit *rlimit[_RLIMIT_MAX];
diff --git a/src/core/scope.c b/src/core/scope.c
index 5f6527c155..1953af1f88 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -402,15 +402,10 @@ static bool scope_check_gc(Unit *u) {
/* Never clean up scopes that still have a process around,
* even if the scope is formally dead. */
- if (u->cgroup_path) {
- int r;
+ if (!u->cgroup_path)
+ return false;
- r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
- if (r <= 0)
- return true;
- }
-
- return false;
+ return cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path) <= 0;
}
static void scope_notify_cgroup_empty_event(Unit *u) {
@@ -577,6 +572,7 @@ const UnitVTable scope_vtable = {
.no_alias = true,
.no_instances = true,
+ .can_transient = true,
.init = scope_init,
.load = scope_load,
@@ -611,7 +607,5 @@ const UnitVTable scope_vtable = {
.bus_set_property = bus_scope_set_property,
.bus_commit_properties = bus_scope_commit_properties,
- .can_transient = true,
-
.enumerate = scope_enumerate,
};
diff --git a/src/core/slice.c b/src/core/slice.c
index 39dabae055..9c488f0fd7 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -305,6 +305,7 @@ const UnitVTable slice_vtable = {
.no_alias = true,
.no_instances = true,
+ .can_transient = true,
.load = slice_load,
diff --git a/src/core/system.conf b/src/core/system.conf
index 50668e12c4..e2ded27333 100644
--- a/src/core/system.conf
+++ b/src/core/system.conf
@@ -40,7 +40,8 @@
#DefaultCPUAccounting=no
#DefaultBlockIOAccounting=no
#DefaultMemoryAccounting=no
-#DefaultTasksAccounting=no
+#DefaultTasksAccounting=yes
+#DefaultTasksMax=512
#DefaultLimitCPU=
#DefaultLimitFSIZE=
#DefaultLimitDATA=
diff --git a/src/core/unit.c b/src/core/unit.c
index f553f24829..d199d87bf8 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -132,6 +132,9 @@ static void unit_init(Unit *u) {
cc->blockio_accounting = u->manager->default_blockio_accounting;
cc->memory_accounting = u->manager->default_memory_accounting;
cc->tasks_accounting = u->manager->default_tasks_accounting;
+
+ if (u->type != UNIT_SLICE)
+ cc->tasks_max = u->manager->default_tasks_max;
}
ec = unit_get_exec_context(u);
@@ -314,9 +317,6 @@ bool unit_check_gc(Unit *u) {
if (state != UNIT_INACTIVE)
return true;
- if (UNIT_VTABLE(u)->no_gc)
- return true;
-
if (u->no_gc)
return true;
diff --git a/src/core/unit.h b/src/core/unit.h
index 14e3072146..bcf41d2348 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -403,9 +403,6 @@ struct UnitVTable {
/* Instances make no sense for this type */
bool no_instances:1;
- /* Exclude from automatic gc */
- bool no_gc:1;
-
/* True if transient units of this type are OK */
bool can_transient:1;
};
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 5cc90c6e24..7cc0044bab 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -2753,13 +2753,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) {
@@ -2827,6 +2915,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 1d561a6f8a..6c4ada29fb 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -513,25 +513,31 @@ 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;
- _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 {
@@ -543,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 <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;
}
diff --git a/src/login/logind.c b/src/login/logind.c
index be6bbe5b5c..7b41174c64 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_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 6df6f04c77..81f6695434 100644
--- a/src/login/logind.conf
+++ b/src/login/logind.conf
@@ -32,3 +32,4 @@
#IdleActionSec=30min
#RuntimeDirectorySize=10%
#RemoveIPC=yes
+#UserTasksMax=4096
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);
diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c
index 374f958c20..50871464c5 100644
--- a/src/nspawn/nspawn-register.c
+++ b/src/nspawn/nspawn-register.c
@@ -105,6 +105,10 @@ int register_machine(
return bus_log_create_error(r);
}
+ r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", 8192);
+ if (r < 0)
+ return bus_log_create_error(r);
+
r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
if (r < 0)
return bus_log_create_error(r);
diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c
index de6c421b82..85b0d607d6 100644
--- a/src/test/test-cgroup-mask.c
+++ b/src/test/test-cgroup-mask.c
@@ -40,6 +40,16 @@ static int test_cgroup_mask(void) {
puts("manager_new: Permission denied. Skipping test.");
return EXIT_TEST_SKIP;
}
+
+ /* Turn off all kinds of default accouning, so that we can
+ * verify the masks resulting of our configuration and nothing
+ * else. */
+ m->default_cpu_accounting =
+ m->default_memory_accounting =
+ m->default_blockio_accounting =
+ m->default_tasks_accounting = false;
+ m->default_tasks_max = (uint64_t) -1;
+
assert_se(r >= 0);
assert_se(manager_startup(m, serial, fdset) >= 0);
diff --git a/units/systemd-nspawn@.service.in b/units/systemd-nspawn@.service.in
index 2e79adff44..eb10343ac6 100644
--- a/units/systemd-nspawn@.service.in
+++ b/units/systemd-nspawn@.service.in
@@ -20,6 +20,7 @@ RestartForceExitStatus=133
SuccessExitStatus=133
Slice=machine.slice
Delegate=yes
+TasksMax=8192
# Enforce a strict device policy, similar to the one nspawn configures
# when it allocates its own scope unit. Make sure to keep these