From b42defe3b8ed3947d85db654a6cdb1b9999f394d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Jun 2013 21:50:35 +0200 Subject: [PATCH] dbus: make more cgroup attributes runtime settable --- TODO | 2 + src/core/dbus-cgroup.c | 86 +++++++++++++++++++++++++++++++++++---- src/core/unit.c | 19 +++++++++ src/core/unit.h | 1 + src/systemctl/systemctl.c | 29 +++++++++++++ 5 files changed, 129 insertions(+), 8 deletions(-) diff --git a/TODO b/TODO index 709883388..19fc2cd60 100644 --- a/TODO +++ b/TODO @@ -28,6 +28,8 @@ Fedora 19: Features: +* when reloading configuration, apply new cgroup configuration + * implement system-wide DefaultCPUAccounting=1 switch (and similar for blockio, memory, fair scheduling?) * handle jointly mounted controllers correctly diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index f7d1dd12a..ae360eae3 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -152,50 +152,120 @@ int bus_cgroup_set_property( assert(i); if (streq(name, "CPUAccounting")) { - dbus_bool_t b; if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN) return -EINVAL; if (mode != UNIT_CHECK) { + dbus_bool_t b; dbus_message_iter_get_basic(i, &b); c->cpu_accounting = b; - unit_write_drop_in(u, mode, "cpu-accounting", b ? "CPUAccounting=yes" : "CPUAccounting=no"); + unit_write_drop_in_private_section(u, mode, "cpu-accounting", b ? "CPUAccounting=yes" : "CPUAccounting=no"); + } + + return 1; + + } else if (streq(name, "CPUShares")) { + uint64_t u64; + unsigned long ul; + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64) + return -EINVAL; + + dbus_message_iter_get_basic(i, &u64); + ul = (unsigned long) u64; + + if (u64 <= 0 || u64 != (uint64_t) ul) + return -EINVAL; + + if (mode != UNIT_CHECK) { + char buf[sizeof("CPUShares=") + DECIMAL_STR_MAX(ul)]; + c->cpu_shares = ul; + + sprintf(buf, "CPUShares=%lu", ul); + unit_write_drop_in_private_section(u, mode, "cpu-shares", buf); } return 1; } else if (streq(name, "BlockIOAccounting")) { - dbus_bool_t b; if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN) return -EINVAL; if (mode != UNIT_CHECK) { + dbus_bool_t b; dbus_message_iter_get_basic(i, &b); c->blockio_accounting = b; - unit_write_drop_in(u, mode, "block-io-accounting", b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no"); + unit_write_drop_in_private_section(u, mode, "block-io-accounting", b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no"); } return 1; + + } else if (streq(name, "BlockIOWeight")) { + uint64_t u64; + unsigned long ul; + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64) + return -EINVAL; + + dbus_message_iter_get_basic(i, &u64); + ul = (unsigned long) u64; + + if (u64 < 10 || u64 > 1000) + return -EINVAL; + + if (mode != UNIT_CHECK) { + char buf[sizeof("BlockIOWeight=") + DECIMAL_STR_MAX(ul)]; + c->cpu_shares = ul; + + sprintf(buf, "BlockIOWeight=%lu", ul); + unit_write_drop_in_private_section(u, mode, "blockio-weight", buf); + } + + return 1; + } else if (streq(name, "MemoryAccounting")) { - dbus_bool_t b; if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN) return -EINVAL; if (mode != UNIT_CHECK) { + dbus_bool_t b; dbus_message_iter_get_basic(i, &b); - c->blockio_accounting = b; - unit_write_drop_in(u, mode, "memory-accounting", b ? "MemoryAccounting=yes" : "MemoryAccounting=no"); + c->memory_accounting = b; + unit_write_drop_in_private_section(u, mode, "memory-accounting", b ? "MemoryAccounting=yes" : "MemoryAccounting=no"); } return 1; - } + } else if (streq(name, "MemoryLimit") || streq(name, "MemorySoftLimit")) { + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64) + return -EINVAL; + + if (mode != UNIT_CHECK) { + uint64_t limit; + char buf[sizeof("MemorySoftLimit=") + DECIMAL_STR_MAX(limit)]; + + dbus_message_iter_get_basic(i, &limit); + + if (streq(name, "MemoryLimit")) { + c->memory_limit = limit; + sprintf(buf, "MemoryLimit=%" PRIu64, limit); + unit_write_drop_in_private_section(u, mode, "memory-limit", buf); + } else { + c->memory_soft_limit = limit; + sprintf(buf, "MemorySoftLimit=%" PRIu64, limit); + unit_write_drop_in_private_section(u, mode, "memory-soft-limit", buf); + } + } + + return 1; + } return 0; } diff --git a/src/core/unit.c b/src/core/unit.c index be554dac2..211704e23 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2691,6 +2691,8 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co int r; assert(u); + assert(name); + assert(data); if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME))) return 0; @@ -2703,6 +2705,23 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co return write_string_file_atomic_label(q, data); } +int unit_write_drop_in_private_section(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { + _cleanup_free_ char *ndata = NULL; + + assert(u); + assert(name); + assert(data); + + if (!UNIT_VTABLE(u)->private_section) + return -EINVAL; + + ndata = strjoin("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL); + if (!ndata) + return -ENOMEM; + + return unit_write_drop_in(u, mode, name, ndata); +} + int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) { _cleanup_free_ char *p = NULL, *q = NULL; int r; diff --git a/src/core/unit.h b/src/core/unit.h index c344719b1..be6abaff9 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -590,6 +590,7 @@ ExecContext *unit_get_exec_context(Unit *u) _pure_; CGroupContext *unit_get_cgroup_context(Unit *u) _pure_; int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data); +int unit_write_drop_in_private_section(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data); int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name); int unit_kill_context(Unit *u, KillContext *c, bool sigkill, pid_t main_pid, pid_t control_pid, bool main_pid_alien); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 1f81bda7e..5048b529e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3632,6 +3632,35 @@ static int append_assignment(DBusMessageIter *iter, const char *assignment) { if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) || !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b)) return log_oom(); + + } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) { + off_t bytes; + uint64_t u; + + r = parse_bytes(eq, &bytes); + if (r < 0) { + log_error("Failed to parse bytes specification %s", assignment); + return -EINVAL; + } + + u = bytes; + if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) || + !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u)) + return log_oom(); + + } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) { + uint64_t u; + + r = safe_atou64(eq, &u); + if (r < 0) { + log_error("Failed to parse %s value %s.", field, eq); + return -EINVAL; + } + + if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) || + !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u)) + return log_oom(); + } else { log_error("Unknown assignment %s.", assignment); return -EINVAL; -- 2.30.2