[systemd-commits] 2 commits - TODO src/core src/shared src/systemctl
Lennart Poettering
lennart at kemper.freedesktop.org
Thu Jan 17 16:48:53 PST 2013
TODO | 11 ++++-
src/core/cgroup-attr.c | 10 +----
src/core/dbus-manager.c | 53 +++++++++++++++++++++++----
src/core/dbus-unit.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++
src/core/dbus-unit.h | 19 ++++++---
src/shared/util.c | 3 +
src/systemctl/systemctl.c | 65 ++++++++++++++++++++++++++++++++-
7 files changed, 222 insertions(+), 28 deletions(-)
New commits:
commit 7e2c2bcf1285d124c9c656ff46cafa4db0a987c9
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Jan 18 01:48:46 2013 +0100
update TODO
diff --git a/TODO b/TODO
index 4c59e74..a74ffc3 100644
--- a/TODO
+++ b/TODO
@@ -19,6 +19,7 @@ Fedora 19:
* create /var/log/journal/
Features:
+
* re-enable "make check" for gtk-doc (broken for unknown reason)
* logind: make PrepareForSuspend(false) an official api for notification of resumes
@@ -32,9 +33,13 @@ Features:
* add "loginctl unlock-sessions" as counterpart for "loginctl lock-sessions"
-* extend cgroup attr dbus calls to optionally make changes persistent, and retrieve current kernel values
-
-* support high-level cgroup setting syntax in systemctl. Example: "systemctl set-cgroup-attr MemoryLimit 5K"
+* cgroup attrs:
+ - make persistent
+ - don't filter out duplicate settings
+ - support high-level cgroup setting syntax in systemctl. Example: "systemctl set-cgroup-attr MemoryLimit 5K"
+ - support writte string mapping even for non-high-level settings
+ - add man page for systemctl commands
+ - make sure we work fine with multi-line strings
* print a nicer explanation if people use variable/specifier expansion in ExecStart= for the first word
commit d2a30975827b3447ca0fd5a2c06ec1ff15ce7f0f
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Jan 18 01:44:41 2013 +0100
systemctl: add new "get-cgroup-attr" to query current cgroup attribute value
Also adds a pair of bus calls for this to the daemon.
diff --git a/src/core/cgroup-attr.c b/src/core/cgroup-attr.c
index cedf37d..aed4e99 100644
--- a/src/core/cgroup-attr.c
+++ b/src/core/cgroup-attr.c
@@ -25,8 +25,7 @@
int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b) {
int r;
- char *path = NULL;
- char *v = NULL;
+ _cleanup_free_ char *path = NULL, *v = NULL;
assert(a);
@@ -41,18 +40,13 @@ int cgroup_attribute_apply(CGroupAttribute *a, CGroupBonding *b) {
}
r = cg_get_path(a->controller, b->path, a->name, &path);
- if (r < 0) {
- free(v);
+ if (r < 0)
return r;
- }
r = write_one_line_file(path, v ? v : a->value);
if (r < 0)
log_warning("Failed to write '%s' to %s: %s", v ? v : a->value, path, strerror(-r));
- free(path);
- free(v);
-
return r;
}
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 1d785a2..b782957 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -102,15 +102,10 @@
" <method name=\"ResetFailedUnit\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" </method>\n" \
- " <method name=\"SetUnitControlGroups\">\n" \
- " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"UnsetUnitControlGroups\">\n" \
+ " <method name=\"GetUnitControlGroupAttributes\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
+ " <arg name=\"attributes\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"SetUnitControlGroupAttributes\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
@@ -122,6 +117,16 @@
" <arg name=\"attributes\" type=\"a(ss)\" direction=\"in\"/>\n" \
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" </method>\n" \
+ " <method name=\"SetUnitControlGroups\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"UnsetUnitControlGroups\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
+ " </method>\n" \
" <method name=\"GetJob\">\n" \
" <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
@@ -979,6 +984,38 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (!reply)
goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttributes")) {
+ const char *name;
+ Unit *u;
+ DBusMessageIter iter;
+ _cleanup_strv_free_ char **list = NULL;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ u = manager_get_unit(m, name);
+ if (!u) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+ }
+
+ SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
+ 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 (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
DBusMessageIter iter, sub;
Iterator i;
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index c7bf043..d2f8ebf 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;
@@ -965,6 +986,74 @@ int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter) {
return 0;
}
+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;
+
+ r = bus_parse_strv_iter(iter, &l);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(name, l) {
+ _cleanup_free_ char *controller = NULL;
+ const char *dot;
+ CGroupAttribute *a;
+ CGroupBonding *b;
+
+ dot = strchr(*name, '.');
+ if (dot) {
+ controller = strndup(*name, dot - *name);
+ if (!controller)
+ return -ENOMEM;
+ }
+
+ /* 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;
+
+ 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) {
DBusMessageIter sub, sub2;
int r;
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index c7d5863..c8903f8 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -127,13 +127,9 @@
" <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"ControlGroups\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"ControlGroupAttributes\" type=\"a(sss)\" access=\"read\"/>\n" \
- " <method name=\"SetControlGroups\">\n" \
- " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"UnsetControlGroups\">\n" \
- " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
- " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
+ " <method name=\"GetControlGroupAttributes\">\n" \
+ " <arg name=\"attributes\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"SetControlGroupAttributes\">\n" \
" <arg name=\"attributes\" type=\"a(ss)\" direction=\"in\"/>\n" \
@@ -142,6 +138,14 @@
" <method name=\"UnsetControlGroupAttributes\">\n" \
" <arg name=\"attributes\" type=\"as\" direction=\"in\"/>\n" \
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetControlGroups\">\n" \
+ " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"UnsetControlGroups\">\n" \
+ " <arg name=\"groups\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" </method>\n"
#define BUS_UNIT_INTERFACES_LIST \
@@ -164,6 +168,7 @@ DBusHandlerResult bus_unit_queue_job(
int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter);
int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter);
+int bus_unit_cgroup_attribute_get(Unit *u, DBusMessageIter *iter, char ***_result);
int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter);
int bus_unit_cgroup_attribute_unset(Unit *u, DBusMessageIter *iter);
diff --git a/src/shared/util.c b/src/shared/util.c
index d5de59f..f75a81c 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -641,6 +641,9 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
_cleanup_free_ char *buf = NULL;
struct stat st;
+ assert(fn);
+ assert(contents);
+
f = fopen(fn, "re");
if (!f)
return -errno;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index cac7067..f3d661d 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2273,6 +2273,64 @@ static int set_cgroup_attr(DBusConnection *bus, char **args) {
return 0;
}
+static int get_cgroup_attr(DBusConnection *bus, char **args) {
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+ DBusError error;
+ DBusMessageIter iter;
+ int r;
+ _cleanup_free_ char *n = NULL;
+ _cleanup_strv_free_ char **list = NULL;
+ char **a;
+
+ assert(bus);
+ assert(args);
+
+ dbus_error_init(&error);
+
+ n = unit_name_mangle(args[1]);
+ if (!n)
+ return log_oom();
+
+ m = dbus_message_new_method_call(
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnitControlGroupAttributes");
+ if (!m)
+ return log_oom();
+
+ dbus_message_iter_init_append(m, &iter);
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
+ return log_oom();
+
+ r = bus_append_strv_iter(&iter, args + 2);
+ if (r < 0)
+ return log_oom();
+
+ reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+ if (!reply) {
+ log_error("Failed to issue method call: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ return -EIO;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+ r = bus_parse_strv_iter(&iter, &list);
+ if (r < 0) {
+ log_error("Failed to parse value list.");
+ return r;
+ }
+
+ STRV_FOREACH(a, list) {
+ if (endswith(*a, "\n"))
+ fputs(*a, stdout);
+ else
+ puts(*a);
+ }
+
+ return 0;
+}
+
typedef struct ExecStatusInfo {
char *name;
@@ -4276,12 +4334,14 @@ static int systemctl_help(void) {
" help [NAME...|PID...] Show manual for one or more units\n"
" reset-failed [NAME...] Reset failed state for all, one, or more\n"
" units\n"
- " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
- " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
+ " get-cgroup-attr [NAME] [ATTR] ...\n"
+ " Get control group attrubute\n"
" set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
" Set control group attribute\n"
" unset-cgroup-attr [NAME] [ATTR...]\n"
" Unset control group attribute\n"
+ " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
+ " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
" load [NAME...] Load one or more units\n"
" list-dependencies [NAME] Recursively show units which are required\n"
" or wanted by this unit\n\n"
@@ -5261,6 +5321,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
{ "isolate", EQUAL, 2, start_unit },
{ "set-cgroup", MORE, 2, set_cgroup },
{ "unset-cgroup", MORE, 2, set_cgroup },
+ { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
{ "set-cgroup-attr", MORE, 2, set_cgroup_attr },
{ "unset-cgroup-attr", MORE, 2, set_cgroup },
{ "kill", MORE, 2, kill_unit },
More information about the systemd-commits
mailing list