From ebea3f9a926566c1e842102964c3ebb3e57fafd98def29b23bfa65d12a14ab5c Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 23 Jan 2024 13:52:53 +0000 Subject: [PATCH] - Add patches that implement [jsc#PED-5659] 5003-cgroup-rename-TasksMax-structure-to-CGroupTasksMax.patch 5004-bus-print-properties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch 5005-bus-print-properties-prettify-more-unset-properties.patch 5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch 5007-test-Convert-rlimit-test-to-subtest-of-generic-limit.patch 5008-test-Add-effective-cgroup-limits-testing.patch 5009-cgroup-Restrict-effective-limits-with-global-resourc.patch 5010-cgroup-Rename-effective-limits-internal-table.patch They are temporarily put in quarantine to get broader testing but should be eventually moved to the git repo. OBS-URL: https://build.opensuse.org/package/show/Base:System/systemd?expand=0&rev=1485 --- ...TasksMax-structure-to-CGroupTasksMax.patch | 283 ++++++++ ...ties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch | 31 + ...rties-prettify-more-unset-properties.patch | 38 ++ ...tiveMemoryMax-EffectiveMemoryHigh-an.patch | 607 ++++++++++++++++++ ...mit-test-to-subtest-of-generic-limit.patch | 97 +++ ...-Add-effective-cgroup-limits-testing.patch | 111 ++++ ...effective-limits-with-global-resourc.patch | 56 ++ ...name-effective-limits-internal-table.patch | 64 ++ systemd.changes | 17 + systemd.spec | 9 + 10 files changed, 1313 insertions(+) create mode 100644 5003-cgroup-rename-TasksMax-structure-to-CGroupTasksMax.patch create mode 100644 5004-bus-print-properties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch create mode 100644 5005-bus-print-properties-prettify-more-unset-properties.patch create mode 100644 5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch create mode 100644 5007-test-Convert-rlimit-test-to-subtest-of-generic-limit.patch create mode 100644 5008-test-Add-effective-cgroup-limits-testing.patch create mode 100644 5009-cgroup-Restrict-effective-limits-with-global-resourc.patch create mode 100644 5010-cgroup-Rename-effective-limits-internal-table.patch diff --git a/5003-cgroup-rename-TasksMax-structure-to-CGroupTasksMax.patch b/5003-cgroup-rename-TasksMax-structure-to-CGroupTasksMax.patch new file mode 100644 index 00000000..f3ca94ab --- /dev/null +++ b/5003-cgroup-rename-TasksMax-structure-to-CGroupTasksMax.patch @@ -0,0 +1,283 @@ +From 14146f22cdcb6ecbf7d0f46a34843837a21aa118 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 23 Jan 2024 11:30:14 +0100 +Subject: [PATCH 5003/5011] cgroup: rename TasksMax structure to CGroupTasksMax + +Almost all our enums/structs/funcs carry the CGroup prefix if they are +defined in cgroup.h, TasksMax so far does not, even though it is +exclusively used in cgroup context. + +Change that. + +(cherry picked from commit 94f0b13b1623c083ece9c0381bd1e65500dc1363) + +[mkoutny: Adjust for missing struct UnitDefaults + contexts] +--- + src/core/cgroup.c | 16 ++++++++-------- + src/core/cgroup.h | 12 ++++++------ + src/core/dbus-cgroup.c | 10 +++++----- + src/core/load-fragment.c | 10 +++++----- + src/core/main.c | 4 ++-- + src/core/manager.c | 2 +- + src/core/manager.h | 2 +- + src/test/test-cgroup-mask.c | 2 +- + 8 files changed, 29 insertions(+), 29 deletions(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 8a3059b042..5b7205a92e 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -51,7 +51,7 @@ + * out specific attributes from us. */ + #define LOG_LEVEL_CGROUP_WRITE(r) (IN_SET(abs(r), ENOENT, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING) + +-uint64_t tasks_max_resolve(const TasksMax *tasks_max) { ++uint64_t cgroup_tasks_max_resolve(const CGroupTasksMax *tasks_max) { + if (tasks_max->scale == 0) + return tasks_max->value; + +@@ -170,7 +170,7 @@ void cgroup_context_init(CGroupContext *c) { + .blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID, + .startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID, + +- .tasks_max = TASKS_MAX_UNSET, ++ .tasks_max = CGROUP_TASKS_MAX_UNSET, + + .moom_swap = MANAGED_OOM_AUTO, + .moom_mem_pressure = MANAGED_OOM_AUTO, +@@ -562,7 +562,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { + prefix, c->memory_zswap_max, format_cgroup_memory_limit_comparison(cdj, sizeof(cdj), u, "MemoryZSwapMax"), + prefix, c->startup_memory_zswap_max, format_cgroup_memory_limit_comparison(cdk, sizeof(cdk), u, "StartupMemoryZSwapMax"), + prefix, c->memory_limit, +- prefix, tasks_max_resolve(&c->tasks_max), ++ prefix, cgroup_tasks_max_resolve(&c->tasks_max), + prefix, cgroup_device_policy_to_string(c->device_policy), + prefix, strempty(disable_controllers_str), + prefix, delegate_str, +@@ -1760,9 +1760,9 @@ static void cgroup_context_apply( + * which is desirable so that there's an official way to release control of the sysctl from + * systemd: set the limit to unbounded and reload. */ + +- if (tasks_max_isset(&c->tasks_max)) { ++ if (cgroup_tasks_max_isset(&c->tasks_max)) { + u->manager->sysctl_pid_max_changed = true; +- r = procfs_tasks_set_limit(tasks_max_resolve(&c->tasks_max)); ++ r = procfs_tasks_set_limit(cgroup_tasks_max_resolve(&c->tasks_max)); + } else if (u->manager->sysctl_pid_max_changed) + r = procfs_tasks_set_limit(TASKS_MAX); + else +@@ -1775,10 +1775,10 @@ static void cgroup_context_apply( + /* The attribute itself is not available on the host root cgroup, and in the container case we want to + * leave it for the container manager. */ + if (!is_local_root) { +- if (tasks_max_isset(&c->tasks_max)) { ++ if (cgroup_tasks_max_isset(&c->tasks_max)) { + char buf[DECIMAL_STR_MAX(uint64_t) + 1]; + +- xsprintf(buf, "%" PRIu64 "\n", tasks_max_resolve(&c->tasks_max)); ++ xsprintf(buf, "%" PRIu64 "\n", cgroup_tasks_max_resolve(&c->tasks_max)); + (void) set_attribute_and_warn(u, "pids", "pids.max", buf); + } else + (void) set_attribute_and_warn(u, "pids", "pids.max", "max\n"); +@@ -1894,7 +1894,7 @@ static CGroupMask unit_get_cgroup_mask(Unit *u) { + mask |= CGROUP_MASK_DEVICES | CGROUP_MASK_BPF_DEVICES; + + if (c->tasks_accounting || +- tasks_max_isset(&c->tasks_max)) ++ cgroup_tasks_max_isset(&c->tasks_max)) + mask |= CGROUP_MASK_PIDS; + + return CGROUP_MASK_EXTEND_JOINED(mask); +diff --git a/src/core/cgroup.h b/src/core/cgroup.h +index 9f1963b3f2..486957b545 100644 +--- a/src/core/cgroup.h ++++ b/src/core/cgroup.h +@@ -9,20 +9,20 @@ + #include "list.h" + #include "time-util.h" + +-typedef struct TasksMax { ++typedef struct CGroupTasksMax { + /* If scale == 0, just use value; otherwise, value / scale. + * See tasks_max_resolve(). */ + uint64_t value; + uint64_t scale; +-} TasksMax; ++} CGroupTasksMax; + +-#define TASKS_MAX_UNSET ((TasksMax) { .value = UINT64_MAX, .scale = 0 }) ++#define CGROUP_TASKS_MAX_UNSET ((CGroupTasksMax) { .value = UINT64_MAX, .scale = 0 }) + +-static inline bool tasks_max_isset(const TasksMax *tasks_max) { ++static inline bool cgroup_tasks_max_isset(const CGroupTasksMax *tasks_max) { + return tasks_max->value != UINT64_MAX || tasks_max->scale != 0; + } + +-uint64_t tasks_max_resolve(const TasksMax *tasks_max); ++uint64_t cgroup_tasks_max_resolve(const CGroupTasksMax *tasks_max); + + typedef struct CGroupContext CGroupContext; + typedef struct CGroupDeviceAllow CGroupDeviceAllow; +@@ -210,7 +210,7 @@ struct CGroupContext { + LIST_HEAD(CGroupSocketBindItem, socket_bind_deny); + + /* Common */ +- TasksMax tasks_max; ++ CGroupTasksMax tasks_max; + + /* Settings for systemd-oomd */ + ManagedOOMMode moom_swap; +diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c +index 5347525844..3c35673779 100644 +--- a/src/core/dbus-cgroup.c ++++ b/src/core/dbus-cgroup.c +@@ -25,7 +25,7 @@ + #include "percent-util.h" + #include "socket-util.h" + +-BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve); ++BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", CGroupTasksMax, cgroup_tasks_max_resolve); + BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_cgroup_pressure_watch, cgroup_pressure_watch, CGroupPressureWatch); + + static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy); +@@ -994,7 +994,7 @@ static int bus_cgroup_set_cpu_weight( + static int bus_cgroup_set_tasks_max( + Unit *u, + const char *name, +- TasksMax *p, ++ CGroupTasksMax *p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { +@@ -1013,7 +1013,7 @@ static int bus_cgroup_set_tasks_max( + "Value specified in %s is out of range", name); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { +- *p = (TasksMax) { .value = v, .scale = 0 }; /* When .scale==0, .value is the absolute value */ ++ *p = (CGroupTasksMax) { .value = v, .scale = 0 }; /* When .scale==0, .value is the absolute value */ + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); + + if (v == CGROUP_LIMIT_MAX) +@@ -1030,7 +1030,7 @@ static int bus_cgroup_set_tasks_max( + static int bus_cgroup_set_tasks_max_scale( + Unit *u, + const char *name, +- TasksMax *p, ++ CGroupTasksMax *p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { +@@ -1049,7 +1049,7 @@ static int bus_cgroup_set_tasks_max_scale( + "Value specified in %s is out of range", name); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { +- *p = (TasksMax) { v, UINT32_MAX }; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */ ++ *p = (CGroupTasksMax) { v, UINT32_MAX }; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */ + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); + + uint32_t scaled = DIV_ROUND_UP((uint64_t) v * 100U, (uint64_t) UINT32_MAX); +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 86235fa5b6..18ba95a6c5 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -3934,23 +3934,23 @@ int config_parse_tasks_max( + void *userdata) { + + const Unit *u = userdata; +- TasksMax *tasks_max = data; ++ CGroupTasksMax *tasks_max = data; + uint64_t v; + int r; + + if (isempty(rvalue)) { +- *tasks_max = u ? u->manager->default_tasks_max : TASKS_MAX_UNSET; ++ *tasks_max = u ? u->manager->default_tasks_max : CGROUP_TASKS_MAX_UNSET; + return 0; + } + + if (streq(rvalue, "infinity")) { +- *tasks_max = TASKS_MAX_UNSET; ++ *tasks_max = CGROUP_TASKS_MAX_UNSET; + return 0; + } + + r = parse_permyriad(rvalue); + if (r >= 0) +- *tasks_max = (TasksMax) { r, 10000U }; /* r‱ */ ++ *tasks_max = (CGroupTasksMax) { r, 10000U }; /* r‱ */ + else { + r = safe_atou64(rvalue, &v); + if (r < 0) { +@@ -3963,7 +3963,7 @@ int config_parse_tasks_max( + return 0; + } + +- *tasks_max = (TasksMax) { v }; ++ *tasks_max = (CGroupTasksMax) { v }; + } + + return 0; +diff --git a/src/core/main.c b/src/core/main.c +index 14aa1f00c0..efe75d96b3 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -106,7 +106,7 @@ + #include + #endif + +-#define DEFAULT_TASKS_MAX ((TasksMax) { 15U, 100U }) /* 15% */ ++#define DEFAULT_TASKS_MAX ((CGroupTasksMax) { 15U, 100U }) /* 15% */ + + static enum { + ACTION_RUN, +@@ -166,7 +166,7 @@ static bool arg_default_ip_accounting; + static bool arg_default_blockio_accounting; + static bool arg_default_memory_accounting; + static bool arg_default_tasks_accounting; +-static TasksMax arg_default_tasks_max; ++static CGroupTasksMax arg_default_tasks_max; + static usec_t arg_default_memory_pressure_threshold_usec; + static CGroupPressureWatch arg_default_memory_pressure_watch; + static sd_id128_t arg_machine_id; +diff --git a/src/core/manager.c b/src/core/manager.c +index 2ccb753888..5f4522392d 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -840,7 +840,7 @@ int manager_new(RuntimeScope runtime_scope, ManagerTestRunFlags test_run_flags, + .default_timer_accuracy_usec = USEC_PER_MINUTE, + .default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT, + .default_tasks_accounting = true, +- .default_tasks_max = TASKS_MAX_UNSET, ++ .default_tasks_max = CGROUP_TASKS_MAX_UNSET, + .default_timeout_start_usec = manager_default_timeout(runtime_scope), + .default_timeout_stop_usec = manager_default_timeout(runtime_scope), + .default_restart_usec = DEFAULT_RESTART_USEC, +diff --git a/src/core/manager.h b/src/core/manager.h +index a6c87dc852..e4b2393d06 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -375,7 +375,7 @@ struct Manager { + bool default_tasks_accounting; + bool default_ip_accounting; + +- TasksMax default_tasks_max; ++ CGroupTasksMax default_tasks_max; + usec_t default_timer_accuracy_usec; + + OOMPolicy default_oom_policy; +diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c +index c0bf585963..35b2599e86 100644 +--- a/src/test/test-cgroup-mask.c ++++ b/src/test/test-cgroup-mask.c +@@ -58,7 +58,7 @@ TEST_RET(cgroup_mask, .sd_booted = true) { + m->default_blockio_accounting = + m->default_io_accounting = + m->default_tasks_accounting = false; +- m->default_tasks_max = TASKS_MAX_UNSET; ++ m->default_tasks_max = CGROUP_TASKS_MAX_UNSET; + + assert_se(manager_startup(m, NULL, NULL, NULL) >= 0); + +-- +2.35.3 + diff --git a/5004-bus-print-properties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch b/5004-bus-print-properties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch new file mode 100644 index 00000000..ed0b3971 --- /dev/null +++ b/5004-bus-print-properties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch @@ -0,0 +1,31 @@ +From c44ecd40ed4b4221dd9f03f5c2090d994889064c Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Tue, 23 Jan 2024 11:30:15 +0100 +Subject: [PATCH 5004/5011] bus-print-properties: ignore CGROUP_LIMIT_MAX for + Memory*{Current, Peak} + +MemoryCurrent and MemoryAvailable are shown as "[not set]" when UINT64_MAX +(unset). Let's do the same for the newly-added Memory*{Current,Peak} properties. + +(cherry picked from commit 3f362012ce0034dc14d3c1a1c2a3a64a11efa9da) + +[mkoutny: Drop MemoryPeak=] +--- + src/shared/bus-print-properties.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/shared/bus-print-properties.c b/src/shared/bus-print-properties.c +index db41ad2495..46724c98fa 100644 +--- a/src/shared/bus-print-properties.c ++++ b/src/shared/bus-print-properties.c +@@ -158,6 +158,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b + (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) || + (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) || + (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == UINT64_MAX) || ++ (startswith(name, "Memory") && ENDSWITH_SET(name, "Current") && u == CGROUP_LIMIT_MAX) || + (endswith(name, "NSec") && u == UINT64_MAX)) + + bus_print_property_value(name, expected_value, flags, "[not set]"); +-- +2.35.3 + diff --git a/5005-bus-print-properties-prettify-more-unset-properties.patch b/5005-bus-print-properties-prettify-more-unset-properties.patch new file mode 100644 index 00000000..ebc9eb1f --- /dev/null +++ b/5005-bus-print-properties-prettify-more-unset-properties.patch @@ -0,0 +1,38 @@ +From 278ef74e90a13821fc2209eb09de768035e14478 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Tue, 23 Jan 2024 11:30:16 +0100 +Subject: [PATCH 5005/5011] bus-print-properties: prettify more unset + properties + +(cherry picked from commit bfb6b1214a8da947cb82fed2eec3d7f2b1c6175f) + +[mkoutny: Handle MemoryAvailable= separately.] +--- + src/shared/bus-print-properties.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/shared/bus-print-properties.c b/src/shared/bus-print-properties.c +index 46724c98fa..f74d8994ad 100644 +--- a/src/shared/bus-print-properties.c ++++ b/src/shared/bus-print-properties.c +@@ -157,13 +157,15 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b + else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) || + (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) || + (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) || +- (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == UINT64_MAX) || ++ (STR_IN_SET(name, "MemoryCurrent", "MemoryAvailable", "TasksCurrent") && u == UINT64_MAX) || + (startswith(name, "Memory") && ENDSWITH_SET(name, "Current") && u == CGROUP_LIMIT_MAX) || ++ (startswith(name, "IO") && ENDSWITH_SET(name, "Bytes", "Operations") && u == UINT64_MAX) || + (endswith(name, "NSec") && u == UINT64_MAX)) + + bus_print_property_value(name, expected_value, flags, "[not set]"); + +- else if ((STR_IN_SET(name, "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryZSwapMax", "MemoryLimit", "MemoryAvailable") && u == CGROUP_LIMIT_MAX) || ++ else if ((ENDSWITH_SET(name, "MemoryLow", "MemoryMin", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryZSwapMax", "MemoryLimit") && ++ u == CGROUP_LIMIT_MAX) || + (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == UINT64_MAX) || + (startswith(name, "Limit") && u == UINT64_MAX) || + (startswith(name, "DefaultLimit") && u == UINT64_MAX)) +-- +2.35.3 + diff --git a/5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch b/5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch new file mode 100644 index 00000000..a3d7e4a5 --- /dev/null +++ b/5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch @@ -0,0 +1,607 @@ +From 9c86b2c20823dce7f8303648f7e8a8d76342d1d0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Koutn=C3=BD?= +Date: Tue, 23 Jan 2024 11:30:17 +0100 +Subject: [PATCH 5006/5011] cgroup: Add EffectiveMemoryMax=, + EffectiveMemoryHigh= and EffectiveTasksMax= properties + +Users become perplexed when they run their workload in a unit with no +explicit limits configured (moreover, listing the limit property would +even show it's infinity) but they experience unexpected resource +limitation. + +The memory and pid limits come as the most visible, therefore add new +unit read-only properties: +- EffectiveMemoryMax=, +- EffectiveMemoryHigh=, +- EffectiveTasksMax=. + +These properties represent the most stringent limit systemd is aware of +for the given unit -- and that is typically(*) the effective value. + +Implement the properties by simply traversing all parents in the +leaf-slice tree and picking the minimum value. Note that effective +limits are thus defined even for units that don't enable explicit +accounting (because of the hierarchy). + +(*) The evasive case is when systemd runs in a cgroupns and cannot +reason about outer setup. Complete solution would need kernel support. + +(cherry picked from commit 4fb0d2dc140c9a2c01c236d2a8dc09a44157e896) + +[mkoutny: adjust context, drop unapplicable XML] +[mkoutny: fixes jsc#PED-5659] +--- + man/org.freedesktop.systemd1.xml | 108 ++++++++++++++++++++++++++++++ + man/systemd.resource-control.xml | 11 ++- + src/core/cgroup.c | 48 +++++++++++++ + src/core/cgroup.h | 13 ++++ + src/core/dbus-unit.c | 25 +++++++ + src/shared/bus-print-properties.c | 6 +- + 6 files changed, 206 insertions(+), 5 deletions(-) + +diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml +index 2e357539fb..02db33626d 100644 +--- a/man/org.freedesktop.systemd1.xml ++++ b/man/org.freedesktop.systemd1.xml +@@ -2716,6 +2716,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t MemoryAvailable = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryHigh = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t CPUUsageNSec = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly ay EffectiveCPUs = [...]; +@@ -2724,6 +2728,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t TasksCurrent = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveTasksMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressBytes = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressPackets = ...; +@@ -3335,6 +3341,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + + ++ ++ ++ ++ + + + +@@ -3343,6 +3353,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + + ++ ++ + + + +@@ -3963,6 +3975,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + + ++ ++ ++ ++ + + + +@@ -3971,6 +3987,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + + ++ ++ + + + +@@ -4748,6 +4766,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t MemoryAvailable = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryHigh = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t CPUUsageNSec = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly ay EffectiveCPUs = [...]; +@@ -4756,6 +4778,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t TasksCurrent = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveTasksMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressBytes = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressPackets = ...; +@@ -5377,6 +5401,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + + + ++ ++ ++ ++ + + + +@@ -5385,6 +5413,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + + + ++ ++ + + + +@@ -5983,6 +6013,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + + + ++ ++ ++ ++ + + + +@@ -5991,6 +6025,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + + + ++ ++ + + + +@@ -6643,6 +6679,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t MemoryAvailable = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryHigh = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t CPUUsageNSec = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly ay EffectiveCPUs = [...]; +@@ -6651,6 +6691,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t TasksCurrent = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveTasksMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressBytes = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressPackets = ...; +@@ -7200,6 +7242,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { + + + ++ ++ ++ ++ + + + +@@ -7208,6 +7254,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { + + + ++ ++ + + + +@@ -7724,6 +7772,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { + + + ++ ++ ++ ++ + + + +@@ -7732,6 +7784,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { + + + ++ ++ + + + +@@ -8511,6 +8565,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t MemoryAvailable = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryHigh = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t CPUUsageNSec = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly ay EffectiveCPUs = [...]; +@@ -8519,6 +8577,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t TasksCurrent = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveTasksMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressBytes = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressPackets = ...; +@@ -9054,6 +9114,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + + + ++ ++ ++ ++ + + + +@@ -9062,6 +9126,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + + + ++ ++ + + + +@@ -9564,6 +9630,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + + + ++ ++ ++ ++ + + + +@@ -9572,6 +9642,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + + + ++ ++ + + + +@@ -10210,6 +10282,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t MemoryAvailable = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryHigh = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t CPUUsageNSec = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly ay EffectiveCPUs = [...]; +@@ -10218,6 +10294,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t TasksCurrent = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveTasksMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressBytes = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressPackets = ...; +@@ -10381,6 +10459,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + + + ++ ++ ++ ++ + + + +@@ -10389,6 +10471,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + + + ++ ++ + + + +@@ -10557,6 +10641,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + + + ++ ++ ++ ++ + + + +@@ -10565,6 +10653,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + + + ++ ++ + + + +@@ -10759,6 +10849,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t MemoryAvailable = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveMemoryHigh = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t CPUUsageNSec = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly ay EffectiveCPUs = [...]; +@@ -10767,6 +10861,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t TasksCurrent = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") ++ readonly t EffectiveTasksMax = ...; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressBytes = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t IPIngressPackets = ...; +@@ -10950,6 +11046,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + + + ++ ++ ++ ++ + + + +@@ -10958,6 +11058,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + + + ++ ++ + + + +@@ -11156,6 +11258,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + + + ++ ++ ++ ++ + + + +@@ -11164,6 +11270,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + + + ++ ++ + + + +diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml +index 3c17efbe16..5b7900af87 100644 +--- a/man/systemd.resource-control.xml ++++ b/man/systemd.resource-control.xml +@@ -392,7 +392,9 @@ CPUWeight=20 DisableControllers=cpu / \ + system. If assigned the + special value infinity, no memory throttling is applied. This controls the + memory.high control group attribute. For details about this control group attribute, see +- Memory Interface Files. ++ Memory Interface Files. ++ The effective configuration is reported as EffectiveMemoryHigh= ++ (see also EffectiveMemoryMax=). + + While StartupMemoryHigh= applies to the startup and shutdown phases of the system, + MemoryHigh= applies to normal runtime of the system, and if the former is not set also to +@@ -418,7 +420,9 @@ CPUWeight=20 DisableControllers=cpu / \ + percentage value may be specified, which is taken relative to the installed physical memory on the system. If + assigned the special value infinity, no memory limit is applied. This controls the + memory.max control group attribute. For details about this control group attribute, see +- Memory Interface Files. ++ Memory Interface Files. ++ The effective configuration is reported as EffectiveMemoryMax= (the value is ++ the most stringent limit of the unit and parent slices). + + While StartupMemoryMax= applies to the startup and shutdown phases of the system, + MemoryMax= applies to normal runtime of the system, and if the former is not set also to +@@ -534,7 +538,8 @@ CPUWeight=20 DisableControllers=cpu / \ + limit is applied. This controls the pids.max control group attribute. For + details about this control group attribute, the + pids controller +- . ++ . ++ The effective configuration is reported as EffectiveTasksMax=. + + The system default for this setting may be controlled with + DefaultTasksMax= in +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 5b7205a92e..0842036559 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -4000,6 +4000,46 @@ int unit_get_ip_accounting( + return r; + } + ++static uint64_t unit_get_effective_limit_one(Unit *u, CGroupLimitType type) { ++ CGroupContext *cc; ++ ++ assert(u); ++ assert(UNIT_HAS_CGROUP_CONTEXT(u)); ++ ++ cc = unit_get_cgroup_context(u); ++ switch (type) { ++ /* Note: on legacy/hybrid hierarchies memory_max stays CGROUP_LIMIT_MAX unless configured ++ * explicitly. Effective value of MemoryLimit= (cgroup v1) is not implemented. */ ++ case CGROUP_LIMIT_MEMORY_MAX: ++ return cc->memory_max; ++ case CGROUP_LIMIT_MEMORY_HIGH: ++ return cc->memory_high; ++ case CGROUP_LIMIT_TASKS_MAX: ++ return cgroup_tasks_max_resolve(&cc->tasks_max); ++ default: ++ assert_not_reached(); ++ } ++} ++ ++int unit_get_effective_limit(Unit *u, CGroupLimitType type, uint64_t *ret) { ++ uint64_t infimum; ++ ++ assert(u); ++ assert(ret); ++ assert(type >= 0); ++ assert(type < _CGROUP_LIMIT_TYPE_MAX); ++ ++ if (!UNIT_HAS_CGROUP_CONTEXT(u)) ++ return -EINVAL; ++ ++ infimum = unit_get_effective_limit_one(u, type); ++ for (Unit *slice = UNIT_GET_SLICE(u); slice; slice = UNIT_GET_SLICE(slice)) ++ infimum = MIN(infimum, unit_get_effective_limit_one(slice, type)); ++ ++ *ret = infimum; ++ return 0; ++} ++ + static int unit_get_io_accounting_raw(Unit *u, uint64_t ret[static _CGROUP_IO_ACCOUNTING_METRIC_MAX]) { + static const char *const field_names[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IO_READ_BYTES] = "rbytes=", +@@ -4418,3 +4458,11 @@ static const char* const cgroup_pressure_watch_table[_CGROUP_PRESSURE_WATCH_MAX] + }; + + DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(cgroup_pressure_watch, CGroupPressureWatch, CGROUP_PRESSURE_WATCH_ON); ++ ++static const char *const cgroup_limit_type_table[_CGROUP_LIMIT_TYPE_MAX] = { ++ [CGROUP_LIMIT_MEMORY_MAX] = "EffectiveMemoryMax", ++ [CGROUP_LIMIT_MEMORY_HIGH] = "EffectiveMemoryHigh", ++ [CGROUP_LIMIT_TASKS_MAX] = "EffectiveTasksMax", ++}; ++ ++DEFINE_STRING_TABLE_LOOKUP(cgroup_limit_type, CGroupLimitType); +diff --git a/src/core/cgroup.h b/src/core/cgroup.h +index 486957b545..a19a2fffa3 100644 +--- a/src/core/cgroup.h ++++ b/src/core/cgroup.h +@@ -245,6 +245,15 @@ typedef enum CGroupIOAccountingMetric { + _CGROUP_IO_ACCOUNTING_METRIC_INVALID = -EINVAL, + } CGroupIOAccountingMetric; + ++/* Used for limits whose value sets have infimum */ ++typedef enum CGroupLimitType { ++ CGROUP_LIMIT_MEMORY_MAX, ++ CGROUP_LIMIT_MEMORY_HIGH, ++ CGROUP_LIMIT_TASKS_MAX, ++ _CGROUP_LIMIT_TYPE_MAX, ++ _CGROUP_LIMIT_INVALID = -EINVAL, ++} CGroupLimitType; ++ + typedef struct Unit Unit; + typedef struct Manager Manager; + +@@ -337,6 +346,7 @@ int unit_get_tasks_current(Unit *u, uint64_t *ret); + int unit_get_cpu_usage(Unit *u, nsec_t *ret); + int unit_get_io_accounting(Unit *u, CGroupIOAccountingMetric metric, bool allow_cache, uint64_t *ret); + int unit_get_ip_accounting(Unit *u, CGroupIPAccountingMetric metric, uint64_t *ret); ++int unit_get_effective_limit(Unit *u, CGroupLimitType type, uint64_t *ret); + + int unit_reset_cpu_accounting(Unit *u); + int unit_reset_ip_accounting(Unit *u); +@@ -378,3 +388,6 @@ FreezerAction freezer_action_from_string(const char *s) _pure_; + + const char* cgroup_pressure_watch_to_string(CGroupPressureWatch a) _const_; + CGroupPressureWatch cgroup_pressure_watch_from_string(const char *s) _pure_; ++ ++const char* cgroup_limit_type_to_string(CGroupLimitType m) _const_; ++CGroupLimitType cgroup_limit_type_from_string(const char *s) _pure_; +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index ed376cec87..b4509a990e 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -1438,6 +1438,28 @@ static int property_get_io_counter( + return sd_bus_message_append(reply, "t", value); + } + ++static int property_get_effective_limit( ++ sd_bus *bus, ++ const char *path, ++ const char *interface, ++ const char *property, ++ sd_bus_message *reply, ++ void *userdata, ++ sd_bus_error *error) { ++ ++ uint64_t value = CGROUP_LIMIT_MAX; ++ Unit *u = ASSERT_PTR(userdata); ++ ssize_t type; ++ ++ assert(bus); ++ assert(reply); ++ assert(property); ++ ++ assert_se((type = cgroup_limit_type_from_string(property)) >= 0); ++ (void) unit_get_effective_limit(u, type, &value); ++ return sd_bus_message_append(reply, "t", value); ++} ++ + int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) { + + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; +@@ -1557,10 +1579,13 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = { + SD_BUS_PROPERTY("ControlGroupId", "t", NULL, offsetof(Unit, cgroup_id), 0), + SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0), + SD_BUS_PROPERTY("MemoryAvailable", "t", property_get_available_memory, 0, 0), ++ SD_BUS_PROPERTY("EffectiveMemoryMax", "t", property_get_effective_limit, 0, 0), ++ SD_BUS_PROPERTY("EffectiveMemoryHigh", "t", property_get_effective_limit, 0, 0), + SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0), + SD_BUS_PROPERTY("EffectiveCPUs", "ay", property_get_cpuset_cpus, 0, 0), + SD_BUS_PROPERTY("EffectiveMemoryNodes", "ay", property_get_cpuset_mems, 0, 0), + SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0), ++ SD_BUS_PROPERTY("EffectiveTasksMax", "t", property_get_effective_limit, 0, 0), + SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0), + SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0), + SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0), +diff --git a/src/shared/bus-print-properties.c b/src/shared/bus-print-properties.c +index f74d8994ad..62bbc598bb 100644 +--- a/src/shared/bus-print-properties.c ++++ b/src/shared/bus-print-properties.c +@@ -164,9 +164,11 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b + + bus_print_property_value(name, expected_value, flags, "[not set]"); + +- else if ((ENDSWITH_SET(name, "MemoryLow", "MemoryMin", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryZSwapMax", "MemoryLimit") && ++ else if ((ENDSWITH_SET(name, "MemoryLow", "MemoryMin", ++ "MemoryHigh", "MemoryMax", ++ "MemorySwapMax", "MemoryZSwapMax", "MemoryLimit") && + u == CGROUP_LIMIT_MAX) || +- (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == UINT64_MAX) || ++ (endswith(name, "TasksMax") && u == UINT64_MAX) || + (startswith(name, "Limit") && u == UINT64_MAX) || + (startswith(name, "DefaultLimit") && u == UINT64_MAX)) + +-- +2.35.3 + diff --git a/5007-test-Convert-rlimit-test-to-subtest-of-generic-limit.patch b/5007-test-Convert-rlimit-test-to-subtest-of-generic-limit.patch new file mode 100644 index 00000000..ece5242a --- /dev/null +++ b/5007-test-Convert-rlimit-test-to-subtest-of-generic-limit.patch @@ -0,0 +1,97 @@ +From 46451a18828473edaf7e9873a084f26f0c827a3d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Koutn=C3=BD?= +Date: Tue, 23 Jan 2024 11:30:18 +0100 +Subject: [PATCH 5007/5011] test: Convert rlimit test to subtest of generic + limit testing + +No functional change intended. Preparation for new tests. + +(cherry picked from commit 834ca54624ae1d61ec4fcf3a63b10271c38c4860) + +[mkoutny: fixes jsc#PED-5659] +--- + test/units/testsuite-05.rlimit.sh | 25 +++++++++++++++++++++++++ + test/units/testsuite-05.service | 2 +- + test/units/testsuite-05.sh | 22 +++------------------- + 3 files changed, 29 insertions(+), 20 deletions(-) + create mode 100755 test/units/testsuite-05.rlimit.sh + +diff --git a/test/units/testsuite-05.rlimit.sh b/test/units/testsuite-05.rlimit.sh +new file mode 100755 +index 0000000000..bbf3adbe65 +--- /dev/null ++++ b/test/units/testsuite-05.rlimit.sh +@@ -0,0 +1,25 @@ ++#!/usr/bin/env bash ++# SPDX-License-Identifier: LGPL-2.1-or-later ++set -eux ++set -o pipefail ++ ++P=/run/systemd/system.conf.d ++mkdir $P ++ ++cat >$P/rlimits.conf <$P/rlimits.conf < +Date: Tue, 23 Jan 2024 11:30:19 +0100 +Subject: [PATCH 5008/5011] test: Add effective cgroup limits testing + +(cherry picked from commit ce35bb95c7b6fe9a48d2b8628bd690279b17fffa) + +[mkoutny: fixes jsc#PED-5659] +--- + test/units/testsuite-05.effective-limit.sh | 68 ++++++++++++++++++++++ + test/units/util.sh | 9 +++ + 2 files changed, 77 insertions(+) + create mode 100755 test/units/testsuite-05.effective-limit.sh + +diff --git a/test/units/testsuite-05.effective-limit.sh b/test/units/testsuite-05.effective-limit.sh +new file mode 100755 +index 0000000000..3ff8e83140 +--- /dev/null ++++ b/test/units/testsuite-05.effective-limit.sh +@@ -0,0 +1,68 @@ ++#!/usr/bin/env bash ++# SPDX-License-Identifier: LGPL-2.1-or-later ++set -eux ++set -o pipefail ++ ++# shellcheck source=test/units/util.sh ++. "$(dirname "$0")"/util.sh ++ ++pre=test05 ++cat >/run/systemd/system/"$pre"alpha.slice </run/systemd/system/"$pre"alpha-beta.slice </run/systemd/system/"$pre"alpha-beta-gamma.slice < '$2'" >&2 ++ exit 1 ++ fi ++)} ++ + assert_in() {( + set +ex + +-- +2.35.3 + diff --git a/5009-cgroup-Restrict-effective-limits-with-global-resourc.patch b/5009-cgroup-Restrict-effective-limits-with-global-resourc.patch new file mode 100644 index 00000000..889ab52b --- /dev/null +++ b/5009-cgroup-Restrict-effective-limits-with-global-resourc.patch @@ -0,0 +1,56 @@ +From edfd70ab2c5490131fcf5a4348e31c19251d3479 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Koutn=C3=BD?= +Date: Tue, 23 Jan 2024 11:30:20 +0100 +Subject: [PATCH 5009/5011] cgroup: Restrict effective limits with global + resource provision + +Global resource (whole system or root cg's (e.g. in a container)) is +also a well-defined limit for memory and tasks, take it into account +when calculating effective limits. + +(cherry picked from commit 93f8e88d23bd383b5134f32c1e2ee315ac3a38c8) + +[mkoutny: fixes jsc#PED-5659] +--- + man/systemd.resource-control.xml | 2 +- + src/core/cgroup.c | 11 +++++++++++ + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml +index 5b7900af87..ded4722e7a 100644 +--- a/man/systemd.resource-control.xml ++++ b/man/systemd.resource-control.xml +@@ -422,7 +422,7 @@ CPUWeight=20 DisableControllers=cpu / \ + memory.max control group attribute. For details about this control group attribute, see + Memory Interface Files. + The effective configuration is reported as EffectiveMemoryMax= (the value is +- the most stringent limit of the unit and parent slices). ++ the most stringent limit of the unit and parent slices and it is capped by physical memory). + + While StartupMemoryMax= applies to the startup and shutdown phases of the system, + MemoryMax= applies to normal runtime of the system, and if the former is not set also to +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index 0842036559..a53d90486c 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -4006,6 +4006,17 @@ static uint64_t unit_get_effective_limit_one(Unit *u, CGroupLimitType type) { + assert(u); + assert(UNIT_HAS_CGROUP_CONTEXT(u)); + ++ if (unit_has_name(u, SPECIAL_ROOT_SLICE)) ++ switch (type) { ++ case CGROUP_LIMIT_MEMORY_MAX: ++ case CGROUP_LIMIT_MEMORY_HIGH: ++ return physical_memory(); ++ case CGROUP_LIMIT_TASKS_MAX: ++ return system_tasks_max(); ++ default: ++ assert_not_reached(); ++ } ++ + cc = unit_get_cgroup_context(u); + switch (type) { + /* Note: on legacy/hybrid hierarchies memory_max stays CGROUP_LIMIT_MAX unless configured +-- +2.35.3 + diff --git a/5010-cgroup-Rename-effective-limits-internal-table.patch b/5010-cgroup-Rename-effective-limits-internal-table.patch new file mode 100644 index 00000000..2342136a --- /dev/null +++ b/5010-cgroup-Rename-effective-limits-internal-table.patch @@ -0,0 +1,64 @@ +From 0c3448f0e341e3e1f23722e4275c4fdd4062d280 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Koutn=C3=BD?= +Date: Tue, 23 Jan 2024 11:30:21 +0100 +Subject: [PATCH 5010/5011] cgroup: Rename effective limits internal table + +Post-merge fixup of commit 4fb0d2dc14 ("cgroup: Add EffectiveMemoryMax=, +EffectiveMemoryHigh= and EffectiveTasksMax= properties"), no functional +change intended. + +(cherry picked from commit 8ad614890bba66b5f6b590d6a3e1b8b04a920126) + +[mkoutny: adjust context] +[mkoutny: fixes jsc#PED-5659] +--- + src/core/cgroup.c | 4 ++-- + src/core/cgroup.h | 4 ++-- + src/core/dbus-unit.c | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index a53d90486c..2d8d61a26d 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -4470,10 +4470,10 @@ static const char* const cgroup_pressure_watch_table[_CGROUP_PRESSURE_WATCH_MAX] + + DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(cgroup_pressure_watch, CGroupPressureWatch, CGROUP_PRESSURE_WATCH_ON); + +-static const char *const cgroup_limit_type_table[_CGROUP_LIMIT_TYPE_MAX] = { ++static const char *const cgroup_effective_limit_type_table[_CGROUP_LIMIT_TYPE_MAX] = { + [CGROUP_LIMIT_MEMORY_MAX] = "EffectiveMemoryMax", + [CGROUP_LIMIT_MEMORY_HIGH] = "EffectiveMemoryHigh", + [CGROUP_LIMIT_TASKS_MAX] = "EffectiveTasksMax", + }; + +-DEFINE_STRING_TABLE_LOOKUP(cgroup_limit_type, CGroupLimitType); ++DEFINE_STRING_TABLE_LOOKUP(cgroup_effective_limit_type, CGroupLimitType); +diff --git a/src/core/cgroup.h b/src/core/cgroup.h +index a19a2fffa3..9ff650abcf 100644 +--- a/src/core/cgroup.h ++++ b/src/core/cgroup.h +@@ -389,5 +389,5 @@ FreezerAction freezer_action_from_string(const char *s) _pure_; + const char* cgroup_pressure_watch_to_string(CGroupPressureWatch a) _const_; + CGroupPressureWatch cgroup_pressure_watch_from_string(const char *s) _pure_; + +-const char* cgroup_limit_type_to_string(CGroupLimitType m) _const_; +-CGroupLimitType cgroup_limit_type_from_string(const char *s) _pure_; ++const char* cgroup_effective_limit_type_to_string(CGroupLimitType m) _const_; ++CGroupLimitType cgroup_effective_limit_type_from_string(const char *s) _pure_; +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index b4509a990e..da22e8f524 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -1455,7 +1455,7 @@ static int property_get_effective_limit( + assert(reply); + assert(property); + +- assert_se((type = cgroup_limit_type_from_string(property)) >= 0); ++ assert_se((type = cgroup_effective_limit_type_from_string(property)) >= 0); + (void) unit_get_effective_limit(u, type, &value); + return sd_bus_message_append(reply, "t", value); + } +-- +2.35.3 + diff --git a/systemd.changes b/systemd.changes index 981737d5..7b532c61 100644 --- a/systemd.changes +++ b/systemd.changes @@ -1,3 +1,20 @@ +------------------------------------------------------------------- +Tue Jan 23 13:44:21 UTC 2024 - Franck Bui + +- Add patches that implement [jsc#PED-5659] + + 5003-cgroup-rename-TasksMax-structure-to-CGroupTasksMax.patch + 5004-bus-print-properties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch + 5005-bus-print-properties-prettify-more-unset-properties.patch + 5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch + 5007-test-Convert-rlimit-test-to-subtest-of-generic-limit.patch + 5008-test-Add-effective-cgroup-limits-testing.patch + 5009-cgroup-Restrict-effective-limits-with-global-resourc.patch + 5010-cgroup-Rename-effective-limits-internal-table.patch + + They are temporarily put in quarantine to get broader testing but should be + eventually moved to the git repo. + ------------------------------------------------------------------- Sat Jan 20 20:42:06 UTC 2024 - Giacomo Comes diff --git a/systemd.spec b/systemd.spec index 3d98cedc..8d1621ef 100644 --- a/systemd.spec +++ b/systemd.spec @@ -221,6 +221,15 @@ Patch5: 0008-sysv-generator-translate-Required-Start-into-a-Wants.patch # will be removed as soon as a proper fix will be merged by upstream. Patch5001: 5001-Revert-udev-update-devlink-with-the-newer-device-nod.patch Patch5002: 5002-Revert-udev-revert-workarounds-for-issues-caused-by-.patch +# jsc#PED-5659 +Patch5003: 5003-cgroup-rename-TasksMax-structure-to-CGroupTasksMax.patch +Patch5004: 5004-bus-print-properties-ignore-CGROUP_LIMIT_MAX-for-Mem.patch +Patch5005: 5005-bus-print-properties-prettify-more-unset-properties.patch +Patch5006: 5006-cgroup-Add-EffectiveMemoryMax-EffectiveMemoryHigh-an.patch +Patch5007: 5007-test-Convert-rlimit-test-to-subtest-of-generic-limit.patch +Patch5008: 5008-test-Add-effective-cgroup-limits-testing.patch +Patch5009: 5009-cgroup-Restrict-effective-limits-with-global-resourc.patch +Patch5010: 5010-cgroup-Rename-effective-limits-internal-table.patch %description Systemd is a system and service manager, compatible with SysV and LSB