]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add MemoryMin
authorTejun Heo <tj@kernel.org>
Sat, 9 Jun 2018 00:33:14 +0000 (17:33 -0700)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 12 Jul 2018 06:21:43 +0000 (08:21 +0200)
The kernel added support for a new cgroup memory controller knob memory.min in
bf8d5d52ffe8 ("memcg: introduce memory.min") which was merged during v4.18
merge window.

Add MemoryMin to support memory.min.

doc/TRANSIENT-SETTINGS.md
man/systemd.resource-control.xml
src/core/cgroup.c
src/core/cgroup.h
src/core/dbus-cgroup.c
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/shared/bus-unit-util.c
src/systemctl/systemctl.c

index ca9e8387b74a1c8b4ed58cb9df42c3afaecfe6bf..0df36967ac6c6f91a5e1709a80798fcc2f8f6c1b 100644 (file)
@@ -216,6 +216,7 @@ All cgroup/resource control settings are available for transient units
 ✓ StartupCPUShares=
 ✓ CPUQuota=
 ✓ MemoryAccounting=
+✓ MemoryMin=
 ✓ MemoryLow=
 ✓ MemoryHigh=
 ✓ MemoryMax=
index af839a1ee01db1894bfb88ce7c1518f593bae3e1..8ebd162be799602b5a1703cfa0adb8aaef97a5aa 100644 (file)
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>MemoryMin=<replaceable>bytes</replaceable></varname></term>
+
+        <listitem>
+          <para>Specify the memory usage protection of the executed processes in this unit. If the memory usages of
+          this unit and all its ancestors are below their minimum boundaries, this unit's memory won't be reclaimed.</para>
+
+          <para>Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is
+          parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a
+          percentage value may be specified, which is taken relative to the installed physical memory on the
+          system. This controls the <literal>memory.min</literal> control group attribute. For details about this
+          control group attribute, see <ulink
+          url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink>.</para>
+
+          <para>Implies <literal>MemoryAccounting=true</literal>.</para>
+
+          <para>This setting is supported only if the unified control group hierarchy is used and disables
+          <varname>MemoryLimit=</varname>.</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>MemoryLow=<replaceable>bytes</replaceable></varname></term>
 
index d4b9bdb8847d473db8af9eccdfb34a83f2863370..eea30b21ff5999b9c04c3dbd39480fbe3a6cdff0 100644 (file)
@@ -193,6 +193,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 "%sStartupIOWeight=%" PRIu64 "\n"
                 "%sBlockIOWeight=%" PRIu64 "\n"
                 "%sStartupBlockIOWeight=%" PRIu64 "\n"
+                "%sMemoryMin=%" PRIu64 "\n"
                 "%sMemoryLow=%" PRIu64 "\n"
                 "%sMemoryHigh=%" PRIu64 "\n"
                 "%sMemoryMax=%" PRIu64 "\n"
@@ -216,6 +217,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 prefix, c->startup_io_weight,
                 prefix, c->blockio_weight,
                 prefix, c->startup_blockio_weight,
+                prefix, c->memory_min,
                 prefix, c->memory_low,
                 prefix, c->memory_high,
                 prefix, c->memory_max,
@@ -668,7 +670,7 @@ static void cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint6
 }
 
 static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
-        return c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || c->memory_swap_max != CGROUP_LIMIT_MAX;
+        return c->memory_min > 0 || c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || c->memory_swap_max != CGROUP_LIMIT_MAX;
 }
 
 static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) {
@@ -920,6 +922,7 @@ static void cgroup_context_apply(
                                         log_cgroup_compat(u, "Applying MemoryLimit %" PRIu64 " as MemoryMax", max);
                         }
 
+                        cgroup_apply_unified_memory_limit(u, "memory.min", c->memory_min);
                         cgroup_apply_unified_memory_limit(u, "memory.low", c->memory_low);
                         cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high);
                         cgroup_apply_unified_memory_limit(u, "memory.max", max);
index 2d2ff6fc3c79f08ef4c32e6188d0d1c96e1688e1..bda139c30bca8e8e80dbd4a2f2782b5e67944bb1 100644 (file)
@@ -82,6 +82,7 @@ struct CGroupContext {
         LIST_HEAD(CGroupIODeviceWeight, io_device_weights);
         LIST_HEAD(CGroupIODeviceLimit, io_device_limits);
 
+        uint64_t memory_min;
         uint64_t memory_low;
         uint64_t memory_high;
         uint64_t memory_max;
index 540bc77aed91fa13e5f9b7e2b059a5f5e95dd13d..137bd47d87cce43827f8f50223f19fe98864882b 100644 (file)
@@ -298,6 +298,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
         SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
         SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
         SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
+        SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0),
         SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
         SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
         SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
@@ -606,6 +607,9 @@ int bus_cgroup_set_property(
         if (streq(name, "MemoryAccounting"))
                 return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
 
+        if (streq(name, "MemoryMin"))
+                return bus_cgroup_set_memory(u, name, &c->memory_min, message, flags, error);
+
         if (streq(name, "MemoryLow"))
                 return bus_cgroup_set_memory(u, name, &c->memory_low, message, flags, error);
 
@@ -621,6 +625,9 @@ int bus_cgroup_set_property(
         if (streq(name, "MemoryLimit"))
                 return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
 
+        if (streq(name, "MemoryMinScale"))
+                return bus_cgroup_set_memory_scale(u, name, &c->memory_min, message, flags, error);
+
         if (streq(name, "MemoryLowScale"))
                 return bus_cgroup_set_memory_scale(u, name, &c->memory_low, message, flags, error);
 
index 15fb47838c0bcaae329c4a3ae1862d6a78534111..290e8001d8ce4b08d3eb8728ee7fa223ff3e82be 100644 (file)
@@ -162,6 +162,7 @@ $1.CPUShares,                    config_parse_cpu_shares,            0,
 $1.StartupCPUShares,             config_parse_cpu_shares,            0,                             offsetof($1, cgroup_context.startup_cpu_shares)
 $1.CPUQuota,                     config_parse_cpu_quota,             0,                             offsetof($1, cgroup_context)
 $1.MemoryAccounting,             config_parse_bool,                  0,                             offsetof($1, cgroup_context.memory_accounting)
+$1.MemoryMin,                    config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
 $1.MemoryLow,                    config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
 $1.MemoryHigh,                   config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
 $1.MemoryMax,                    config_parse_memory_limit,          0,                             offsetof($1, cgroup_context)
index 94c7d33117bd6935017b10c638d6ae428a470000..e18499384a2589b280d67ea3d2af5bb135846751 100644 (file)
@@ -3047,7 +3047,9 @@ int config_parse_memory_limit(
                 }
         }
 
-        if (streq(lvalue, "MemoryLow"))
+        if (streq(lvalue, "MemoryMin"))
+                c->memory_min = bytes;
+        else if (streq(lvalue, "MemoryLow"))
                 c->memory_low = bytes;
         else if (streq(lvalue, "MemoryHigh"))
                 c->memory_high = bytes;
index 3238b442c053507965c899d04027ceabaf8df0e2..0c713678e2da6639b750f5ef9e5e789165c433e1 100644 (file)
@@ -413,7 +413,7 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
                 return 1;
         }
 
-        if (STR_IN_SET(field, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit", "TasksMax")) {
+        if (STR_IN_SET(field, "MemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit", "TasksMax")) {
 
                 if (isempty(eq) || streq(eq, "infinity")) {
                         r = sd_bus_message_append(m, "(sv)", field, "t", CGROUP_LIMIT_MAX);
index 9c6156237a21ef58f5f68ed28c3db8dd40a92719..8f337b78a23c54cd11f12c3072c9b215d07c7e6f 100644 (file)
@@ -3911,6 +3911,7 @@ typedef struct UnitStatusInfo {
 
         /* CGroup */
         uint64_t memory_current;
+        uint64_t memory_min;
         uint64_t memory_low;
         uint64_t memory_high;
         uint64_t memory_max;
@@ -4290,12 +4291,17 @@ static void print_status_info(
 
                 printf("   Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
 
-                if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX ||
-                    i->memory_max != CGROUP_LIMIT_MAX || i->memory_swap_max != CGROUP_LIMIT_MAX ||
+                if (i->memory_min > 0 || i->memory_low > 0 ||
+                    i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX ||
+                    i->memory_swap_max != CGROUP_LIMIT_MAX ||
                     i->memory_limit != CGROUP_LIMIT_MAX) {
                         const char *prefix = "";
 
                         printf(" (");
+                        if (i->memory_min > 0) {
+                                printf("%smin: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_min));
+                                prefix = " ";
+                        }
                         if (i->memory_low > 0) {
                                 printf("%slow: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_low));
                                 prefix = " ";
@@ -4971,6 +4977,7 @@ static int show_one(
                 { "Where",                          "s",              NULL,           offsetof(UnitStatusInfo, where)                             },
                 { "What",                           "s",              NULL,           offsetof(UnitStatusInfo, what)                              },
                 { "MemoryCurrent",                  "t",              NULL,           offsetof(UnitStatusInfo, memory_current)                    },
+                { "MemoryMin",                      "t",              NULL,           offsetof(UnitStatusInfo, memory_min)                        },
                 { "MemoryLow",                      "t",              NULL,           offsetof(UnitStatusInfo, memory_low)                        },
                 { "MemoryHigh",                     "t",              NULL,           offsetof(UnitStatusInfo, memory_high)                       },
                 { "MemoryMax",                      "t",              NULL,           offsetof(UnitStatusInfo, memory_max)                        },