chiark / gitweb /
dbus: make more cgroup attributes runtime settable
authorLennart Poettering <lennart@poettering.net>
Thu, 27 Jun 2013 19:50:35 +0000 (21:50 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 27 Jun 2013 19:50:35 +0000 (21:50 +0200)
TODO
src/core/dbus-cgroup.c
src/core/unit.c
src/core/unit.h
src/systemctl/systemctl.c

diff --git a/TODO b/TODO
index 7098833881e64a3d8b0dd2fb65941e08f694bc33..19fc2cd604c523563f523680f74e9f56dc696fe9 100644 (file)
--- 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
index f7d1dd12ad35dfb31a918381a732bf341566ab47..ae360eae3348a0d6be3eba422358860bf0e3de67 100644 (file)
@@ -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;
 }
index be554dac2082840297d88602a5afb14ae94f0e43..211704e230603882f78490ee314df5163a469252 100644 (file)
@@ -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;
index c344719b1603c57201e29dd1614f81958ce6e1fb..be6abaff98e8fcb5ca63ecb948842e832264ea10 100644 (file)
@@ -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);
index 1f81bda7e3fd38516580a4b86e021b9d69860e16..5048b529e14b6dcae8ae91cf73b0f07a5da157df 100644 (file)
@@ -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;