From 83f8e80857090f63cf6a02c54d381dad3c0fad55 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 15:58:49 +0200 Subject: core: support percentage specifications on TasksMax= This adds support for a TasksMax=40% syntax for specifying values relative to the system's configured maximum number of processes. This is useful in order to neatly subdivide the available room for tasks within containers. --- src/core/dbus-cgroup.c | 22 ++++++++++++++++++++++ src/core/load-fragment.c | 15 ++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 6167ce92cd..b3e2830c11 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -1060,6 +1060,8 @@ int bus_cgroup_set_property( r = sd_bus_message_read(message, "t", &limit); if (r < 0) return r; + if (limit <= 0) + return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name); if (mode != UNIT_CHECK) { c->tasks_max = limit; @@ -1071,6 +1073,26 @@ int bus_cgroup_set_property( unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit); } + return 1; + } else if (streq(name, "TasksMaxScale")) { + uint64_t limit; + uint32_t raw; + + r = sd_bus_message_read(message, "u", &raw); + if (r < 0) + return r; + + limit = system_tasks_max_scale(raw, UINT32_MAX); + if (limit <= 0 || limit >= UINT64_MAX) + return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name); + + if (mode != UNIT_CHECK) { + c->tasks_max = limit; + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); + unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu32 "%%", + (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); + } + return 1; } diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 782e420e4c..cd7bf9c707 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2861,9 +2861,18 @@ int config_parse_tasks_max( return 0; } - r = safe_atou64(rvalue, &u); - if (r < 0 || u < 1) { - log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue); + r = parse_percent(rvalue); + if (r < 0) { + r = safe_atou64(rvalue, &u); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue); + return 0; + } + } else + u = system_tasks_max_scale(r, 100U); + + if (u <= 0 || u >= UINT64_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range. Ignoring.", rvalue); return 0; } -- cgit v1.2.3-54-g00ecf From f7903e8db673505328ba904f050f5ec52cf79c23 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 16:10:15 +0200 Subject: core: rename MemoryLimitByPhysicalMemory transient property to MemoryLimitScale That way, we can neatly keep this in line with the new TasksMaxScale= option. Note that we didn't release a version with MemoryLimitByPhysicalMemory= yet, hence this change should be unproblematic without breaking API. --- src/core/dbus-cgroup.c | 12 +++++++----- src/shared/bus-unit-util.c | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index b3e2830c11..85b0c86a2f 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -856,7 +856,7 @@ int bus_cgroup_set_property( return 1; - } else if (STR_IN_SET(name, "MemoryLowByPhysicalMemory", "MemoryHighByPhysicalMemory", "MemoryMaxByPhysicalMemory")) { + } else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale")) { uint32_t raw; uint64_t v; @@ -872,7 +872,7 @@ int bus_cgroup_set_property( const char *e; /* Chop off suffix */ - assert_se(e = endswith(name, "ByPhysicalMemory")); + assert_se(e = endswith(name, "Scale")); name = strndupa(name, e - name); if (streq(name, "MemoryLow")) @@ -883,7 +883,8 @@ int bus_cgroup_set_property( c->memory_max = v; unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY); - unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu32 "%%", name, (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100, (uint64_t) UINT32_MAX))); + unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu32 "%%", name, + (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); } return 1; @@ -909,7 +910,7 @@ int bus_cgroup_set_property( return 1; - } else if (streq(name, "MemoryLimitByPhysicalMemory")) { + } else if (streq(name, "MemoryLimitScale")) { uint64_t limit; uint32_t raw; @@ -924,7 +925,8 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->memory_limit = limit; unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY); - unit_write_drop_in_private_format(u, mode, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%", (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100, (uint64_t) UINT32_MAX))); + unit_write_drop_in_private_format(u, mode, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%", + (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); } return 1; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index e63e9195f1..ea020b517b 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -132,10 +132,10 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen char *n; /* When this is a percentage we'll convert this into a relative value in the range - * 0…UINT32_MAX and pass it in the MemoryLowByPhysicalMemory property (and related + * 0…UINT32_MAX and pass it in the MemoryLowScale property (and related * ones). This way the physical memory size can be determined server-side */ - n = strjoina(field, "ByPhysicalMemory"); + n = strjoina(field, "Scale"); r = sd_bus_message_append(m, "sv", n, "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U)); goto finish; -- cgit v1.2.3-54-g00ecf From 84af7821b65ad11417ac2984717cf42a3655fcd7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 17:00:36 +0200 Subject: main: simplify things a bit by moving container check into fixup_environment() --- src/core/main.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src/core') diff --git a/src/core/main.c b/src/core/main.c index fc04fb8051..4c767a3c9d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1298,6 +1298,11 @@ static int fixup_environment(void) { _cleanup_free_ char *term = NULL; int r; + /* We expect the environment to be set correctly + * if run inside a container. */ + if (detect_container() > 0) + return 0; + /* When started as PID1, the kernel uses /dev/console * for our stdios and uses TERM=linux whatever the * backend device used by the console. We try to make @@ -1314,7 +1319,7 @@ static int fixup_environment(void) { if (r == 0) { term = strdup(default_term_for_tty("/dev/console") + 5); if (!term) - return -errno; + return -ENOMEM; } if (setenv("TERM", term, 1) < 0) @@ -1508,13 +1513,10 @@ int main(int argc, char *argv[]) { } if (arg_system) { - /* We expect the environment to be set correctly - * if run inside a container. */ - if (detect_container() <= 0) - if (fixup_environment() < 0) { - error_message = "Failed to fix up PID1 environment"; - goto finish; - } + if (fixup_environment() < 0) { + error_message = "Failed to fix up PID1 environment"; + goto finish; + } /* Try to figure out if we can use colors with the console. No * need to do that for user instances since they never log -- cgit v1.2.3-54-g00ecf From 79baeeb96d58676853521e10a358e85d83dac7f1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 17:29:00 +0200 Subject: core: change TasksMax= default for system services to 15% As it turns out 512 is max number of tasks per service is hit by too many applications, hence let's bump it a bit, and make it relative to the system's maximum number of PIDs. With this change the new default is 15%. At the kernel's default pids_max value of 32768 this translates to 4915. At machined's default TasksMax= setting of 16384 this translates to 2457. Why 15%? Because it sounds like a round number and is close enough to 4096 which I was going for, i.e. an eight-fold increase over the old 512 Summary: | on the host | in a container old default | 512 | 512 new default | 4915 | 2457 --- man/systemd-system.conf.xml | 9 ++++----- src/core/main.c | 4 +++- src/core/manager.c | 2 +- src/core/system.conf | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src/core') diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 8833e73c72..1bb40fd234 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -325,12 +325,11 @@ DefaultTasksMax= - Configure the default value for the per-unit - TasksMax= setting. See + 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. Defaults to 512. + for details. This setting applies to all unit types that support resource control settings, with the exception + of slice units. Defaults to 15%, which equals 4915 with the kernel's defaults on the host, but might be smaller + in OS containers. diff --git a/src/core/main.c b/src/core/main.c index 4c767a3c9d..c59228ad53 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -127,7 +127,7 @@ static bool arg_default_io_accounting = false; static bool arg_default_blockio_accounting = false; static bool arg_default_memory_accounting = false; static bool arg_default_tasks_accounting = true; -static uint64_t arg_default_tasks_max = UINT64_C(512); +static uint64_t arg_default_tasks_max = UINT64_MAX; static sd_id128_t arg_machine_id = {}; noreturn static void freeze_or_reboot(void) { @@ -1558,6 +1558,8 @@ int main(int argc, char *argv[]) { (void) reset_all_signal_handlers(); (void) ignore_signals(SIGNALS_IGNORE, -1); + arg_default_tasks_max = system_tasks_max_scale(15U, 100U); /* 15% the system PIDs equals 4915 by default. */ + if (parse_config_file() < 0) { error_message = "Failed to parse config file"; goto finish; diff --git a/src/core/manager.c b/src/core/manager.c index a0181e2138..4d84a0b37e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -569,7 +569,7 @@ int manager_new(UnitFileScope scope, bool test_run, Manager **_m) { 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); + m->default_tasks_max = UINT64_MAX; #ifdef ENABLE_EFI if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) diff --git a/src/core/system.conf b/src/core/system.conf index db8b7acd78..c6bb050aac 100644 --- a/src/core/system.conf +++ b/src/core/system.conf @@ -42,7 +42,7 @@ #DefaultBlockIOAccounting=no #DefaultMemoryAccounting=no #DefaultTasksAccounting=yes -#DefaultTasksMax=512 +#DefaultTasksMax=15% #DefaultLimitCPU= #DefaultLimitFSIZE= #DefaultLimitDATA= -- cgit v1.2.3-54-g00ecf From b3785cd5e6a0ac4d465713db221e1a150aabd5f6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 22 Jul 2016 15:30:23 +0200 Subject: core: check for overflow when handling scaled MemoryLimit= settings Just in case... --- src/core/load-fragment.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index cd7bf9c707..ae306de4ae 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2823,8 +2823,8 @@ int config_parse_memory_limit( } else bytes = physical_memory_scale(r, 100U); - if (bytes < 1) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' too small. Ignoring.", rvalue); + if (bytes <= 0 || bytes >= UINT64_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range. Ignoring.", rvalue); return 0; } } -- cgit v1.2.3-54-g00ecf