From ecee72e1b6c3476b674b58472c483fc4aef7ceed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 15:24:21 +0100 Subject: core: make sure DefaultLimitCPU= and DefaultLimitRTTIME= understand time units, too We added this for the per-unit setting, hence let's enable this for the global default settings too. --- src/core/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/main.c b/src/core/main.c index 33529c3e76..0924b51a7d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -657,7 +657,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,7 +672,7 @@ 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 }, -- cgit v1.2.3-54-g00ecf From 0af20ea2ee2af2bcf2258e7a8e1a13181a6a75d6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 17:13:55 +0100 Subject: core: add new DefaultTasksMax= setting for system.conf This allows initializing the TasksMax= setting of all units by default to some fixed value, instead of leaving it at infinity as before. --- man/systemd-system.conf.xml | 13 ++++++++++++- man/systemd.resource-control.xml | 5 ++++- src/core/dbus-manager.c | 1 + src/core/load-fragment-gperf.gperf.m4 | 2 +- src/core/load-fragment.c | 7 +++---- src/core/main.c | 3 +++ src/core/manager.c | 1 + src/core/manager.h | 1 + src/core/system.conf | 1 + src/core/unit.c | 3 +++ 10 files changed, 30 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 54ce992b85..0050f24f8e 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -1,4 +1,4 @@ - + @@ -320,6 +320,17 @@ for details on the per-unit settings. + + DefaultTasksMax= + + Configure the default value for the per-unit + TasksMax= setting. See + systemd.resource-control5 + for details. This setting applies to all unit types that + support resource control settings, with the exception of slice + units. + + DefaultLimitCPU= DefaultLimitFSIZE= 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 pids.txt. - Implies TasksAccounting=true. + Implies TasksAccounting=true. The + system default for this setting may be controlled with + DefaultTasksMax= in + systemd-system.conf5. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index d3bcc795ae..72ad6121e0 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1960,6 +1960,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 0924b51a7d..f8e1d88335 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -126,6 +126,7 @@ 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 uint64_t arg_default_tasks_max = (uint64_t) -1; static void pager_open_if_enabled(void) { @@ -677,6 +678,7 @@ static int parse_config_file(void) { { "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..fd915d748c 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -577,6 +577,7 @@ 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_max = (uint64_t) -1; /* 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/system.conf b/src/core/system.conf index 50668e12c4..63bff085eb 100644 --- a/src/core/system.conf +++ b/src/core/system.conf @@ -41,6 +41,7 @@ #DefaultBlockIOAccounting=no #DefaultMemoryAccounting=no #DefaultTasksAccounting=no +#DefaultTasksMax= #DefaultLimitCPU= #DefaultLimitFSIZE= #DefaultLimitDATA= diff --git a/src/core/unit.c b/src/core/unit.c index f553f24829..a5872ef30a 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); -- cgit v1.2.3-54-g00ecf From 08c77cf3987b52d0380b3d7d239ba254447692ee Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 18:07:39 +0100 Subject: btrfs: properly handle the case when a subvol has no parent Don't be confused by subvols without parent. This is after all how the root subvol is set up. --- src/basic/btrfs-util.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'src') 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; -- cgit v1.2.3-54-g00ecf From eb55ec9feccead1ea359fccf915fa8333ec20879 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 18:12:37 +0100 Subject: util-lib: when parsing time values, accept "M" as short for "month" nginx defines an uppercase "M" that way (in contrast to the lowercase "m" for "minute"), and it sounds like an OK logic to follow, so that we understand a true superset of time values nginx understands. http://nginx.org/en/docs/syntax.html --- man/systemd.time.xml | 2 +- src/basic/time-util.c | 71 ++++++++++++++++++++++++++------------------------- 2 files changed, 37 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/man/systemd.time.xml b/man/systemd.time.xml index 135eb35f1b..ec13781f15 100644 --- a/man/systemd.time.xml +++ b/man/systemd.time.xml @@ -82,7 +82,7 @@ hours, hour, hr, h days, day, d weeks, week, w - months, month + months, month, M years, year, y 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; -- cgit v1.2.3-54-g00ecf From 17f62e9bd00f5fefd486475861b06d3ec6b7ee10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 18:46:50 +0100 Subject: core: enable transient unit support for slice units --- src/core/dbus-manager.c | 13 ++++++++++++- src/core/slice.c | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 72ad6121e0..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); 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, -- cgit v1.2.3-54-g00ecf 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') 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') 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 700e2d63b7458e57203355f840bd1dcc1fb46645 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 18:46:12 +0100 Subject: core: simplify scope unit GC checking code a bit --- src/core/scope.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src') 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, }; -- cgit v1.2.3-54-g00ecf From 702d4e6f14b0c92f7325fcdc3650c79c2221849e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 18:48:42 +0100 Subject: core: now that .snapshot unit are gone, we don't need the per-type .no_gc bool anymore --- src/core/unit.c | 3 --- src/core/unit.h | 3 --- 2 files changed, 6 deletions(-) (limited to 'src') diff --git a/src/core/unit.c b/src/core/unit.c index a5872ef30a..d199d87bf8 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -317,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; }; -- cgit v1.2.3-54-g00ecf From 9ded9cd14cc03c67291b10a5c42ce5094ba0912f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 19:28:32 +0100 Subject: core: enable TasksMax= for all services by default, and set it to 512 Also, enable TasksAccounting= for all services by default, too. See: http://lists.freedesktop.org/archives/systemd-devel/2015-November/035006.html --- man/systemd-system.conf.xml | 6 ++++-- src/core/main.c | 4 ++-- src/core/manager.c | 3 ++- src/core/system.conf | 4 ++-- src/test/test-cgroup-mask.c | 10 ++++++++++ 5 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 0050f24f8e..ead52951da 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -317,7 +317,9 @@ MemoryAccounting= and TasksAccounting=. See systemd.resource-control5 - for details on the per-unit settings. + for details on the per-unit + settings. DefaulTasksAccounting= defaults + to on, the other three settings to off. @@ -328,7 +330,7 @@ systemd.resource-control5 for details. This setting applies to all unit types that support resource control settings, with the exception of slice - units. + units. Defaults to 512. diff --git a/src/core/main.c b/src/core/main.c index f8e1d88335..a09ce0f083 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -125,8 +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 uint64_t arg_default_tasks_max = (uint64_t) -1; +static bool arg_default_tasks_accounting = true; +static uint64_t arg_default_tasks_max = UINT64_C(512); static void pager_open_if_enabled(void) { diff --git a/src/core/manager.c b/src/core/manager.c index fd915d748c..edff6758c5 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -577,7 +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_max = (uint64_t) -1; + 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/system.conf b/src/core/system.conf index 63bff085eb..e2ded27333 100644 --- a/src/core/system.conf +++ b/src/core/system.conf @@ -40,8 +40,8 @@ #DefaultCPUAccounting=no #DefaultBlockIOAccounting=no #DefaultMemoryAccounting=no -#DefaultTasksAccounting=no -#DefaultTasksMax= +#DefaultTasksAccounting=yes +#DefaultTasksMax=512 #DefaultLimitCPU= #DefaultLimitFSIZE= #DefaultLimitDATA= 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); -- 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') 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 From 541ec33075f9f2461b5286592312d2b50295ad32 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Nov 2015 19:38:40 +0100 Subject: nspawn: set TasksMax= for containers to 8192 by default --- src/nspawn/nspawn-register.c | 4 ++++ units/systemd-nspawn@.service.in | 1 + 2 files changed, 5 insertions(+) (limited to 'src') 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/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 -- cgit v1.2.3-54-g00ecf