summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--src/core/dbus-cgroup.c86
-rw-r--r--src/core/unit.c19
-rw-r--r--src/core/unit.h1
-rw-r--r--src/systemctl/systemctl.c29
5 files changed, 129 insertions, 8 deletions
diff --git a/TODO b/TODO
index 7098833881..19fc2cd604 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 f7d1dd12ad..ae360eae33 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 be554dac20..211704e230 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 c344719b16..be6abaff98 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 1f81bda7e3..5048b529e1 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;