naccyde / rpms / systemd

Forked from rpms/systemd a year ago
Clone
4f096d
From 3dbc067d326c600a92822037118961641fc76575 Mon Sep 17 00:00:00 2001
4f096d
From: Pasha Vorobyev <plv@fb.com>
4f096d
Date: Fri, 4 Feb 2022 11:49:46 -0800
4f096d
Subject: [PATCH] MemoryZSwapMax directive to configure new memory.zswap.max
4f096d
 cgroup file
4f096d
4f096d
---
4f096d
 man/org.freedesktop.systemd1.xml              | 36 +++++++++++++++++++
4f096d
 src/basic/cgroup-util.c                       | 36 +++++++++++++++++++
4f096d
 src/basic/cgroup-util.h                       |  2 ++
4f096d
 src/core/cgroup.c                             | 17 +++++++--
4f096d
 src/core/cgroup.h                             |  1 +
4f096d
 src/core/dbus-cgroup.c                        |  8 +++++
4f096d
 src/core/load-fragment-gperf.gperf.in         |  1 +
4f096d
 src/core/load-fragment.c                      |  4 ++-
4f096d
 src/shared/bus-print-properties.c             |  2 +-
4f096d
 src/shared/bus-unit-util.c                    |  1 +
4f096d
 src/systemctl/systemctl-show.c                |  8 +++++
4f096d
 .../fuzz-unit-file/directives-all.service     |  1 +
4f096d
 test/fuzz/fuzz-unit-file/directives.mount     |  1 +
4f096d
 test/fuzz/fuzz-unit-file/directives.scope     |  1 +
4f096d
 test/fuzz/fuzz-unit-file/directives.service   |  1 +
4f096d
 test/fuzz/fuzz-unit-file/directives.slice     |  1 +
4f096d
 test/fuzz/fuzz-unit-file/directives.socket    |  1 +
4f096d
 test/fuzz/fuzz-unit-file/directives.swap      |  1 +
4f096d
 18 files changed, 118 insertions(+), 5 deletions(-)
4f096d
4f096d
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
4f096d
index c14c5b6601..cc37de4fb4 100644
4f096d
--- a/man/org.freedesktop.systemd1.xml
4f096d
+++ b/man/org.freedesktop.systemd1.xml
4f096d
@@ -2493,6 +2493,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemorySwapMax = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
+      readonly t MemoryZSwapMax = ...;
4f096d
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemoryLimit = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly s DevicePolicy = '...';
4f096d
@@ -3030,6 +3032,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
4f096d
 
4f096d
     
4f096d
 
4f096d
+    
4f096d
+
4f096d
     
4f096d
 
4f096d
     
4f096d
@@ -3594,6 +3598,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemorySwapMax"/>
4f096d
 
4f096d
+    <variablelist class="dbus-property" generated="True" extra-ref="MemoryZSwapMax"/>
4f096d
+
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemoryLimit"/>
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="DevicePolicy"/>
4f096d
@@ -4293,6 +4299,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemorySwapMax = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
+      readonly t MemoryZSwapMax = ...;
4f096d
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemoryLimit = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly s DevicePolicy = '...';
4f096d
@@ -4858,6 +4866,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
4f096d
 
4f096d
     
4f096d
 
4f096d
+    
4f096d
+
4f096d
     
4f096d
 
4f096d
     
4f096d
@@ -5420,6 +5430,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemorySwapMax"/>
4f096d
 
4f096d
+    <variablelist class="dbus-property" generated="True" extra-ref="MemoryZSwapMax"/>
4f096d
+
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemoryLimit"/>
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="DevicePolicy"/>
4f096d
@@ -6016,6 +6028,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemorySwapMax = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
+      readonly t MemoryZSwapMax = ...;
4f096d
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemoryLimit = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly s DevicePolicy = '...';
4f096d
@@ -6509,6 +6523,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
4f096d
 
4f096d
     
4f096d
 
4f096d
+    
4f096d
+
4f096d
     
4f096d
 
4f096d
     
4f096d
@@ -6989,6 +7005,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemorySwapMax"/>
4f096d
 
4f096d
+    <variablelist class="dbus-property" generated="True" extra-ref="MemoryZSwapMax"/>
4f096d
+
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemoryLimit"/>
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="DevicePolicy"/>
4f096d
@@ -7706,6 +7724,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemorySwapMax = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
+      readonly t MemoryZSwapMax = ...;
4f096d
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemoryLimit = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly s DevicePolicy = '...';
4f096d
@@ -8185,6 +8205,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
4f096d
 
4f096d
     
4f096d
 
4f096d
+    
4f096d
+
4f096d
     
4f096d
 
4f096d
     
4f096d
@@ -8651,6 +8673,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemorySwapMax"/>
4f096d
 
4f096d
+    <variablelist class="dbus-property" generated="True" extra-ref="MemoryZSwapMax"/>
4f096d
+
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemoryLimit"/>
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="DevicePolicy"/>
4f096d
@@ -9221,6 +9245,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemorySwapMax = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
+      readonly t MemoryZSwapMax = ...;
4f096d
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemoryLimit = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly s DevicePolicy = '...';
4f096d
@@ -9364,6 +9390,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
4f096d
 
4f096d
     
4f096d
 
4f096d
+    
4f096d
+
4f096d
     
4f096d
 
4f096d
     
4f096d
@@ -9514,6 +9542,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemorySwapMax"/>
4f096d
 
4f096d
+    <variablelist class="dbus-property" generated="True" extra-ref="MemoryZSwapMax"/>
4f096d
+
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemoryLimit"/>
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="DevicePolicy"/>
4f096d
@@ -9684,6 +9714,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemorySwapMax = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
+      readonly t MemoryZSwapMax = ...;
4f096d
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly t MemoryLimit = ...;
4f096d
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
4f096d
       readonly s DevicePolicy = '...';
4f096d
@@ -9843,6 +9875,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
4f096d
 
4f096d
     
4f096d
 
4f096d
+    
4f096d
+
4f096d
     
4f096d
 
4f096d
     
4f096d
@@ -10019,6 +10053,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemorySwapMax"/>
4f096d
 
4f096d
+    <variablelist class="dbus-property" generated="True" extra-ref="MemoryZSwapMax"/>
4f096d
+
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="MemoryLimit"/>
4f096d
 
4f096d
     <variablelist class="dbus-property" generated="True" extra-ref="DevicePolicy"/>
4f096d
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
4f096d
index 1ff6160dc8..00b1e71520 100644
4f096d
--- a/src/basic/cgroup-util.c
4f096d
+++ b/src/basic/cgroup-util.c
4f096d
@@ -160,6 +160,42 @@ bool cg_freezer_supported(void) {
4f096d
         return supported;
4f096d
 }
4f096d
 
4f096d
+bool cg_kill_supported(void) {
4f096d
+        static thread_local int supported = -1;
4f096d
+
4f096d
+        if (supported >= 0)
4f096d
+                return supported;
4f096d
+
4f096d
+        if (cg_all_unified() <= 0)
4f096d
+                supported = false;
4f096d
+        else if (access("/sys/fs/cgroup/init.scope/cgroup.kill", F_OK) < 0) {
4f096d
+                if (errno != ENOENT)
4f096d
+                        log_debug_errno(errno, "Failed to check if cgroup.kill is available, assuming not: %m");
4f096d
+                supported = false;
4f096d
+        } else
4f096d
+                supported = true;
4f096d
+
4f096d
+        return supported;
4f096d
+}
4f096d
+
4f096d
+bool cg_zswap_supported(void) {
4f096d
+        static thread_local int supported = -1;
4f096d
+
4f096d
+        if (supported >= 0)
4f096d
+                return supported;
4f096d
+
4f096d
+        if (cg_all_unified() <= 0)
4f096d
+                supported = false;
4f096d
+        else if (access("/sys/fs/cgroup/init.scope/memory.zswap.max", F_OK) < 0) {
4f096d
+                if (errno != ENOENT)
4f096d
+                        log_debug_errno(errno, "Failed to check if cgroup memory.zswap.max is available, assuming not: %m");
4f096d
+                supported = false;
4f096d
+        } else
4f096d
+                supported = true;
4f096d
+
4f096d
+        return supported;
4f096d
+}
4f096d
+
4f096d
 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
4f096d
         _cleanup_free_ char *fs = NULL;
4f096d
         int r;
4f096d
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
4f096d
index ce2f4c6589..8ea94b8870 100644
4f096d
--- a/src/basic/cgroup-util.h
4f096d
+++ b/src/basic/cgroup-util.h
4f096d
@@ -272,6 +272,8 @@ int cg_kernel_controllers(Set **controllers);
4f096d
 
4f096d
 bool cg_ns_supported(void);
4f096d
 bool cg_freezer_supported(void);
4f096d
+bool cg_kill_supported(void);
4f096d
+bool cg_zswap_supported(void);
4f096d
 
4f096d
 int cg_all_unified(void);
4f096d
 int cg_hybrid_unified(void);
4f096d
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
4f096d
index 5c07aa71d1..4a0aa65037 100644
4f096d
--- a/src/core/cgroup.c
4f096d
+++ b/src/core/cgroup.c
4f096d
@@ -123,6 +123,7 @@ void cgroup_context_init(CGroupContext *c) {
4f096d
                 .memory_high = CGROUP_LIMIT_MAX,
4f096d
                 .memory_max = CGROUP_LIMIT_MAX,
4f096d
                 .memory_swap_max = CGROUP_LIMIT_MAX,
4f096d
+                .memory_zswap_max = CGROUP_LIMIT_MAX,
4f096d
 
4f096d
                 .memory_limit = CGROUP_LIMIT_MAX,
4f096d
 
4f096d
@@ -322,6 +323,9 @@ static int unit_compare_memory_limit(Unit *u, const char *property_name, uint64_
4f096d
         } else if (streq(property_name, "MemorySwapMax")) {
4f096d
                 unit_value = c->memory_swap_max;
4f096d
                 file = "memory.swap.max";
4f096d
+        } else if (streq(property_name, "MemoryZSwapMax")) {
4f096d
+                unit_value = c->memory_zswap_max;
4f096d
+                file = "memory.zswap.max";
4f096d
         } else
4f096d
                 return -EINVAL;
4f096d
 
4f096d
@@ -364,9 +368,10 @@ static char *format_cgroup_memory_limit_comparison(char *buf, size_t l, Unit *u,
4f096d
 
4f096d
         /* memory.swap.max is special in that it relies on CONFIG_MEMCG_SWAP (and the default swapaccount=1).
4f096d
          * In the absence of reliably being able to detect whether memcg swap support is available or not,
4f096d
-         * only complain if the error is not ENOENT. */
4f096d
+         * only complain if the error is not ENOENT. This is similarly the case for memory.zswap.max relying on CONFIG_ZSWAP. */
4f096d
         if (r > 0 || IN_SET(r, -ENODATA, -EOWNERDEAD) ||
4f096d
-            (r == -ENOENT && streq(property_name, "MemorySwapMax"))) {
4f096d
+            (r == -ENOENT && (streq(property_name, "MemorySwapMax") ||
4f096d
+                              streq(property_name, "MemoryZSwapMax")))) {
4f096d
                 buf[0] = 0;
4f096d
                 return buf;
4f096d
         }
4f096d
@@ -441,6 +446,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
4f096d
                 "%sMemoryHigh: %" PRIu64 "%s\n"
4f096d
                 "%sMemoryMax: %" PRIu64 "%s\n"
4f096d
                 "%sMemorySwapMax: %" PRIu64 "%s\n"
4f096d
+                "%sMemoryZSwapMax: %" PRIu64 "%s\n"
4f096d
                 "%sMemoryLimit: %" PRIu64 "\n"
4f096d
                 "%sTasksMax: %" PRIu64 "\n"
4f096d
                 "%sDevicePolicy: %s\n"
4f096d
@@ -475,6 +481,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
4f096d
                 prefix, c->memory_high, format_cgroup_memory_limit_comparison(cdc, sizeof(cdc), u, "MemoryHigh"),
4f096d
                 prefix, c->memory_max, format_cgroup_memory_limit_comparison(cdd, sizeof(cdd), u, "MemoryMax"),
4f096d
                 prefix, c->memory_swap_max, format_cgroup_memory_limit_comparison(cde, sizeof(cde), u, "MemorySwapMax"),
4f096d
+                prefix, c->memory_zswap_max, format_cgroup_memory_limit_comparison(cde, sizeof(cde), u, "MemoryZSwapMax"),
4f096d
                 prefix, c->memory_limit,
4f096d
                 prefix, tasks_max_resolve(&c->tasks_max),
4f096d
                 prefix, cgroup_device_policy_to_string(c->device_policy),
4f096d
@@ -1075,7 +1082,7 @@ static bool unit_has_unified_memory_config(Unit *u) {
4f096d
 
4f096d
         return unit_get_ancestor_memory_min(u) > 0 || unit_get_ancestor_memory_low(u) > 0 ||
4f096d
                c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX ||
4f096d
-               c->memory_swap_max != CGROUP_LIMIT_MAX;
4f096d
+               c->memory_swap_max != CGROUP_LIMIT_MAX || c->memory_zswap_max != CGROUP_LIMIT_MAX;
4f096d
 }
4f096d
 
4f096d
 static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) {
4f096d
@@ -1442,10 +1449,12 @@ static void cgroup_context_apply(
4f096d
 
4f096d
                 if (cg_all_unified() > 0) {
4f096d
                         uint64_t max, swap_max = CGROUP_LIMIT_MAX;
4f096d
+                        uint64_t zswap_max = CGROUP_LIMIT_MAX;
4f096d
 
4f096d
                         if (unit_has_unified_memory_config(u)) {
4f096d
                                 max = c->memory_max;
4f096d
                                 swap_max = c->memory_swap_max;
4f096d
+                                zswap_max = c->memory_zswap_max;
4f096d
                         } else {
4f096d
                                 max = c->memory_limit;
4f096d
 
4f096d
@@ -1458,6 +1467,8 @@ static void cgroup_context_apply(
4f096d
                         cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high);
4f096d
                         cgroup_apply_unified_memory_limit(u, "memory.max", max);
4f096d
                         cgroup_apply_unified_memory_limit(u, "memory.swap.max", swap_max);
4f096d
+                        if (cg_zswap_supported())
4f096d
+                                cgroup_apply_unified_memory_limit(u, "memory.zswap.max", zswap_max);
4f096d
 
4f096d
                         (void) set_attribute_and_warn(u, "memory", "memory.oom.group", one_zero(c->memory_oom_group));
4f096d
 
4f096d
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
4f096d
index 3f8cad899d..d40ac0fadc 100644
4f096d
--- a/src/core/cgroup.h
4f096d
+++ b/src/core/cgroup.h
4f096d
@@ -147,6 +147,7 @@ struct CGroupContext {
4f096d
         uint64_t memory_high;
4f096d
         uint64_t memory_max;
4f096d
         uint64_t memory_swap_max;
4f096d
+        uint64_t memory_zswap_max;
4f096d
 
4f096d
         bool default_memory_min_set;
4f096d
         bool default_memory_low_set;
4f096d
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
4f096d
index 84c3caf3a5..e57ceff6f4 100644
4f096d
--- a/src/core/dbus-cgroup.c
4f096d
+++ b/src/core/dbus-cgroup.c
4f096d
@@ -439,6 +439,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
4f096d
         SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
4f096d
         SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
4f096d
         SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
4f096d
+        SD_BUS_PROPERTY("MemoryZSwapMax", "t", NULL, offsetof(CGroupContext, memory_zswap_max), 0),
4f096d
         SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
4f096d
         SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
4f096d
         SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
4f096d
@@ -860,6 +861,7 @@ BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEI
4f096d
 BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
4f096d
 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
4f096d
 BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
4f096d
+BUS_DEFINE_SET_CGROUP_LIMIT(zswap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
4f096d
 REENABLE_WARNING;
4f096d
 
4f096d
 static int bus_cgroup_set_tasks_max(
4f096d
@@ -1019,6 +1021,9 @@ int bus_cgroup_set_property(
4f096d
         if (streq(name, "MemorySwapMax"))
4f096d
                 return bus_cgroup_set_swap(u, name, &c->memory_swap_max, message, flags, error);
4f096d
 
4f096d
+        if (streq(name, "MemoryZSwapMax"))
4f096d
+                return bus_cgroup_set_zswap(u, name, &c->memory_zswap_max, message, flags, error);
4f096d
+
4f096d
         if (streq(name, "MemoryMax"))
4f096d
                 return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
4f096d
 
4f096d
@@ -1059,6 +1064,9 @@ int bus_cgroup_set_property(
4f096d
         if (streq(name, "MemorySwapMaxScale"))
4f096d
                 return bus_cgroup_set_swap_scale(u, name, &c->memory_swap_max, message, flags, error);
4f096d
 
4f096d
+        if (streq(name, "MemoryZSwapMaxScale"))
4f096d
+                return bus_cgroup_set_zswap_scale(u, name, &c->memory_zswap_max, message, flags, error);
4f096d
+
4f096d
         if (streq(name, "MemoryMaxScale"))
4f096d
                 return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
4f096d
 
4f096d
diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in
4f096d
index 42441eab6e..27860fb973 100644
4f096d
--- a/src/core/load-fragment-gperf.gperf.in
4f096d
+++ b/src/core/load-fragment-gperf.gperf.in
4f096d
@@ -196,6 +196,7 @@
4f096d
 {{type}}.MemoryHigh,                       config_parse_memory_limit,                   0,                                  offsetof({{type}}, cgroup_context)
4f096d
 {{type}}.MemoryMax,                        config_parse_memory_limit,                   0,                                  offsetof({{type}}, cgroup_context)
4f096d
 {{type}}.MemorySwapMax,                    config_parse_memory_limit,                   0,                                  offsetof({{type}}, cgroup_context)
4f096d
+{{type}}.MemoryZSwapMax,                   config_parse_memory_limit,                   0,                                  offsetof({{type}}, cgroup_context)
4f096d
 {{type}}.MemoryLimit,                      config_parse_memory_limit,                   0,                                  offsetof({{type}}, cgroup_context)
4f096d
 {{type}}.DeviceAllow,                      config_parse_device_allow,                   0,                                  offsetof({{type}}, cgroup_context)
4f096d
 {{type}}.DevicePolicy,                     config_parse_device_policy,                  0,                                  offsetof({{type}}, cgroup_context.device_policy)
4f096d
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
4f096d
index a068fdf313..b64e64d90f 100644
4f096d
--- a/src/core/load-fragment.c
4f096d
+++ b/src/core/load-fragment.c
4f096d
@@ -3690,7 +3690,7 @@ int config_parse_memory_limit(
4f096d
                         bytes = physical_memory_scale(r, 10000U);
4f096d
 
4f096d
                 if (bytes >= UINT64_MAX ||
4f096d
-                    (bytes <= 0 && !STR_IN_SET(lvalue, "MemorySwapMax", "MemoryLow", "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin"))) {
4f096d
+                    (bytes <= 0 && !STR_IN_SET(lvalue, "MemorySwapMax", "MemoryZSwapMax", "MemoryLow", "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin"))) {
4f096d
                         log_syntax(unit, LOG_WARNING, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue);
4f096d
                         return 0;
4f096d
                 }
4f096d
@@ -3714,6 +3714,8 @@ int config_parse_memory_limit(
4f096d
                 c->memory_max = bytes;
4f096d
         else if (streq(lvalue, "MemorySwapMax"))
4f096d
                 c->memory_swap_max = bytes;
4f096d
+        else if (streq(lvalue, "MemoryZSwapMax"))
4f096d
+                c->memory_zswap_max = bytes;
4f096d
         else if (streq(lvalue, "MemoryLimit"))
4f096d
                 c->memory_limit = bytes;
4f096d
         else
4f096d
diff --git a/src/shared/bus-print-properties.c b/src/shared/bus-print-properties.c
4f096d
index b45921943a..31c2e3cd35 100644
4f096d
--- a/src/shared/bus-print-properties.c
4f096d
+++ b/src/shared/bus-print-properties.c
4f096d
@@ -165,7 +165,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
4f096d
 
4f096d
                         bus_print_property_value(name, expected_value, flags, "[not set]");
4f096d
 
4f096d
-                else if ((STR_IN_SET(name, "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit", "MemoryAvailable") && u == CGROUP_LIMIT_MAX) ||
4f096d
+                else if ((STR_IN_SET(name, "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryZSwapMax", "MemoryLimit", "MemoryAvailable") && u == CGROUP_LIMIT_MAX) ||
4f096d
                          (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == UINT64_MAX) ||
4f096d
                          (startswith(name, "Limit") && u == UINT64_MAX) ||
4f096d
                          (startswith(name, "DefaultLimit") && u == UINT64_MAX))
4f096d
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
4f096d
index d3a5b25d18..f89b6e7428 100644
4f096d
--- a/src/shared/bus-unit-util.c
4f096d
+++ b/src/shared/bus-unit-util.c
4f096d
@@ -516,6 +516,7 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
4f096d
                               "MemoryHigh",
4f096d
                               "MemoryMax",
4f096d
                               "MemorySwapMax",
4f096d
+                              "MemoryZSwapMax",
4f096d
                               "MemoryLimit",
4f096d
                               "TasksMax")) {
4f096d
 
4f096d
diff --git a/src/systemctl/systemctl-show.c b/src/systemctl/systemctl-show.c
4f096d
index 1f524626bf..2bba11936e 100644
4f096d
--- a/src/systemctl/systemctl-show.c
4f096d
+++ b/src/systemctl/systemctl-show.c
4f096d
@@ -247,6 +247,7 @@ typedef struct UnitStatusInfo {
4f096d
         uint64_t memory_high;
4f096d
         uint64_t memory_max;
4f096d
         uint64_t memory_swap_max;
4f096d
+        uint64_t memory_zswap_max;
4f096d
         uint64_t memory_limit;
4f096d
         uint64_t memory_available;
4f096d
         uint64_t cpu_usage_nsec;
4f096d
@@ -684,6 +685,7 @@ static void print_status_info(
4f096d
                 if (i->memory_min > 0 || i->memory_low > 0 ||
4f096d
                     i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX ||
4f096d
                     i->memory_swap_max != CGROUP_LIMIT_MAX ||
4f096d
+                    i->memory_zswap_max != CGROUP_LIMIT_MAX ||
4f096d
                     i->memory_available != CGROUP_LIMIT_MAX ||
4f096d
                     i->memory_limit != CGROUP_LIMIT_MAX) {
4f096d
                         const char *prefix = "";
4f096d
@@ -709,6 +711,10 @@ static void print_status_info(
4f096d
                                 printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max));
4f096d
                                 prefix = " ";
4f096d
                         }
4f096d
+                        if (i->memory_zswap_max != CGROUP_LIMIT_MAX) {
4f096d
+                                printf("%szswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_zswap_max));
4f096d
+                                prefix = " ";
4f096d
+                        }
4f096d
                         if (i->memory_limit != CGROUP_LIMIT_MAX) {
4f096d
                                 printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit));
4f096d
                                 prefix = " ";
4f096d
@@ -1850,6 +1856,7 @@ static int show_one(
4f096d
                 { "MemoryHigh",                     "t",               NULL,           offsetof(UnitStatusInfo, memory_high)                       },
4f096d
                 { "MemoryMax",                      "t",               NULL,           offsetof(UnitStatusInfo, memory_max)                        },
4f096d
                 { "MemorySwapMax",                  "t",               NULL,           offsetof(UnitStatusInfo, memory_swap_max)                   },
4f096d
+                { "MemoryZSwapMax",                 "t",               NULL,           offsetof(UnitStatusInfo, memory_zswap_max)                  },
4f096d
                 { "MemoryLimit",                    "t",               NULL,           offsetof(UnitStatusInfo, memory_limit)                      },
4f096d
                 { "CPUUsageNSec",                   "t",               NULL,           offsetof(UnitStatusInfo, cpu_usage_nsec)                    },
4f096d
                 { "TasksCurrent",                   "t",               NULL,           offsetof(UnitStatusInfo, tasks_current)                     },
4f096d
@@ -1884,6 +1891,7 @@ static int show_one(
4f096d
                 .memory_high = CGROUP_LIMIT_MAX,
4f096d
                 .memory_max = CGROUP_LIMIT_MAX,
4f096d
                 .memory_swap_max = CGROUP_LIMIT_MAX,
4f096d
+                .memory_zswap_max = CGROUP_LIMIT_MAX,
4f096d
                 .memory_limit = UINT64_MAX,
4f096d
                 .memory_available = CGROUP_LIMIT_MAX,
4f096d
                 .cpu_usage_nsec = UINT64_MAX,
4f096d
diff --git a/test/fuzz/fuzz-unit-file/directives-all.service b/test/fuzz/fuzz-unit-file/directives-all.service
4f096d
index 3039d1c0cd..81ffe4fc86 100644
4f096d
--- a/test/fuzz/fuzz-unit-file/directives-all.service
4f096d
+++ b/test/fuzz/fuzz-unit-file/directives-all.service
4f096d
@@ -152,6 +152,7 @@ MemoryLimit=
4f096d
 MemoryLow=
4f096d
 MemoryMax=
4f096d
 MemorySwapMax=
4f096d
+MemoryZSwapMax=
4f096d
 MessageQueueMaxMessages=
4f096d
 MessageQueueMessageSize=
4f096d
 MountAPIVFS=
4f096d
diff --git a/test/fuzz/fuzz-unit-file/directives.mount b/test/fuzz/fuzz-unit-file/directives.mount
4f096d
index 451f291988..ba5d03cc4b 100644
4f096d
--- a/test/fuzz/fuzz-unit-file/directives.mount
4f096d
+++ b/test/fuzz/fuzz-unit-file/directives.mount
4f096d
@@ -103,6 +103,7 @@ MemoryLow=
4f096d
 MemoryMax=
4f096d
 MemoryMin=
4f096d
 MemorySwapMax=
4f096d
+MemoryZSwapMax=
4f096d
 MountAPIVFS=
4f096d
 MountFlags=
4f096d
 MountImages=
4f096d
diff --git a/test/fuzz/fuzz-unit-file/directives.scope b/test/fuzz/fuzz-unit-file/directives.scope
4f096d
index 7e69cf816b..12e3f02b9b 100644
4f096d
--- a/test/fuzz/fuzz-unit-file/directives.scope
4f096d
+++ b/test/fuzz/fuzz-unit-file/directives.scope
4f096d
@@ -46,6 +46,7 @@ MemoryLow=
4f096d
 MemoryMax=
4f096d
 MemoryMin=
4f096d
 MemorySwapMax=
4f096d
+MemoryZSwapMax=
4f096d
 NetClass=
4f096d
 RestartKillSignal=
4f096d
 RuntimeMaxSec=
4f096d
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
4f096d
index de7d2c7daf..b27b100f1a 100644
4f096d
--- a/test/fuzz/fuzz-unit-file/directives.service
4f096d
+++ b/test/fuzz/fuzz-unit-file/directives.service
4f096d
@@ -225,6 +225,7 @@ MemoryLow=
4f096d
 MemoryMax=
4f096d
 MemoryMin=
4f096d
 MemorySwapMax=
4f096d
+MemoryZSwapMax=
4f096d
 MountAPIVFS=
4f096d
 MountFlags=
4f096d
 MountImages=
4f096d
diff --git a/test/fuzz/fuzz-unit-file/directives.slice b/test/fuzz/fuzz-unit-file/directives.slice
4f096d
index 789ac8f0db..0004d4dfd4 100644
4f096d
--- a/test/fuzz/fuzz-unit-file/directives.slice
4f096d
+++ b/test/fuzz/fuzz-unit-file/directives.slice
4f096d
@@ -43,6 +43,7 @@ MemoryLow=
4f096d
 MemoryMax=
4f096d
 MemoryMin=
4f096d
 MemorySwapMax=
4f096d
+MemoryZSwapMax=
4f096d
 NetClass=
4f096d
 Slice=
4f096d
 SocketBindAllow=
4f096d
diff --git a/test/fuzz/fuzz-unit-file/directives.socket b/test/fuzz/fuzz-unit-file/directives.socket
4f096d
index 11f589e22c..02e0349009 100644
4f096d
--- a/test/fuzz/fuzz-unit-file/directives.socket
4f096d
+++ b/test/fuzz/fuzz-unit-file/directives.socket
4f096d
@@ -131,6 +131,7 @@ MemoryLow=
4f096d
 MemoryMax=
4f096d
 MemoryMin=
4f096d
 MemorySwapMax=
4f096d
+MemoryZSwapMax=
4f096d
 MessageQueueMaxMessages=
4f096d
 MessageQueueMessageSize=
4f096d
 MountAPIVFS=
4f096d
diff --git a/test/fuzz/fuzz-unit-file/directives.swap b/test/fuzz/fuzz-unit-file/directives.swap
4f096d
index 582a136531..4536b2a606 100644
4f096d
--- a/test/fuzz/fuzz-unit-file/directives.swap
4f096d
+++ b/test/fuzz/fuzz-unit-file/directives.swap
4f096d
@@ -100,6 +100,7 @@ MemoryLow=
4f096d
 MemoryMax=
4f096d
 MemoryMin=
4f096d
 MemorySwapMax=
4f096d
+MemoryZSwapMax=
4f096d
 MountAPIVFS=
4f096d
 MountFlags=
4f096d
 MountImages=
4f096d
-- 
4f096d
2.34.1
4f096d