Add a KernelTcpMemoryLimit setting that behaves the same way as KernelMemoryLimit, except that it controls the memory.kmem.tcp.limit_in_bytes cgroup attribute. --- man/systemd.resource-control.xml | 17 +++++++++++++++++ src/core/cgroup.c | 16 ++++++++++++++++ src/core/cgroup.h | 1 + src/core/dbus-cgroup.c | 1 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/load-fragment.c | 34 ++++++++++++++++++++++++++++++++++ src/core/load-fragment.h | 1 + src/systemctl/systemctl.c | 3 ++- 8 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index e80c02f..b6576dc 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -171,6 +171,23 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. </varlistentry> <varlistentry> + <term><varname>KernelTcpMemoryLimit=<replaceable>bytes</replaceable></varname></term> + + <listitem> + <para>Specify the limit on maximum kernel TCP buffer memory usage. + 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. This controls the + <literal>memory.kmem.tcp.limit_in_bytes</literal> control group + attribute. + </para> + + <para>Implies <literal>MemoryAccounting=true</literal>.</para> + </listitem> + </varlistentry> + + <varlistentry> <term><varname>BlockIOAccounting=</varname></term> <listitem> diff --git a/src/core/cgroup.c b/src/core/cgroup.c index d7aa49e..5482c78 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -36,6 +36,7 @@ void cgroup_context_init(CGroupContext *c) { c->memory_limit = (uint64_t) -1; c->memory_and_swap_limit = (uint64_t) -1; c->kernel_memory_limit = (uint64_t) -1; + c->kernel_tcp_memory_limit = (uint64_t) -1; c->memory_soft_limit = (uint64_t) -1; c->blockio_weight = 1000; } @@ -100,6 +101,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { "%sMemorySoftLimit=%" PRIu64 "\n" "%sMemoryAndSwapLimit=%" PRIu64 "\n" "%sKernelMemoryLimit=%" PRIu64 "\n" + "%sKernelTcpMemoryLimit=%" PRIu64 "\n" "%sDevicePolicy=%s\n", prefix, yes_no(c->cpu_accounting), prefix, yes_no(c->blockio_accounting), @@ -110,6 +112,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { prefix, c->memory_soft_limit, prefix, c->memory_and_swap_limit, prefix, c->kernel_memory_limit, + prefix, c->kernel_tcp_memory_limit, prefix, cgroup_device_policy_to_string(c->device_policy)); LIST_FOREACH(device_allow, a, c->device_allow) @@ -297,6 +300,18 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha if (r < 0) log_error("Failed to set memory.kmem.limit_in_bytes on %s: %s", path, strerror(-r)); + if (c->kernel_tcp_memory_limit != (uint64_t) -1) { + sprintf(buf, "%" PRIu64 "\n", c->kernel_tcp_memory_limit); + r = cg_set_attribute("memory", path, "memory.kmem.tcp.limit_in_bytes", buf); + } else { + r = cg_set_attribute("memory", path, "memory.kmem.tcp.limit_in_bytes", "-1"); + if (r == -EACCES) /* CONFIG_MEMCG_KMEM not built into kernel, ignore */ + r = 0; + } + + if (r < 0) + log_error("Failed to set memory.kmem.tcp.limit_in_bytes on %s: %s", path, strerror(-r)); + if (c->memory_soft_limit != (uint64_t) -1) { sprintf(buf, "%" PRIu64 "\n", c->memory_soft_limit); r = cg_set_attribute("memory", path, "memory.soft_limit_in_bytes", buf); @@ -371,6 +386,7 @@ CGroupControllerMask cgroup_context_get_mask(CGroupContext *c) { c->memory_limit != (uint64_t) -1 || c->memory_and_swap_limit != (uint64_t) -1 || c->memory_soft_limit != (uint64_t) -1 || + c->kernel_tcp_memory_limit != (uint64_t) -1 || c->kernel_memory_limit != (uint64_t) -1) mask |= CGROUP_MEMORY; diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 501fb1b..2c9a538 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -79,6 +79,7 @@ struct CGroupContext { uint64_t memory_limit; uint64_t memory_and_swap_limit; uint64_t kernel_memory_limit; + uint64_t kernel_tcp_memory_limit; uint64_t memory_soft_limit; CGroupDevicePolicy device_policy; diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 15f2e21..9fefd85 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -135,6 +135,7 @@ const BusProperty bus_cgroup_context_properties[] = { { "MemoryLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, memory_limit) }, { "MemoryAndSwapLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, memory_and_swap_limit) }, { "KernelMemoryLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, kernel_memory_limit) }, + { "KernelTcpMemoryLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, kernel_tcp_memory_limit) }, { "MemorySoftLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, memory_soft_limit) }, { "DevicePolicy", bus_cgroup_append_device_policy, "s", offsetof(CGroupContext, device_policy) }, { "DeviceAllow", bus_cgroup_append_device_allow, "a(ss)", 0 }, diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 7945922..e401e5d 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -92,6 +92,7 @@ $1.MemoryLimit, config_parse_memory_limit, 0, $1.MemorySoftLimit, config_parse_memory_soft_limit, 0, offsetof($1, cgroup_context) $1.MemoryAndSwapLimit, config_parse_memory_and_swap_limit, 0, offsetof($1, cgroup_context) $1.KernelMemoryLimit, config_parse_kernel_memory_limit, 0, offsetof($1, cgroup_context) +$1.KernelTcpMemoryLimit, config_parse_kernel_tcp_memory_limit, 0, offsetof($1, cgroup_context) $1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context) $1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy) $1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 3852632..03b087f 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2171,6 +2171,39 @@ int config_parse_kernel_memory_limit( return 0; } +int config_parse_kernel_tcp_memory_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + off_t bytes; + int r; + + if (isempty(rvalue)) { + c->kernel_tcp_memory_limit = (uint64_t) -1; + return 0; + } + + assert_cc(sizeof(uint64_t) == sizeof(off_t)); + + r = parse_bytes(rvalue, &bytes); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Kernel TCP memory limit '%s' invalid. Ignoring.", rvalue); + return 0; + } + + c->kernel_tcp_memory_limit = (uint64_t) bytes; + return 0; +} + int config_parse_device_allow( const char *unit, const char *filename, @@ -2814,6 +2847,7 @@ void unit_dump_config_items(FILE *f) { { config_parse_memory_soft_limit, "LIMIT" }, { config_parse_memory_and_swap_limit, "LIMIT" }, { config_parse_kernel_memory_limit, "LIMIT" }, + { config_parse_kernel_tcp_memory_limit, "LIMIT" }, { config_parse_device_allow, "DEVICE" }, { config_parse_device_policy, "POLICY" }, { config_parse_blockio_bandwidth, "BANDWIDTH" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index f90ce1a..f187e2d 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -81,6 +81,7 @@ int config_parse_memory_limit(const char *unit, const char *filename, unsigned l int config_parse_memory_soft_limit(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_memory_and_swap_limit(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_kernel_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_kernel_tcp_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 1bea3bd..a834ed4 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3659,7 +3659,8 @@ static int append_assignment(DBusMessageIter *iter, const char *assignment) { return log_oom(); } else if (streq(field, "MemoryLimit") || streq(field, "MemoryAndSwapLimit") || - streq(field, "MemorySoftLimit") || streq(field, "KernelMemoryLimit")) { + streq(field, "MemorySoftLimit") || streq(field, "KernelMemoryLimit") || + streq(field, "KernelTcpMemoryLimit")) { off_t bytes; uint64_t u; -- 1.8.3.2 _______________________________________________ systemd-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/systemd-devel
