core: add MemoryMin

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.
This commit is contained in:
Tejun Heo 2018-06-08 17:33:14 -07:00 committed by Zbigniew Jędrzejewski-Szmek
parent 11c9846e31
commit 4842263577
9 changed files with 48 additions and 5 deletions

View file

@ -216,6 +216,7 @@ All cgroup/resource control settings are available for transient units
✓ StartupCPUShares=
✓ CPUQuota=
✓ MemoryAccounting=
✓ MemoryMin=
✓ MemoryLow=
✓ MemoryHigh=
✓ MemoryMax=

View file

@ -216,6 +216,27 @@
</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>

View 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);

View 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;

View 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);

View 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)

View 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;

View 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);

View 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) },