X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fdbus-unit.c;h=d1de46afd4e2069e358fe79853932ed58684d37a;hb=8b55b8c4e7fce5e05dcfd783a37fb843d1bf1868;hp=c7bf043764e898d96e25702ae7ea1dcf7124a8d6;hpb=246aa6dd9dcea84bb945d16ec86e69f869dbb9b4;p=elogind.git diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index c7bf04376..d1de46afd 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -502,6 +502,27 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn reply = dbus_message_new_method_return(message); if (!reply) goto oom; + } else if (streq_ptr(dbus_message_get_member(message), "GetControlGroupAttributes")) { + DBusMessageIter iter; + _cleanup_strv_free_ char **list = NULL; + + SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status"); + + if (!dbus_message_iter_init(message, &iter)) + goto oom; + + r = bus_unit_cgroup_attribute_get(u, &iter, &list); + if (r < 0) + return bus_send_error_reply(connection, message, NULL, r); + + reply = dbus_message_new_method_return(message); + if (!reply) + goto oom; + + dbus_message_iter_init_append(reply, &iter); + if (bus_append_strv_iter(&iter, list) < 0) + goto oom; + } else if (streq_ptr(dbus_message_get_member(message), "SetControlGroupAttributes")) { DBusMessageIter iter; @@ -875,10 +896,32 @@ oom: return DBUS_HANDLER_RESULT_NEED_MEMORY; } +static int next_and_parse_mode(DBusMessageIter *iter, bool *runtime) { + const char *mode; + + assert(iter); + assert(runtime); + + dbus_message_iter_next(iter); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) + return -EINVAL; + + dbus_message_iter_get_basic(iter, &mode); + if (streq(mode, "runtime")) + *runtime = true; + else if (streq(mode, "persistent")) + *runtime = false; + else + return -EINVAL; + + return 0; +} + int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter) { int r; _cleanup_strv_free_ char **a = NULL; char **name; + bool runtime; assert(u); assert(iter); @@ -890,8 +933,12 @@ int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter) { if (r < 0) return r; + r = next_and_parse_mode(iter, &runtime); + if (r < 0) + return r; + STRV_FOREACH(name, a) { - _cleanup_free_ char *controller = NULL, *old_path = NULL, *new_path = NULL; + _cleanup_free_ char *controller = NULL, *old_path = NULL, *new_path = NULL, *contents = NULL; CGroupBonding *b; r = cg_split_spec(*name, &controller, &new_path); @@ -917,6 +964,15 @@ int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter) { if (old_path) cg_trim(controller, old_path, true); } + + contents = strjoin("[", UNIT_VTABLE(u)->exec_section, "]\n" + "ControlGroup=", *name, "\n", NULL); + if (!contents) + return -ENOMEM; + + r = unit_write_drop_in(u, runtime, *name, contents); + if (r < 0) + return r; } return 0; @@ -926,6 +982,7 @@ int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter) { _cleanup_strv_free_ char **a = NULL; char **name; int r; + bool runtime; assert(u); assert(iter); @@ -937,6 +994,10 @@ int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter) { if (r < 0) return r; + r = next_and_parse_mode(iter, &runtime); + if (r < 0) + return r; + STRV_FOREACH(name, a) { _cleanup_free_ char *controller = NULL, *path = NULL, *target = NULL; CGroupBonding *b; @@ -945,6 +1006,11 @@ int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter) { if (r < 0) return r; + if (!controller || streq(controller, SYSTEMD_CGROUP_CONTROLLER)) + return -EINVAL; + + unit_remove_drop_in(u, runtime, *name); + b = cgroup_bonding_find_list(u->cgroup_bondings, controller); if (!b) continue; @@ -965,37 +1031,95 @@ int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter) { return 0; } -int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter) { - DBusMessageIter sub, sub2; +int bus_unit_cgroup_attribute_get(Unit *u, DBusMessageIter *iter, char ***_result) { + _cleanup_strv_free_ char **l = NULL, **result = NULL; + char **name; int r; assert(u); assert(iter); + assert(_result); if (!unit_get_exec_context(u)) return -EINVAL; - if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRUCT) - return -EINVAL; - - dbus_message_iter_recurse(iter, &sub); + r = bus_parse_strv_iter(iter, &l); + if (r < 0) + return r; - while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) { - const char *name, *value; + STRV_FOREACH(name, l) { + _cleanup_free_ char *controller = NULL; CGroupAttribute *a; + CGroupBonding *b; - assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT); + r = cg_controller_from_attr(*name, &controller); + if (r < 0) + return r; - dbus_message_iter_recurse(&sub, &sub2); + /* First attempt, read the value from the kernel */ + b = cgroup_bonding_find_list(u->cgroup_bondings, controller); + if (b) { + _cleanup_free_ char *p = NULL, *v = NULL; - if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 || - bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) < 0) - return -EINVAL; + r = cg_get_path(b->controller, b->path, *name, &p); + if (r < 0) + return r; + + r = read_full_file(p, &v, NULL); + if (r >= 0) { + r = strv_extend(&result, v); + if (r < 0) + return r; + + continue; + } else if (r != -ENOENT) + return r; + } + + /* If that didn't work, read our cached value */ + a = cgroup_attribute_find_list(u->cgroup_attributes, NULL, *name); + if (a) { + r = strv_extend(&result, a->value); + if (r < 0) + return r; + + continue; + } + + return -ENOENT; + } + + *_result = result; + result = NULL; + + return 0; +} + +int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter) { + _cleanup_strv_free_ char **l = NULL; + int r; + bool runtime = false; + char **name, **value; + + assert(u); + assert(iter); + + if (!unit_get_exec_context(u)) + return -EINVAL; + + r = bus_parse_strv_pairs_iter(iter, &l); + if (r < 0) + return r; + + r = next_and_parse_mode(iter, &runtime); + if (r < 0) + return r; - dbus_message_iter_next(&sub); + STRV_FOREACH_PAIR(name, value, l) { + _cleanup_free_ char *contents = NULL; + CGroupAttribute *a; - r = unit_add_cgroup_attribute(u, NULL, name, value, NULL, &a); + r = unit_add_cgroup_attribute(u, NULL, *name, *value, NULL, &a); if (r < 0) return r; @@ -1018,6 +1142,15 @@ int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter) { /* Make it count */ cgroup_attribute_apply(a, u->cgroup_bondings); } + + contents = strjoin("[", UNIT_VTABLE(u)->exec_section, "]\n" + "ControlGroupAttribute=", *name, " ", *value, "\n", NULL); + if (!contents) + return -ENOMEM; + + r = unit_write_drop_in(u, runtime, *name, contents); + if (r < 0) + return r; } return 0; @@ -1026,6 +1159,7 @@ int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter) { int bus_unit_cgroup_attribute_unset(Unit *u, DBusMessageIter *iter) { _cleanup_strv_free_ char **l = NULL; char **name; + bool runtime; int r; assert(u); @@ -1038,12 +1172,18 @@ int bus_unit_cgroup_attribute_unset(Unit *u, DBusMessageIter *iter) { if (r < 0) return r; + r = next_and_parse_mode(iter, &runtime); + if (r < 0) + return r; + STRV_FOREACH(name, l) { CGroupAttribute *a; a = cgroup_attribute_find_list(u->cgroup_attributes, NULL, *name); if (a) cgroup_attribute_free(a); + + unit_remove_drop_in(u, runtime, *name); } return 0;