[systemd-commits] 10 commits - TODO src/bootchart src/core src/shared src/systemctl src/test

Lennart Poettering lennart at kemper.freedesktop.org
Mon Jan 14 12:25:46 PST 2013


 TODO                      |    6 
 src/bootchart/bootchart.c |    4 
 src/core/cgroup-attr.c    |   33 +
 src/core/cgroup-attr.h    |    3 
 src/core/cgroup.c         |   32 +
 src/core/cgroup.h         |    3 
 src/core/dbus-manager.c   |  131 +++++++
 src/core/dbus-mount.c     |    2 
 src/core/dbus-service.c   |    2 
 src/core/dbus-socket.c    |    2 
 src/core/dbus-swap.c      |    2 
 src/core/dbus-unit.c      |  250 ++++++++++++++
 src/core/dbus-unit.h      |   31 +
 src/core/load-dropin.c    |    4 
 src/core/load-fragment.c  |   16 
 src/core/unit.c           |  134 +++++--
 src/core/unit.h           |    4 
 src/shared/cgroup-util.c  |  116 +++---
 src/shared/cgroup-util.h  |    4 
 src/shared/strv.h         |    4 
 src/shared/unit-name.c    |   30 +
 src/shared/unit-name.h    |    1 
 src/systemctl/systemctl.c |  782 ++++++++++++++++++++++------------------------
 src/test/test-cgroup.c    |    2 
 24 files changed, 1071 insertions(+), 527 deletions(-)

New commits:
commit aca26b52200a4666c9f80a942150a90004130010
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 14 02:13:26 2013 +0100

    systemctl: drop compat with really really old systemd versions

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 76c67f2..0bae67e 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1120,7 +1120,6 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
         } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
                 uint32_t id;
                 const char *path, *result, *unit;
-                dbus_bool_t success = true;
 
                 if (dbus_message_get_args(message, &error,
                                           DBUS_TYPE_UINT32, &id,
@@ -1128,10 +1127,8 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
                                           DBUS_TYPE_STRING, &unit,
                                           DBUS_TYPE_STRING, &result,
                                           DBUS_TYPE_INVALID)) {
-                        char *p;
 
-                        p = set_remove(d->set, (char*) path);
-                        free(p);
+                        free(set_remove(d->set, (char*) path));
 
                         if (!isempty(result))
                                 d->result = strdup(result);
@@ -1148,40 +1145,16 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
                                           DBUS_TYPE_OBJECT_PATH, &path,
                                           DBUS_TYPE_STRING, &result,
                                           DBUS_TYPE_INVALID)) {
-                        char *p;
-
                         /* Compatibility with older systemd versions <
                          * 183 during upgrades. This should be dropped
                          * one day. */
-                        p = set_remove(d->set, (char*) path);
-                        free(p);
+                        free(set_remove(d->set, (char*) path));
 
                         if (*result)
                                 d->result = strdup(result);
 
                         goto finish;
                 }
-
-                dbus_error_free(&error);
-                if (dbus_message_get_args(message, &error,
-                                          DBUS_TYPE_UINT32, &id,
-                                          DBUS_TYPE_OBJECT_PATH, &path,
-                                          DBUS_TYPE_BOOLEAN, &success,
-                                          DBUS_TYPE_INVALID)) {
-                        char *p;
-
-                        /* Compatibility with older systemd versions <
-                         * 19 during upgrades. This should be dropped
-                         * one day */
-
-                        p = set_remove(d->set, (char*) path);
-                        free(p);
-
-                        if (!success)
-                                d->result = strdup("failed");
-
-                        goto finish;
-                }
 #endif
 
                 log_error("Failed to parse message: %s", bus_error_message(&error));

commit 7b4da18c1717f811bae67ea3d39290495857c03e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 14 02:13:07 2013 +0100

    update TODO

diff --git a/TODO b/TODO
index e89be55..dce2604 100644
--- a/TODO
+++ b/TODO
@@ -21,11 +21,15 @@ 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"
+
 * add a man page "systemdall" that lists all of systemd's man pages, inspired by zsh's "zshall" page
 
 * print a nicer explanation if people use variable/specifier expansion in ExecStart= for the first word
 
-* kernel cmdline switch to turn of predictable network interface names
+* kernel cmdline switch to turn off predictable network interface names
 
 * mount: turn dependency information from /proc/self/mountinfo into dependency information between systemd units.
 

commit 1dcf60656cc68cf0182703d77e31f24f05b0c8cc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 14 02:11:57 2013 +0100

    systemctl: be smarter when mangling snapshot names
    
    For "systemctl snapshot" it makes no sense to complete an incomplete
    name with ".service" as we previously did, use ".snapshot" instead.
    Also, don't bother with mount units or suchlike, we know that this must
    be a snapshot and hence is the only sane way for completion.

diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c
index 88ca0b8..06bbfac 100644
--- a/src/shared/unit-name.c
+++ b/src/shared/unit-name.c
@@ -506,6 +506,36 @@ char *unit_name_mangle(const char *name) {
         return r;
 }
 
+char *snapshot_name_mangle(const char *name) {
+        char *r, *t;
+        const char *f;
+
+        assert(name);
+
+        /* Similar to unit_name_mangle(), but is called when we know
+         * that this is about snapshot units. */
+
+        r = new(char, strlen(name) * 4 + 1 + sizeof(".snapshot")-1);
+        if (!r)
+                return NULL;
+
+        for (f = name, t = r; *f; f++) {
+                if (*f == '/')
+                        *(t++) = '-';
+                else if (!strchr(VALID_CHARS, *f))
+                        t = do_escape_char(*f, t);
+                else
+                        *(t++) = *f;
+        }
+
+        if (!endswith(name, ".snapshot"))
+                strcpy(t, ".snapshot");
+        else
+                *t = 0;
+
+        return r;
+}
+
 UnitType unit_name_to_type(const char *n) {
         const char *e;
 
diff --git a/src/shared/unit-name.h b/src/shared/unit-name.h
index d7528a3..9150dd0 100644
--- a/src/shared/unit-name.h
+++ b/src/shared/unit-name.h
@@ -94,3 +94,4 @@ char *unit_name_to_path(const char *name);
 char *unit_dbus_path_from_name(const char *name);
 
 char *unit_name_mangle(const char *name);
+char *snapshot_name_mangle(const char *name);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index b22010d..76c67f2 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3173,17 +3173,19 @@ static int snapshot(DBusConnection *bus, char **args) {
         dbus_bool_t cleanup = FALSE;
         DBusMessageIter iter, sub;
         const char
-                *name = "", *path, *id,
+                *path, *id,
                 *interface = "org.freedesktop.systemd1.Unit",
                 *property = "Id";
         _cleanup_free_ char *n = NULL;
 
         dbus_error_init(&error);
 
-        if (strv_length(args) > 1) {
-                name = args[1];
-                n = unit_name_mangle(name);
-        }
+        if (strv_length(args) > 1)
+                n = snapshot_name_mangle(args[1]);
+        else
+                n = strdup("");
+        if (!n)
+                return log_oom();
 
         r = bus_method_call_with_reply (
                         bus,
@@ -3193,18 +3195,18 @@ static int snapshot(DBusConnection *bus, char **args) {
                         "CreateSnapshot",
                         &reply,
                         NULL,
-                        DBUS_TYPE_STRING, n ? (const char**) &n : &name,
+                        DBUS_TYPE_STRING, &n,
                         DBUS_TYPE_BOOLEAN, &cleanup,
                         DBUS_TYPE_INVALID);
         if (r < 0)
-                goto finish;
+                return r;
 
         if (!dbus_message_get_args(reply, &error,
                                    DBUS_TYPE_OBJECT_PATH, &path,
                                    DBUS_TYPE_INVALID)) {
                 log_error("Failed to parse reply: %s", bus_error_message(&error));
-                r = -EIO;
-                goto finish;
+                dbus_error_free(&error);
+                return -EIO;
         }
 
         dbus_message_unref(reply);
@@ -3222,21 +3224,19 @@ static int snapshot(DBusConnection *bus, char **args) {
                         DBUS_TYPE_STRING, &property,
                         DBUS_TYPE_INVALID);
         if (r < 0)
-                goto finish;
+                return r;
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_iter_recurse(&iter, &sub);
 
         if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_iter_get_basic(&sub, &id);
@@ -3244,10 +3244,7 @@ static int snapshot(DBusConnection *bus, char **args) {
         if (!arg_quiet)
                 puts(id);
 
-finish:
-        dbus_error_free(&error);
-
-        return r;
+        return 0;
 }
 
 static int delete_snapshot(DBusConnection *bus, char **args) {
@@ -3259,7 +3256,10 @@ static int delete_snapshot(DBusConnection *bus, char **args) {
                 _cleanup_free_ char *n = NULL;
                 int r;
 
-                n = unit_name_mangle(*name);
+                n = snapshot_name_mangle(*name);
+                if (!n)
+                        return log_oom();
+
                 r = bus_method_call_with_reply(
                                 bus,
                                 "org.freedesktop.systemd1",
@@ -3268,7 +3268,7 @@ static int delete_snapshot(DBusConnection *bus, char **args) {
                                 "RemoveSnapshot",
                                 NULL,
                                 NULL,
-                                DBUS_TYPE_STRING, n ? &n : name,
+                                DBUS_TYPE_STRING, &n,
                                 DBUS_TYPE_INVALID);
                 if (r < 0)
                         return r;
@@ -3302,7 +3302,7 @@ static int daemon_reload(DBusConnection *bus, char **args) {
                                     /* "daemon-reload" */ "Reload";
         }
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -3320,10 +3320,10 @@ static int daemon_reload(DBusConnection *bus, char **args) {
                 /* On reexecution, we expect a disconnect, not
                  * a reply */
                 r = 0;
-        else if (r)
+        else if (r < 0)
                 log_error("Failed to issue method call: %s", bus_error_message(&error));
-        dbus_error_free(&error);
 
+        dbus_error_free(&error);
         return r;
 }
 

commit f84190d8cad66f36eef1d851213711244ca297be
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 14 02:11:22 2013 +0100

    systemctl: numerous modernizations

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 075ee4b..b22010d 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -237,21 +237,18 @@ static void warn_wall(enum action a) {
                 return;
 
         if (arg_wall) {
-                char *p;
+                _cleanup_free_ char *p;
 
                 p = strv_join(arg_wall, " ");
                 if (!p) {
-                        log_error("Failed to join strings.");
+                        log_oom();
                         return;
                 }
 
                 if (*p) {
                         utmp_wall(p, NULL);
-                        free(p);
                         return;
                 }
-
-                free(p);
         }
 
         if (!table[a])
@@ -300,7 +297,8 @@ static int compare_unit_info(const void *a, const void *b) {
         if (d1 && d2) {
                 int r;
 
-                if ((r = strcasecmp(d1, d2)) != 0)
+                r = strcasecmp(d1, d2);
+                if (r != 0)
                         return r;
         }
 
@@ -447,15 +445,15 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
 }
 
 static int list_units(DBusConnection *bus, char **args) {
-        DBusMessage *reply = NULL;
-        int r;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+        _cleanup_free_ struct unit_info *unit_infos = NULL;
         DBusMessageIter iter, sub, sub2;
         unsigned c = 0, n_units = 0;
-        struct unit_info *unit_infos = NULL;
+        int r;
 
         pager_open_if_enabled();
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -464,15 +462,14 @@ static int list_units(DBusConnection *bus, char **args) {
                         &reply,
                         NULL,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
             dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_iter_recurse(&iter, &sub);
@@ -480,28 +477,20 @@ static int list_units(DBusConnection *bus, char **args) {
         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
                 struct unit_info *u;
 
-                if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
-                        log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
-                }
+                assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
 
                 if (c >= n_units) {
                         struct unit_info *w;
 
                         n_units = MAX(2*c, 16);
                         w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
-
-                        if (!w) {
-                                log_error("Failed to allocate unit array.");
-                                r = -ENOMEM;
-                                goto finish;
-                        }
+                        if (!w)
+                                return log_oom();
 
                         unit_infos = w;
                 }
 
-                u = unit_infos+c;
+                u = unit_infos + c;
 
                 dbus_message_iter_recurse(&sub, &sub2);
 
@@ -516,8 +505,7 @@ static int list_units(DBusConnection *bus, char **args) {
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 dbus_message_iter_next(&sub);
@@ -529,13 +517,7 @@ static int list_units(DBusConnection *bus, char **args) {
                 output_units_list(unit_infos, c);
         }
 
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
-        free(unit_infos);
-
-        return r;
+        return 0;
 }
 
 static int compare_unit_file_list(const void *a, const void *b) {
@@ -626,11 +608,11 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
 }
 
 static int list_unit_files(DBusConnection *bus, char **args) {
-        DBusMessage *reply = NULL;
-        int r;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+        _cleanup_free_ UnitFileList *units = NULL;
         DBusMessageIter iter, sub, sub2;
         unsigned c = 0, n_units = 0;
-        UnitFileList *units = NULL;
+        int r;
 
         pager_open_if_enabled();
 
@@ -664,7 +646,7 @@ static int list_unit_files(DBusConnection *bus, char **args) {
 
                 hashmap_free(h);
         } else {
-                r = bus_method_call_with_reply (
+                r = bus_method_call_with_reply(
                                 bus,
                                 "org.freedesktop.systemd1",
                                 "/org/freedesktop/systemd1",
@@ -673,15 +655,14 @@ static int list_unit_files(DBusConnection *bus, char **args) {
                                 &reply,
                                 NULL,
                                 DBUS_TYPE_INVALID);
-                if (r)
-                        goto finish;
+                if (r < 0)
+                        return r;
 
                 if (!dbus_message_iter_init(reply, &iter) ||
                     dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
                     dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT)  {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 dbus_message_iter_recurse(&iter, &sub);
@@ -690,36 +671,27 @@ static int list_unit_files(DBusConnection *bus, char **args) {
                         UnitFileList *u;
                         const char *state;
 
-                        if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
-                                log_error("Failed to parse reply.");
-                                r = -EIO;
-                                goto finish;
-                        }
+                        assert(dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT);
 
                         if (c >= n_units) {
                                 UnitFileList *w;
 
                                 n_units = MAX(2*c, 16);
                                 w = realloc(units, sizeof(struct UnitFileList) * n_units);
-
-                                if (!w) {
-                                        log_error("Failed to allocate unit array.");
-                                        r = -ENOMEM;
-                                        goto finish;
-                                }
+                                if (!w)
+                                        return log_oom();
 
                                 units = w;
                         }
 
-                        u = units+c;
+                        u = units + c;
 
                         dbus_message_iter_recurse(&sub, &sub2);
 
                         if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
                             bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
                                 log_error("Failed to parse reply.");
-                                r = -EIO;
-                                goto finish;
+                                return -EIO;
                         }
 
                         u->state = unit_file_state_from_string(state);
@@ -734,18 +706,11 @@ static int list_unit_files(DBusConnection *bus, char **args) {
                 output_unit_file_list(units, c);
         }
 
-        r = 0;
-
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
-        free(units);
-
-        return r;
+        return 0;
 }
 
 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
+
         static const char * const colors[] = {
                 "Requires",              "[color=\"black\"]",
                 "RequiresOverridable",   "[color=\"black\"]",
@@ -804,14 +769,15 @@ static int dot_one_property(const char *name, const char *prop, DBusMessageIter
 }
 
 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
-        DBusMessage *reply = NULL;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         const char *interface = "org.freedesktop.systemd1.Unit";
         int r;
         DBusMessageIter iter, sub, sub2, sub3;
 
+        assert(bus);
         assert(path);
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         path,
@@ -821,15 +787,14 @@ static int dot_one(DBusConnection *bus, const char *name, const char *path) {
                         NULL,
                         DBUS_TYPE_STRING, &interface,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
             dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_iter_recurse(&iter, &sub);
@@ -837,50 +802,32 @@ static int dot_one(DBusConnection *bus, const char *name, const char *path) {
         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
                 const char *prop;
 
-                if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
-                        log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
-                }
-
+                assert(dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY);
                 dbus_message_iter_recurse(&sub, &sub2);
 
-                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
+                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0 ||
+                    dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
-                }
-
-                if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT)  {
-                        log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 dbus_message_iter_recurse(&sub2, &sub3);
-
-                if (dot_one_property(name, prop, &sub3)) {
-                        log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
-                }
+                r = dot_one_property(name, prop, &sub3);
+                if (r < 0)
+                        return r;
 
                 dbus_message_iter_next(&sub);
         }
 
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
-        return r;
+        return 0;
 }
 
 static int dot(DBusConnection *bus, char **args) {
-        DBusMessage *reply = NULL;
-        int r;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         DBusMessageIter iter, sub, sub2;
+        int r;
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -889,15 +836,14 @@ static int dot(DBusConnection *bus, char **args) {
                         &reply,
                         NULL,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
             dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         printf("digraph systemd {\n");
@@ -908,8 +854,7 @@ static int dot(DBusConnection *bus, char **args) {
 
                 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 dbus_message_iter_recurse(&sub, &sub2);
@@ -922,12 +867,12 @@ static int dot(DBusConnection *bus, char **args) {
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
-                if ((r = dot_one(bus, id, unit_path)) < 0)
-                        goto finish;
+                r = dot_one(bus, id, unit_path);
+                if (r < 0)
+                        return r;
 
                 /* printf("\t\"%s\";\n", id); */
                 dbus_message_iter_next(&sub);
@@ -945,24 +890,18 @@ static int dot(DBusConnection *bus, char **args) {
                 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
                            "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
 
-        r = 0;
-
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
-        return r;
+        return 0;
 }
 
 static int list_jobs(DBusConnection *bus, char **args) {
-        DBusMessage *reply = NULL;
-        int r;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         DBusMessageIter iter, sub, sub2;
         unsigned k = 0;
+        int r;
 
         pager_open_if_enabled();
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -971,15 +910,14 @@ static int list_jobs(DBusConnection *bus, char **args) {
                         &reply,
                         NULL,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
             dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_iter_recurse(&iter, &sub);
@@ -994,8 +932,7 @@ static int list_jobs(DBusConnection *bus, char **args) {
 
                 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 dbus_message_iter_recurse(&sub, &sub2);
@@ -1007,8 +944,7 @@ static int list_jobs(DBusConnection *bus, char **args) {
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 e = arg_full ? NULL : ellipsize(name, 25, 33);
@@ -1023,13 +959,7 @@ static int list_jobs(DBusConnection *bus, char **args) {
         if (on_tty())
                 printf("\n%u jobs listed.\n", k);
 
-        r = 0;
-
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
-        return r;
+        return 0;
 }
 
 static int load_unit(DBusConnection *bus, char **args) {
@@ -1042,7 +972,10 @@ static int load_unit(DBusConnection *bus, char **args) {
                 int r;
 
                 n = unit_name_mangle(*name);
-                r = bus_method_call_with_reply (
+                if (!n)
+                        return log_oom();
+
+                r = bus_method_call_with_reply(
                                 bus,
                                 "org.freedesktop.systemd1",
                                 "/org/freedesktop/systemd1",
@@ -1050,7 +983,7 @@ static int load_unit(DBusConnection *bus, char **args) {
                                 "LoadUnit",
                                 NULL,
                                 NULL,
-                                DBUS_TYPE_STRING, n ? &n : name,
+                                DBUS_TYPE_STRING, &n,
                                 DBUS_TYPE_INVALID);
                 if (r < 0)
                         return r;
@@ -1095,19 +1028,22 @@ static int cancel_job(DBusConnection *bus, char **args) {
 }
 
 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
-        DBusMessage *reply = NULL;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         dbus_bool_t b = FALSE;
         DBusMessageIter iter, sub;
         const char
                 *interface = "org.freedesktop.systemd1.Unit",
                 *property = "NeedDaemonReload",
                 *path;
-        char *n;
+        _cleanup_free_ char *n = NULL;
         int r;
 
         /* We ignore all errors here, since this is used to show a warning only */
 
         n = unit_name_mangle(unit);
+        if (n)
+                return log_oom();
+
         r = bus_method_call_with_reply (
                         bus,
                         "org.freedesktop.systemd1",
@@ -1116,19 +1052,20 @@ static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
                         "GetUnit",
                         &reply,
                         NULL,
-                        DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
+                        DBUS_TYPE_STRING, &n,
                         DBUS_TYPE_INVALID);
-        free(n);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_get_args(reply, NULL,
                                    DBUS_TYPE_OBJECT_PATH, &path,
                                    DBUS_TYPE_INVALID))
-                goto finish;
+                return -EIO;
 
         dbus_message_unref(reply);
-        r = bus_method_call_with_reply (
+        reply = NULL;
+
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         path,
@@ -1139,24 +1076,18 @@ static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
                         DBUS_TYPE_STRING, &interface,
                         DBUS_TYPE_STRING, &property,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
-                goto finish;
+                return -EIO;
 
         dbus_message_iter_recurse(&iter, &sub);
-
         if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
-                goto finish;
+                return -EIO;
 
         dbus_message_iter_get_basic(&sub, &b);
-
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
         return b;
 }
 
@@ -1343,12 +1274,12 @@ static int wait_for_jobs(DBusConnection *bus, Set *s) {
 
 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
         _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+        _cleanup_free_ char *n = NULL;
         DBusMessageIter iter, sub;
         const char
                 *interface = "org.freedesktop.systemd1.Unit",
                 *property = "ActiveState";
         const char *state, *path;
-        _cleanup_free_ char *n = NULL;
         DBusError error;
         int r;
 
@@ -1434,7 +1365,6 @@ static void check_triggering_units(
         DBusMessageIter iter, sub;
         const char *interface = "org.freedesktop.systemd1.Unit",
                    *triggered_by_property = "TriggeredBy";
-
         char _cleanup_free_ *unit_path = NULL, *n = NULL;
         bool print_warning_label = true;
         int r;
@@ -1515,9 +1445,9 @@ static int start_unit_one(
                 Set *s) {
 
         _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+        _cleanup_free_ char *n;
         const char *path;
         int r;
-        _cleanup_free_ char *n, *p = NULL;
 
         assert(method);
         assert(name);
@@ -1562,17 +1492,18 @@ static int start_unit_one(
                             n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
 
         if (s) {
+                char *p;
+
                 p = strdup(path);
                 if (!p)
                         return log_oom();
 
                 r = set_put(s, p);
                 if (r < 0) {
+                        free(p);
                         log_error("Failed to add path to set.");
                         return r;
                 }
-
-                p = NULL;
         }
 
         return 0;
@@ -1769,7 +1700,7 @@ static int reboot_with_logind(DBusConnection *bus, enum action a) {
                 return -EINVAL;
         }
 
-        return bus_method_call_with_reply (
+        return bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.login1",
                         "/org/freedesktop/login1",
@@ -2006,6 +1937,8 @@ static int kill_unit(DBusConnection *bus, char **args) {
                 _cleanup_free_ char *n = NULL;
 
                 n = unit_name_mangle(*name);
+                if (!n)
+                        return log_oom();
 
                 r = bus_method_call_with_reply(
                                 bus,
@@ -2015,7 +1948,7 @@ static int kill_unit(DBusConnection *bus, char **args) {
                                 "KillUnit",
                                 NULL,
                                 NULL,
-                                DBUS_TYPE_STRING, n ? &n : name,
+                                DBUS_TYPE_STRING, &n,
                                 DBUS_TYPE_STRING, &arg_kill_who,
                                 DBUS_TYPE_INT32, &arg_signal,
                                 DBUS_TYPE_INVALID);
@@ -2077,7 +2010,6 @@ static int set_cgroup_attr(DBusConnection *bus, char **args) {
         _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
         DBusError error;
         DBusMessageIter iter, sub, sub2;
-        int r;
         char **x, **y;
         _cleanup_free_ char *n = NULL;
 
@@ -2175,7 +2107,8 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
         if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
                 return -EIO;
 
-        if (!(i->path = strdup(path)))
+        i->path = strdup(path);
+        if (!i->path)
                 return -ENOMEM;
 
         if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
@@ -2190,8 +2123,8 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
                 n++;
         }
 
-
-        if (!(i->argv = new0(char*, n+1)))
+        i->argv = new0(char*, n+1);
+        if (!i->argv)
                 return -ENOMEM;
 
         n = 0;
@@ -2203,8 +2136,11 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
                 dbus_message_iter_get_basic(&sub3, &s);
                 dbus_message_iter_next(&sub3);
 
-                if (!(i->argv[n++] = strdup(s)))
+                i->argv[n] = strdup(s);
+                if (!i->argv[n])
                         return -ENOMEM;
+
+                n++;
         }
 
         if (!dbus_message_iter_next(&sub2) ||
@@ -2403,7 +2339,7 @@ static void print_status_info(UnitStatusInfo *i) {
                 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
 
         LIST_FOREACH(exec, p, i->exec) {
-                char *t;
+                _cleanup_free_ char *t = NULL;
                 bool good;
 
                 /* Only show exited processes here */
@@ -2412,7 +2348,6 @@ static void print_status_info(UnitStatusInfo *i) {
 
                 t = strv_join(p->argv, " ");
                 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
-                free(t);
 
                 good = is_clean_exit_lsb(p->code, p->status, NULL);
                 if (!good) {
@@ -2454,12 +2389,10 @@ static void print_status_info(UnitStatusInfo *i) {
                         printf("Main PID: %u", (unsigned) i->main_pid);
 
                         if (i->running) {
-                                char *t = NULL;
+                                _cleanup_free_ char *t = NULL;
                                 get_process_comm(i->main_pid, &t);
-                                if (t) {
+                                if (t)
                                         printf(" (%s)", t);
-                                        free(t);
-                                }
                         } else if (i->exit_code > 0) {
                                 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
 
@@ -2482,15 +2415,13 @@ static void print_status_info(UnitStatusInfo *i) {
                         printf(";");
 
                 if (i->control_pid > 0) {
-                        char *t = NULL;
+                        _cleanup_free_ char *t = NULL;
 
                         printf(" Control: %u", (unsigned) i->control_pid);
 
                         get_process_comm(i->control_pid, &t);
-                        if (t) {
+                        if (t)
                                 printf(" (%s)", t);
-                                free(t);
-                        }
                 }
 
                 printf("\n");
@@ -3015,7 +2946,7 @@ static int print_property(const char *name, DBusMessageIter *iter) {
 }
 
 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
-        DBusMessage *reply = NULL;
+        _cleanup_free_ DBusMessage *reply = NULL;
         const char *interface = "";
         int r;
         DBusMessageIter iter, sub, sub2, sub3;
@@ -3027,7 +2958,7 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
 
         zero(info);
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         path,
@@ -3037,15 +2968,14 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
                         NULL,
                         DBUS_TYPE_STRING, &interface,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
             dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_iter_recurse(&iter, &sub);
@@ -3058,24 +2988,13 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
                 const char *name;
 
-                if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
-                        log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
-                }
-
+                assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
                 dbus_message_iter_recurse(&sub, &sub2);
 
-                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
+                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
+                    dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
-                }
-
-                if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT)  {
-                        log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 dbus_message_iter_recurse(&sub2, &sub3);
@@ -3084,11 +3003,9 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
                         r = print_property(name, &sub3);
                 else
                         r = status_property(name, &sub3, &info);
-
                 if (r < 0) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 dbus_message_iter_next(&sub);
@@ -3116,22 +3033,18 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
                 exec_status_info_free(p);
         }
 
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
         return r;
 }
 
 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
-        DBusMessage *reply = NULL;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         const char *path = NULL;
         DBusError error;
         int r;
 
         dbus_error_init(&error);
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -3141,7 +3054,7 @@ static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid,
                         NULL,
                         DBUS_TYPE_UINT32, &pid,
                         DBUS_TYPE_INVALID);
-        if (r)
+        if (r < 0)
                 goto finish;
 
         if (!dbus_message_get_args(reply, &error,
@@ -3155,9 +3068,6 @@ static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid,
         r = show_one(verb, bus, path, false, new_line);
 
 finish:
-        if (reply)
-                dbus_message_unref(reply);
-
         dbus_error_free(&error);
 
         return r;
@@ -3176,50 +3086,43 @@ static int show(DBusConnection *bus, char **args) {
         if (show_properties)
                 pager_open_if_enabled();
 
-        if (show_properties && strv_length(args) <= 1) {
-                /* If not argument is specified inspect the manager
-                 * itself */
+        /* If no argument is specified inspect the manager itself */
 
+        if (show_properties && strv_length(args) <= 1)
                 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
-        }
 
         STRV_FOREACH(name, args+1) {
                 uint32_t id;
 
                 if (safe_atou32(*name, &id) < 0) {
-                        char *p, *n;
+                        _cleanup_free_ char *p = NULL, *n = NULL;
                         /* Interpret as unit name */
 
                         n = unit_name_mangle(*name);
-                        p = unit_dbus_path_from_name(n ? n : *name);
-                        free(n);
+                        if (!n)
+                                return log_oom();
+
+                        p = unit_dbus_path_from_name(n);
                         if (!p)
                                 return log_oom();
 
                         r = show_one(args[0], bus, p, show_properties, &new_line);
-                        free(p);
-
                         if (r != 0)
                                 ret = r;
 
                 } else if (show_properties) {
+                        _cleanup_free_ char *p = NULL;
 
                         /* Interpret as job id */
-
-                        char *p;
                         if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
                                 return log_oom();
 
                         r = show_one(args[0], bus, p, show_properties, &new_line);
-                        free(p);
-
                         if (r != 0)
                                 ret = r;
 
                 } else {
-
                         /* Interpret as PID */
-
                         r = show_one_by_pid(args[0], bus, id, &new_line);
                         if (r != 0)
                                 ret = r;
@@ -3230,7 +3133,7 @@ static int show(DBusConnection *bus, char **args) {
 }
 
 static int dump(DBusConnection *bus, char **args) {
-        DBusMessage *reply = NULL;
+        _cleanup_free_ DBusMessage *reply = NULL;
         DBusError error;
         int r;
         const char *text;
@@ -3239,7 +3142,7 @@ static int dump(DBusConnection *bus, char **args) {
 
         pager_open_if_enabled();
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -3248,26 +3151,19 @@ static int dump(DBusConnection *bus, char **args) {
                         &reply,
                         NULL,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_get_args(reply, &error,
                                    DBUS_TYPE_STRING, &text,
                                    DBUS_TYPE_INVALID)) {
                 log_error("Failed to parse reply: %s", bus_error_message(&error));
-                r = -EIO;
-                goto finish;
+                dbus_error_free(&error);
+                return  -EIO;
         }
 
         fputs(text, stdout);
-
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
-        dbus_error_free(&error);
-
-        return r;
+        return 0;
 }
 
 static int snapshot(DBusConnection *bus, char **args) {
@@ -3433,14 +3329,19 @@ static int daemon_reload(DBusConnection *bus, char **args) {
 
 static int reset_failed(DBusConnection *bus, char **args) {
         int r = 0;
-        char **name, *n;
+        char **name;
 
         if (strv_length(args) <= 1)
                 return daemon_reload(bus, args);
 
         STRV_FOREACH(name, args+1) {
+                _cleanup_free_ char *n;
+
                 n = unit_name_mangle(*name);
-                r = bus_method_call_with_reply (
+                if (!n)
+                        return log_oom();
+
+                r = bus_method_call_with_reply(
                                 bus,
                                 "org.freedesktop.systemd1",
                                 "/org/freedesktop/systemd1",
@@ -3448,19 +3349,17 @@ static int reset_failed(DBusConnection *bus, char **args) {
                                 "ResetFailedUnit",
                                 NULL,
                                 NULL,
-                                DBUS_TYPE_STRING, n ? &n : name,
+                                DBUS_TYPE_STRING, &n,
                                 DBUS_TYPE_INVALID);
-                free(n);
-                if (r)
-                        goto finish;
+                if (r < 0)
+                        return r;
         }
 
-finish:
-        return r;
+        return 0;
 }
 
 static int show_enviroment(DBusConnection *bus, char **args) {
-        DBusMessage *reply = NULL;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         DBusMessageIter iter, sub, sub2;
         int r;
         const char
@@ -3469,7 +3368,7 @@ static int show_enviroment(DBusConnection *bus, char **args) {
 
         pager_open_if_enabled();
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -3480,14 +3379,13 @@ static int show_enviroment(DBusConnection *bus, char **args) {
                         DBUS_TYPE_STRING, &interface,
                         DBUS_TYPE_STRING, &property,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0)
+                return r;
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_iter_recurse(&iter, &sub);
@@ -3495,8 +3393,7 @@ static int show_enviroment(DBusConnection *bus, char **args) {
         if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
             dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_iter_recurse(&sub, &sub2);
@@ -3506,23 +3403,16 @@ static int show_enviroment(DBusConnection *bus, char **args) {
 
                 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
                         log_error("Failed to parse reply.");
-                        r = -EIO;
-                        goto finish;
+                        return -EIO;
                 }
 
                 dbus_message_iter_get_basic(&sub2, &text);
-                printf("%s\n", text);
+                puts(text);
 
                 dbus_message_iter_next(&sub2);
         }
 
-        r = 0;
-
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
-        return r;
+        return 0;
 }
 
 static int switch_root(DBusConnection *bus, char **args) {
@@ -3547,15 +3437,13 @@ static int switch_root(DBusConnection *bus, char **args) {
 
                 if (!init)
                         init = strdup("");
-
-                if (!init)
-                        return log_oom();
-
         }
+        if (!init)
+                return log_oom();
 
         log_debug("switching root - root: %s; init: %s", root, init);
 
-        return bus_method_call_with_reply (
+        return bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -3601,15 +3489,11 @@ static int set_environment(DBusConnection *bus, char **args) {
         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));
-                r = -EIO;
-                goto finish;
+                dbus_error_free(&error);
+                return -EIO;
         }
 
-        r = 0;
-
-finish:
-        dbus_error_free(&error);
-        return r;
+        return 0;
 }
 
 static int enable_sysv_units(char **args) {

commit 043c432b77165dd149b7b870d3deb52cafe4fdb5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 14 02:08:02 2013 +0100

    bootchart: no need for memset here

diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 37d8fbe..f1b0e58 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -75,13 +75,11 @@ int main(int argc, char *argv[])
         struct ps_struct *ps;
         char output_file[PATH_MAX];
         char datestr[200];
-        time_t t;
+        time_t t = 0;
         FILE *f;
         int gind;
         int i;
 
-        memset(&t, 0, sizeof(time_t));
-
         rlim.rlim_cur = 4096;
         rlim.rlim_max = 4096;
         (void) setrlimit(RLIMIT_NOFILE, &rlim);

commit 246aa6dd9dcea84bb945d16ec86e69f869dbb9b4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jan 12 04:24:12 2013 +0100

    core: add bus API and systemctl commands for altering cgroup parameters during runtime

diff --git a/src/core/cgroup-attr.c b/src/core/cgroup-attr.c
index 71af09c..cedf37d 100644
--- a/src/core/cgroup-attr.c
+++ b/src/core/cgroup-attr.c
@@ -71,23 +71,42 @@ int cgroup_attribute_apply_list(CGroupAttribute *first, CGroupBonding *b) {
         return r;
 }
 
-CGroupAttribute *cgroup_attribute_find_list(CGroupAttribute *first, const char *controller, const char *name) {
+CGroupAttribute *cgroup_attribute_find_list(
+                CGroupAttribute *first,
+                const char *controller,
+                const char *name) {
         CGroupAttribute *a;
 
-        assert(controller);
         assert(name);
 
-        LIST_FOREACH(by_unit, a, first)
-                if (streq(a->controller, controller) &&
-                    streq(a->name, name))
-                        return a;
+        LIST_FOREACH(by_unit, a, first) {
+
+
+                if (controller) {
+                        if (streq(a->controller, controller) && streq(a->name, name))
+                                return a;
+
+                } else if (streq(a->name, name)) {
+                        size_t x, y;
+                        x = strlen(a->controller);
+                        y = strlen(name);
+
+                        if (y > x &&
+                            memcmp(a->controller, name, x) == 0 &&
+                            name[x] == '.')
+                                return a;
+                }
+        }
 
         return NULL;
 }
 
-static void cgroup_attribute_free(CGroupAttribute *a) {
+void cgroup_attribute_free(CGroupAttribute *a) {
         assert(a);
 
+        if (a->unit)
+                LIST_REMOVE(CGroupAttribute, by_unit, a->unit->cgroup_attributes, a);
+
         free(a->controller);
         free(a->name);
         free(a->value);
diff --git a/src/core/cgroup-attr.h b/src/core/cgroup-attr.h
index 2b754ea..0f5b854 100644
--- a/src/core/cgroup-attr.h
+++ b/src/core/cgroup-attr.h
@@ -33,6 +33,8 @@ struct CGroupAttribute {
         char *name;
         char *value;
 
+        Unit *unit;
+
         CGroupAttributeMapCallback map_callback;
 
         LIST_FIELDS(CGroupAttribute, by_unit);
@@ -43,4 +45,5 @@ int cgroup_attribute_apply_list(CGroupAttribute *first, CGroupBonding *b);
 
 CGroupAttribute *cgroup_attribute_find_list(CGroupAttribute *first, const char *controller, const char *name);
 
+void cgroup_attribute_free(CGroupAttribute *a);
 void cgroup_attribute_free_list(CGroupAttribute *first);
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 8fc1731..4790a09 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -110,7 +110,6 @@ void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root) {
                 cgroup_bonding_trim(b, delete_root);
 }
 
-
 int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *cgroup_suffix) {
         char *p = NULL;
         const char *path;
@@ -151,6 +150,34 @@ int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *cgr
         return 0;
 }
 
+int cgroup_bonding_migrate(CGroupBonding *b, CGroupBonding *list) {
+        CGroupBonding *q;
+        int ret = 0;
+
+        LIST_FOREACH(by_unit, q, list) {
+                int r;
+
+                if (q == b)
+                        continue;
+
+                if (!q->ours)
+                        continue;
+
+                r = cg_migrate_recursive(q->controller, q->path, b->controller, b->path, true, false);
+                if (r < 0 && ret == 0)
+                        ret = r;
+        }
+
+        return ret;
+}
+
+int cgroup_bonding_migrate_to(CGroupBonding *b, const char *target, bool rem) {
+        assert(b);
+        assert(target);
+
+        return cg_migrate_recursive(b->controller, b->path, b->controller, target, true, rem);
+}
+
 int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid) {
         assert(b);
 
@@ -520,7 +547,8 @@ Unit* cgroup_unit_by_pid(Manager *m, pid_t pid) {
 CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *controller) {
         CGroupBonding *b;
 
-        assert(controller);
+        if (!controller)
+                controller = SYSTEMD_CGROUP_CONTROLLER;
 
         LIST_FOREACH(by_unit, b, first)
                 if (streq(b->controller, controller))
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index 229da52..2ff39e5 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -58,6 +58,9 @@ void cgroup_bonding_free_list(CGroupBonding *first, bool trim);
 int cgroup_bonding_install(CGroupBonding *b, pid_t pid, const char *suffix);
 int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid, const char *suffix);
 
+int cgroup_bonding_migrate(CGroupBonding *b, CGroupBonding *list);
+int cgroup_bonding_migrate_to(CGroupBonding *b, const char *target, bool rem);
+
 int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
 int cgroup_bonding_set_group_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
 
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 2d9cea6..1d785a2 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -102,6 +102,26 @@
         "  <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"                  \
+        "   <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=\"SetUnitControlGroupAttributes\">\n"           \
+        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
+        "   <arg name=\"attributes\" type=\"a(sss)\" direction=\"in\"/>\n" \
+        "   <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>"         \
+        "  </method>\n"                                                 \
+        "  <method name=\"UnsetUnitControlGroupAttributes\">\n"         \
+        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
+        "   <arg name=\"attributes\" type=\"a(ss)\" 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"         \
@@ -848,6 +868,117 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
                 if (!reply)
                         goto oom;
 
+        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroups")) {
+                const char *name;
+                Unit *u;
+                DBusMessageIter iter;
+
+                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, "start");
+
+                r = bus_unit_cgroup_set(u, &iter);
+                if (r < 0)
+                        return bus_send_error_reply(connection, message, NULL, r);
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        goto oom;
+
+        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroups")) {
+                const char *name;
+                Unit *u;
+                DBusMessageIter iter;
+
+                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, "stop");
+
+                r = bus_unit_cgroup_unset(u, &iter);
+                if (r < 0)
+                        return bus_send_error_reply(connection, message, NULL, r);
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        goto oom;
+
+        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroupAttributes")) {
+                const char *name;
+                Unit *u;
+                DBusMessageIter iter;
+
+                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, "start");
+                r = bus_unit_cgroup_attribute_set(u, &iter);
+                if (r < 0)
+                        return bus_send_error_reply(connection, message, NULL, r);
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        goto oom;
+
+        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroupAttributes")) {
+                const char *name;
+                Unit *u;
+                DBusMessageIter iter;
+
+                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, "stop");
+
+                r = bus_unit_cgroup_attribute_unset(u, &iter);
+                if (r < 0)
+                        return bus_send_error_reply(connection, message, NULL, r);
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        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-mount.c b/src/core/dbus-mount.c
index d81edeb..0fcceb5 100644
--- a/src/core/dbus-mount.c
+++ b/src/core/dbus-mount.c
@@ -40,6 +40,7 @@
         BUS_EXEC_COMMAND_INTERFACE("ExecRemount")                       \
         BUS_EXEC_CONTEXT_INTERFACE                                      \
         BUS_KILL_CONTEXT_INTERFACE                                      \
+        BUS_UNIT_CGROUP_INTERFACE                                       \
         "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
@@ -159,6 +160,7 @@ DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMess
                 { "org.freedesktop.systemd1.Mount", bus_mount_properties,        m },
                 { "org.freedesktop.systemd1.Mount", bus_exec_context_properties, &m->exec_context },
                 { "org.freedesktop.systemd1.Mount", bus_kill_context_properties, &m->kill_context },
+                { "org.freedesktop.systemd1.Mount", bus_unit_cgroup_properties,  u },
                 { NULL, }
         };
 
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index d99058d..e06a5dc 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -50,6 +50,7 @@
         BUS_EXEC_COMMAND_INTERFACE("ExecStopPost")                      \
         BUS_EXEC_CONTEXT_INTERFACE                                      \
         BUS_KILL_CONTEXT_INTERFACE                                      \
+        BUS_UNIT_CGROUP_INTERFACE                                       \
         "  <property name=\"PermissionsStartOnly\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"RootDirectoryStartOnly\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"RemainAfterExit\" type=\"b\" access=\"read\"/>\n" \
@@ -152,6 +153,7 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio
                 { "org.freedesktop.systemd1.Service", bus_exec_context_properties,     &s->exec_context },
                 { "org.freedesktop.systemd1.Service", bus_kill_context_properties,     &s->kill_context },
                 { "org.freedesktop.systemd1.Service", bus_exec_main_status_properties, &s->main_exec_status },
+                { "org.freedesktop.systemd1.Service", bus_unit_cgroup_properties,      u },
                 { NULL, }
         };
 
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 095a031..2092a63 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -39,6 +39,7 @@
         BUS_EXEC_COMMAND_INTERFACE("ExecStopPost")                      \
         BUS_EXEC_CONTEXT_INTERFACE                                      \
         BUS_KILL_CONTEXT_INTERFACE                                      \
+        BUS_UNIT_CGROUP_INTERFACE                                       \
         "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
@@ -142,6 +143,7 @@ DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMes
                 { "org.freedesktop.systemd1.Socket", bus_socket_properties,       s },
                 { "org.freedesktop.systemd1.Socket", bus_exec_context_properties, &s->exec_context },
                 { "org.freedesktop.systemd1.Socket", bus_kill_context_properties, &s->kill_context },
+                { "org.freedesktop.systemd1.Socket", bus_unit_properties,         u },
                 { NULL, }
         };
 
diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c
index 67ea0f2..2e99fba 100644
--- a/src/core/dbus-swap.c
+++ b/src/core/dbus-swap.c
@@ -38,6 +38,7 @@
         BUS_EXEC_COMMAND_INTERFACE("ExecDeactivate")                    \
         BUS_EXEC_CONTEXT_INTERFACE                                      \
         BUS_KILL_CONTEXT_INTERFACE                                      \
+        BUS_UNIT_CGROUP_INTERFACE                                       \
         "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
         " </interface>\n"
@@ -106,6 +107,7 @@ DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessa
                 { "org.freedesktop.systemd1.Swap", bus_swap_properties,         s },
                 { "org.freedesktop.systemd1.Swap", bus_exec_context_properties, &s->exec_context },
                 { "org.freedesktop.systemd1.Swap", bus_kill_context_properties, &s->kill_context },
+                { "org.freedesktop.systemd1.Swap", bus_unit_cgroup_properties,  u },
                 { NULL, }
         };
 
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 8433a72..c7bf043 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -27,6 +27,9 @@
 #include "bus-errors.h"
 #include "dbus-common.h"
 #include "selinux-access.h"
+#include "cgroup-util.h"
+#include "strv.h"
+#include "path-util.h"
 
 const char bus_unit_interface[] _introspect_("Unit") = BUS_UNIT_INTERFACE;
 
@@ -468,6 +471,69 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
                 if (!reply)
                         goto oom;
 
+        } else if (streq_ptr(dbus_message_get_member(message), "SetControlGroups")) {
+                DBusMessageIter iter;
+
+                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+
+                if (!dbus_message_iter_init(message, &iter))
+                        goto oom;
+
+                r = bus_unit_cgroup_set(u, &iter);
+                if (r < 0)
+                        return bus_send_error_reply(connection, message, NULL, r);
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        goto oom;
+
+        } else if (streq_ptr(dbus_message_get_member(message), "UnsetControlGroups")) {
+                DBusMessageIter iter;
+
+                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
+
+                if (!dbus_message_iter_init(message, &iter))
+                        goto oom;
+
+                r = bus_unit_cgroup_set(u, &iter);
+                if (r < 0)
+                        return bus_send_error_reply(connection, message, NULL, r);
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        goto oom;
+        } else if (streq_ptr(dbus_message_get_member(message), "SetControlGroupAttributes")) {
+                DBusMessageIter iter;
+
+                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+
+                if (!dbus_message_iter_init(message, &iter))
+                        goto oom;
+
+                r = bus_unit_cgroup_attribute_set(u, &iter);
+                if (r < 0)
+                        return bus_send_error_reply(connection, message, NULL, r);
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        goto oom;
+
+        } else if (streq_ptr(dbus_message_get_member(message), "UnsetControlGroupAttributes")) {
+                DBusMessageIter iter;
+
+                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
+
+                if (!dbus_message_iter_init(message, &iter))
+                        goto oom;
+
+                r = bus_unit_cgroup_attribute_unset(u, &iter);
+                if (r < 0)
+                        return bus_send_error_reply(connection, message, NULL, r);
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        goto oom;
+
         } else if (UNIT_VTABLE(u)->bus_message_handler)
                 return UNIT_VTABLE(u)->bus_message_handler(u, connection, message);
         else
@@ -809,6 +875,180 @@ oom:
         return DBUS_HANDLER_RESULT_NEED_MEMORY;
 }
 
+int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter) {
+        int r;
+        _cleanup_strv_free_ char **a = NULL;
+        char **name;
+
+        assert(u);
+        assert(iter);
+
+        if (!unit_get_exec_context(u))
+                return -EINVAL;
+
+        r = bus_parse_strv_iter(iter, &a);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(name, a) {
+                _cleanup_free_ char *controller = NULL, *old_path = NULL, *new_path = NULL;
+                CGroupBonding *b;
+
+                r = cg_split_spec(*name, &controller, &new_path);
+                if (r < 0)
+                        return r;
+
+                b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
+                if (b) {
+                        old_path = strdup(b->path);
+                        if (!old_path)
+                                return -ENOMEM;
+                }
+
+                r = unit_add_cgroup_from_text(u, *name, true, &b);
+                if (r < 0)
+                        return r;
+
+                if (r > 0) {
+                        /* Try to move things to the new place, and clean up the old place */
+                        cgroup_bonding_realize(b);
+                        cgroup_bonding_migrate(b, u->cgroup_bondings);
+
+                        if (old_path)
+                                cg_trim(controller, old_path, true);
+                }
+        }
+
+        return 0;
+}
+
+int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter) {
+        _cleanup_strv_free_ char **a = NULL;
+        char **name;
+        int r;
+
+        assert(u);
+        assert(iter);
+
+        if (!unit_get_exec_context(u))
+                return -EINVAL;
+
+        r = bus_parse_strv_iter(iter, &a);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(name, a) {
+                _cleanup_free_ char *controller = NULL, *path = NULL, *target = NULL;
+                CGroupBonding *b;
+
+                r = cg_split_spec(*name, &controller, &path);
+                if (r < 0)
+                        return r;
+
+                b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
+                if (!b)
+                        continue;
+
+                if (path && !path_equal(path, b->path))
+                        continue;
+
+                if (b->essential)
+                        return -EINVAL;
+
+                /* Try to migrate the old group away */
+                if (cg_get_by_pid(controller, 0, &target) >= 0)
+                        cgroup_bonding_migrate_to(u->cgroup_bondings, target, false);
+
+                cgroup_bonding_free(b, true);
+        }
+
+        return 0;
+}
+
+int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter) {
+        DBusMessageIter sub, sub2;
+        int r;
+
+        assert(u);
+        assert(iter);
+
+        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);
+
+        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+                const char *name, *value;
+                CGroupAttribute *a;
+
+                assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
+
+                dbus_message_iter_recurse(&sub, &sub2);
+
+                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;
+
+                dbus_message_iter_next(&sub);
+
+                r = unit_add_cgroup_attribute(u, NULL, name, value, NULL, &a);
+                if (r < 0)
+                        return r;
+
+                if (r > 0) {
+                        CGroupBonding *b;
+
+                        b = cgroup_bonding_find_list(u->cgroup_bondings, a->controller);
+                        if (!b) {
+                                /* Doesn't exist yet? Then let's add it */
+                                r = unit_add_cgroup_from_text(u, a->controller, false, &b);
+                                if (r < 0)
+                                        return r;
+
+                                if (r > 0) {
+                                        cgroup_bonding_realize(b);
+                                        cgroup_bonding_migrate(b, u->cgroup_bondings);
+                                }
+                        }
+
+                        /* Make it count */
+                        cgroup_attribute_apply(a, u->cgroup_bondings);
+                }
+        }
+
+        return 0;
+}
+
+int bus_unit_cgroup_attribute_unset(Unit *u, DBusMessageIter *iter) {
+        _cleanup_strv_free_ char **l = NULL;
+        char **name;
+        int r;
+
+        assert(u);
+        assert(iter);
+
+        if (!unit_get_exec_context(u))
+                return -EINVAL;
+
+        r = bus_parse_strv_iter(iter, &l);
+        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);
+        }
+
+        return 0;
+}
+
 const BusProperty bus_unit_properties[] = {
         { "Id",                   bus_property_append_string,         "s", offsetof(Unit, id),                                         true },
         { "Names",                bus_unit_append_names,             "as", 0 },
@@ -864,9 +1104,6 @@ const BusProperty bus_unit_properties[] = {
         { "OnFailureIsolate",     bus_property_append_bool,           "b", offsetof(Unit, on_failure_isolate)                 },
         { "IgnoreOnIsolate",      bus_property_append_bool,           "b", offsetof(Unit, ignore_on_isolate)                  },
         { "IgnoreOnSnapshot",     bus_property_append_bool,           "b", offsetof(Unit, ignore_on_snapshot)                 },
-        { "DefaultControlGroup",  bus_unit_append_default_cgroup,     "s", 0 },
-        { "ControlGroup",         bus_unit_append_cgroups,           "as", 0 },
-        { "ControlGroupAttributes", bus_unit_append_cgroup_attrs,"a(sss)", 0 },
         { "NeedDaemonReload",     bus_unit_append_need_daemon_reload, "b", 0 },
         { "JobTimeoutUSec",       bus_property_append_usec,           "t", offsetof(Unit, job_timeout)                        },
         { "ConditionTimestamp",   bus_property_append_usec,           "t", offsetof(Unit, condition_timestamp.realtime)       },
@@ -875,3 +1112,10 @@ const BusProperty bus_unit_properties[] = {
         { "LoadError",            bus_unit_append_load_error,      "(ss)", 0 },
         { NULL, }
 };
+
+const BusProperty bus_unit_cgroup_properties[] = {
+        { "DefaultControlGroup",    bus_unit_append_default_cgroup,     "s", 0 },
+        { "ControlGroups",          bus_unit_append_cgroups,           "as", 0 },
+        { "ControlGroupAttributes", bus_unit_append_cgroup_attrs,  "a(sss)", 0 },
+        { NULL, }
+};
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index ac6785a..7b8c5a9 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -113,9 +113,6 @@
         "  <property name=\"OnFailureIsolate\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"IgnoreOnIsolate\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"IgnoreOnSnapshot\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"ControlGroup\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ControlGroupAttributes\" type=\"a(sss)\" access=\"read\"/>\n" \
         "  <property name=\"NeedDaemonReload\" type=\"b\" access=\"read\"/>\n" \
         "  <property name=\"JobTimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
@@ -124,16 +121,37 @@
         "  <property name=\"LoadError\" type=\"(ss)\" access=\"read\"/>\n" \
         " </interface>\n"
 
+#define BUS_UNIT_CGROUP_INTERFACE                                       \
+        "  <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>\n"                                                 \
+        "  <method name=\"SetControlGroupAttributes\">\n"               \
+        "   <arg name=\"attributes\" type=\"a(ss)\" direction=\"in\"/>\n" \
+        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
+        "  </method>\n"                                                 \
+        "  <method name=\"UnsetControlGroupAttributes\">\n"             \
+        "   <arg name=\"attributes\" type=\"as\" direction=\"in\"/>\n"  \
+        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
+        "  </method>\n"
+
 #define BUS_UNIT_INTERFACES_LIST                \
         BUS_GENERIC_INTERFACES_LIST             \
         "org.freedesktop.systemd1.Unit\0"
 
 extern const BusProperty bus_unit_properties[];
+extern const BusProperty bus_unit_cgroup_properties[];
 
 void bus_unit_send_change_signal(Unit *u);
 void bus_unit_send_removed_signal(Unit *u);
 
-
 DBusHandlerResult bus_unit_queue_job(
                 DBusConnection *connection,
                 DBusMessage *message,
@@ -142,6 +160,11 @@ DBusHandlerResult bus_unit_queue_job(
                 JobMode mode,
                 bool reload_if_possible);
 
+int bus_unit_cgroup_set(Unit *u, DBusMessageIter *iter);
+int bus_unit_cgroup_unset(Unit *u, DBusMessageIter *iter);
+int bus_unit_cgroup_attribute_set(Unit *u, DBusMessageIter *iter);
+int bus_unit_cgroup_attribute_unset(Unit *u, DBusMessageIter *iter);
+
 extern const DBusObjectPathVTable bus_unit_vtable;
 
 extern const char bus_unit_interface[];
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index e35fdbc..4d1154e 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -984,7 +984,7 @@ int config_parse_unit_cgroup(
                 if (!ku)
                         return -ENOMEM;
 
-                r = unit_add_cgroup_from_text(u, ku);
+                r = unit_add_cgroup_from_text(u, ku, true, NULL);
                 if (r < 0) {
                         log_error("[%s:%u] Failed to parse cgroup value %s, ignoring: %s",
                                   filename, line, k, rvalue);
@@ -1659,7 +1659,7 @@ int config_parse_unit_cgroup_attr(
                 return 0;
         }
 
-        r = unit_add_cgroup_attribute(u, NULL, l[0], l[1], NULL);
+        r = unit_add_cgroup_attribute(u, NULL, l[0], l[1], NULL, NULL);
         strv_free(l);
 
         if (r < 0) {
@@ -1689,7 +1689,7 @@ int config_parse_unit_cpu_shares(const char *filename, unsigned line, const char
         if (asprintf(&t, "%lu", ul) < 0)
                 return -ENOMEM;
 
-        r = unit_add_cgroup_attribute(u, "cpu", "cpu.shares", t, NULL);
+        r = unit_add_cgroup_attribute(u, "cpu", "cpu.shares", t, NULL, NULL);
         free(t);
 
         if (r < 0) {
@@ -1722,7 +1722,7 @@ int config_parse_unit_memory_limit(const char *filename, unsigned line, const ch
         r = unit_add_cgroup_attribute(u,
                                       "memory",
                                       streq(lvalue, "MemorySoftLimit") ? "memory.soft_limit_in_bytes" : "memory.limit_in_bytes",
-                                      t, NULL);
+                                      t, NULL, NULL);
         free(t);
 
         if (r < 0) {
@@ -1821,7 +1821,7 @@ int config_parse_unit_device_allow(const char *filename, unsigned line, const ch
 
         r = unit_add_cgroup_attribute(u, "devices",
                                       streq(lvalue, "DeviceAllow") ? "devices.allow" : "devices.deny",
-                                      rvalue, device_map);
+                                      rvalue, device_map, NULL);
 
         if (r < 0) {
                 log_error("[%s:%u] Failed to add cgroup attribute value, ignoring: %s", filename, line, rvalue);
@@ -1931,9 +1931,9 @@ int config_parse_unit_blkio_weight(const char *filename, unsigned line, const ch
                 return -ENOMEM;
 
         if (device)
-                r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight_device", t, blkio_map);
+                r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight_device", t, blkio_map, NULL);
         else
-                r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight", t, NULL);
+                r = unit_add_cgroup_attribute(u, "blkio", "blkio.weight", t, NULL, NULL);
         free(t);
 
         if (r < 0) {
@@ -1987,7 +1987,7 @@ int config_parse_unit_blkio_bandwidth(const char *filename, unsigned line, const
 
         r = unit_add_cgroup_attribute(u, "blkio",
                                       streq(lvalue, "BlockIOReadBandwidth") ? "blkio.read_bps_device" : "blkio.write_bps_device",
-                                      t, blkio_map);
+                                      t, blkio_map, NULL);
         free(t);
 
         if (r < 0) {
diff --git a/src/core/unit.c b/src/core/unit.c
index f00cfed..1194c52 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1941,8 +1941,9 @@ int unit_add_cgroup(Unit *u, CGroupBonding *b) {
         assert(b->path);
 
         if (!b->controller) {
-                if (!(b->controller = strdup(SYSTEMD_CGROUP_CONTROLLER)))
-                        return -ENOMEM;
+                b->controller = strdup(SYSTEMD_CGROUP_CONTROLLER);
+                if (!b->controller)
+                        return log_oom();
 
                 b->ours = true;
         }
@@ -1956,7 +1957,8 @@ int unit_add_cgroup(Unit *u, CGroupBonding *b) {
                 l = hashmap_get(u->manager->cgroup_bondings, b->path);
                 LIST_PREPEND(CGroupBonding, by_path, l, b);
 
-                if ((r = hashmap_replace(u->manager->cgroup_bondings, b->path, l)) < 0) {
+                r = hashmap_replace(u->manager->cgroup_bondings, b->path, l);
+                if (r < 0) {
                         LIST_REMOVE(CGroupBonding, by_path, l, b);
                         return r;
                 }
@@ -1969,26 +1971,21 @@ int unit_add_cgroup(Unit *u, CGroupBonding *b) {
 }
 
 char *unit_default_cgroup_path(Unit *u) {
-        char *p;
-
         assert(u);
 
         if (u->instance) {
-                char *t;
+                _cleanup_free_ char *t = NULL;
 
                 t = unit_name_template(u->id);
                 if (!t)
                         return NULL;
 
-                p = strjoin(u->manager->cgroup_hierarchy, "/", t, "/", u->instance, NULL);
-                free(t);
+                return strjoin(u->manager->cgroup_hierarchy, "/", t, "/", u->instance, NULL);
         } else
-                p = strjoin(u->manager->cgroup_hierarchy, "/", u->id, NULL);
-
-        return p;
+                return strjoin(u->manager->cgroup_hierarchy, "/", u->id, NULL);
 }
 
-int unit_add_cgroup_from_text(Unit *u, const char *name) {
+int unit_add_cgroup_from_text(Unit *u, const char *name, bool overwrite, CGroupBonding **ret) {
         char *controller = NULL, *path = NULL;
         CGroupBonding *b = NULL;
         bool ours = false;
@@ -1997,7 +1994,8 @@ int unit_add_cgroup_from_text(Unit *u, const char *name) {
         assert(u);
         assert(name);
 
-        if ((r = cg_split_spec(name, &controller, &path)) < 0)
+        r = cg_split_spec(name, &controller, &path);
+        if (r < 0)
                 return r;
 
         if (!path) {
@@ -2013,16 +2011,42 @@ int unit_add_cgroup_from_text(Unit *u, const char *name) {
         if (!path || !controller) {
                 free(path);
                 free(controller);
-
-                return -ENOMEM;
+                return log_oom();
         }
 
-        if (cgroup_bonding_find_list(u->cgroup_bondings, controller)) {
+        b = cgroup_bonding_find_list(u->cgroup_bondings, controller);
+        if (b) {
+                if (streq(path, b->path)) {
+                        free(path);
+                        free(controller);
+
+                        if (ret)
+                                *ret = b;
+                        return 0;
+                }
+
+                if (overwrite && !b->essential) {
+                        free(controller);
+
+                        free(b->path);
+                        b->path = path;
+
+                        b->ours = ours;
+                        b->realized = false;
+
+                        if (ret)
+                                *ret = b;
+
+                        return 1;
+                }
+
                 r = -EEXIST;
+                b = NULL;
                 goto fail;
         }
 
-        if (!(b = new0(CGroupBonding, 1))) {
+        b = new0(CGroupBonding, 1);
+        if (!b) {
                 r = -ENOMEM;
                 goto fail;
         }
@@ -2032,10 +2056,14 @@ int unit_add_cgroup_from_text(Unit *u, const char *name) {
         b->ours = ours;
         b->essential = streq(controller, SYSTEMD_CGROUP_CONTROLLER);
 
-        if ((r = unit_add_cgroup(u, b)) < 0)
+        r = unit_add_cgroup(u, b);
+        if (r < 0)
                 goto fail;
 
-        return 0;
+        if (ret)
+                *ret = b;
+
+        return 1;
 
 fail:
         free(path);
@@ -2057,10 +2085,12 @@ static int unit_add_one_default_cgroup(Unit *u, const char *controller) {
         if (cgroup_bonding_find_list(u->cgroup_bondings, controller))
                 return 0;
 
-        if (!(b = new0(CGroupBonding, 1)))
+        b = new0(CGroupBonding, 1);
+        if (!b)
                 return -ENOMEM;
 
-        if (!(b->controller = strdup(controller)))
+        b->controller = strdup(controller);
+        if (!b)
                 goto fail;
 
         b->path = unit_default_cgroup_path(u);
@@ -2070,7 +2100,8 @@ static int unit_add_one_default_cgroup(Unit *u, const char *controller) {
         b->ours = true;
         b->essential = streq(controller, SYSTEMD_CGROUP_CONTROLLER);
 
-        if ((r = unit_add_cgroup(u, b)) < 0)
+        r = unit_add_cgroup(u, b);
+        if (r < 0)
                 goto fail;
 
         return 0;
@@ -2096,7 +2127,8 @@ int unit_add_default_cgroups(Unit *u) {
         if (!u->manager->cgroup_hierarchy)
                 return 0;
 
-        if ((r = unit_add_one_default_cgroup(u, NULL)) < 0)
+        r = unit_add_one_default_cgroup(u, NULL);
+        if (r < 0)
                 return r;
 
         STRV_FOREACH(c, u->manager->default_controllers)
@@ -2111,12 +2143,18 @@ int unit_add_default_cgroups(Unit *u) {
 CGroupBonding* unit_get_default_cgroup(Unit *u) {
         assert(u);
 
-        return cgroup_bonding_find_list(u->cgroup_bondings, SYSTEMD_CGROUP_CONTROLLER);
+        return cgroup_bonding_find_list(u->cgroup_bondings, NULL);
 }
 
-int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name, const char *value, CGroupAttributeMapCallback map_callback) {
-        int r;
-        char *c = NULL;
+int unit_add_cgroup_attribute(
+                Unit *u,
+                const char *controller,
+                const char *name,
+                const char *value,
+                CGroupAttributeMapCallback map_callback,
+                CGroupAttribute **ret) {
+
+        _cleanup_free_ char *c = NULL;
         CGroupAttribute *a;
 
         assert(u);
@@ -2137,16 +2175,36 @@ int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name,
                 controller = c;
         }
 
-        if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
-                r = -EINVAL;
-                goto finish;
+        if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
+                return -EINVAL;
+
+        a = cgroup_attribute_find_list(u->cgroup_attributes, controller, name);
+        if (a) {
+                char *v;
+
+                if (streq(value, a->value)) {
+                        if (ret)
+                                *ret = a;
+
+                        return 0;
+                }
+
+                v = strdup(value);
+                if (!v)
+                        return -ENOMEM;
+
+                free(a->value);
+                a->value = v;
+
+                if (ret)
+                        *ret = a;
+
+                return 1;
         }
 
         a = new0(CGroupAttribute, 1);
-        if (!a) {
-                r = -ENOMEM;
-                goto finish;
-        }
+        if (!a)
+                return -ENOMEM;
 
         if (c) {
                 a->controller = c;
@@ -2167,14 +2225,14 @@ int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name,
         }
 
         a->map_callback = map_callback;
+        a->unit = u;
 
         LIST_PREPEND(CGroupAttribute, by_unit, u->cgroup_attributes, a);
 
-        r = 0;
+        if (ret)
+                *ret = a;
 
-finish:
-        free(c);
-        return r;
+        return 1;
 }
 
 int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
diff --git a/src/core/unit.h b/src/core/unit.h
index 702bfee..d1ecae7 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -438,10 +438,10 @@ int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDep
 int unit_add_exec_dependencies(Unit *u, ExecContext *c);
 
 int unit_add_cgroup(Unit *u, CGroupBonding *b);
-int unit_add_cgroup_from_text(Unit *u, const char *name);
+int unit_add_cgroup_from_text(Unit *u, const char *name, bool overwrite, CGroupBonding **ret);
 int unit_add_default_cgroups(Unit *u);
 CGroupBonding* unit_get_default_cgroup(Unit *u);
-int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name, const char *value, CGroupAttributeMapCallback map_callback);
+int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name, const char *value, CGroupAttributeMapCallback map_callback, CGroupAttribute **ret);
 
 int unit_choose_id(Unit *u, const char *name);
 int unit_set_description(Unit *u, const char *description);
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index 18cbf04..9dfab2e 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -374,18 +374,20 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path, bool re
         return 0;
 }
 
-int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
+int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
         bool done = false;
-        Set *s;
+        _cleanup_set_free_ Set *s = NULL;
         int r, ret = 0;
         pid_t my_pid;
-        FILE *f = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
 
-        assert(controller);
-        assert(from);
-        assert(to);
+        assert(cfrom);
+        assert(pfrom);
+        assert(cto);
+        assert(pto);
 
-        if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
+        s = set_new(trivial_hash_func, trivial_compare_func);
+        if (!s)
                 return -ENOMEM;
 
         my_pid = getpid();
@@ -394,11 +396,12 @@ int cg_migrate(const char *controller, const char *from, const char *to, bool ig
                 pid_t pid = 0;
                 done = true;
 
-                if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) {
+                r = cg_enumerate_tasks(cfrom, pfrom, &f);
+                if (r < 0) {
                         if (ret >= 0 && r != -ENOENT)
                                 ret = r;
 
-                        goto finish;
+                        return ret;
                 }
 
                 while ((r = cg_read_pid(f, &pid)) > 0) {
@@ -412,7 +415,8 @@ int cg_migrate(const char *controller, const char *from, const char *to, bool ig
                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
                                 continue;
 
-                        if ((r = cg_attach(controller, to, pid)) < 0) {
+                        r = cg_attach(cto, pto, pid);
+                        if (r < 0) {
                                 if (ret >= 0 && r != -ESRCH)
                                         ret = r;
                         } else if (ret == 0)
@@ -420,11 +424,12 @@ int cg_migrate(const char *controller, const char *from, const char *to, bool ig
 
                         done = false;
 
-                        if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
+                        r = set_put(s, LONG_TO_PTR(pid));
+                        if (r < 0) {
                                 if (ret >= 0)
                                         ret = r;
 
-                                goto finish;
+                                return ret;
                         }
                 }
 
@@ -432,56 +437,48 @@ int cg_migrate(const char *controller, const char *from, const char *to, bool ig
                         if (ret >= 0)
                                 ret = r;
 
-                        goto finish;
+                        return ret;
                 }
 
                 fclose(f);
                 f = NULL;
-
         } while (!done);
 
-finish:
-        set_free(s);
-
-        if (f)
-                fclose(f);
-
         return ret;
 }
 
-int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool rem) {
+int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) {
         int r, ret = 0;
-        DIR *d = NULL;
+        _cleanup_closedir_ DIR *d = NULL;
         char *fn;
 
-        assert(controller);
-        assert(from);
-        assert(to);
+        assert(cfrom);
+        assert(pfrom);
+        assert(cto);
+        assert(pto);
 
-        ret = cg_migrate(controller, from, to, ignore_self);
+        ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
 
-        if ((r = cg_enumerate_subgroups(controller, from, &d)) < 0) {
+        r = cg_enumerate_subgroups(cfrom, pfrom, &d);
+        if (r < 0) {
                 if (ret >= 0 && r != -ENOENT)
                         ret = r;
-                goto finish;
+                return ret;
         }
 
         while ((r = cg_read_subgroup(d, &fn)) > 0) {
-                char *p = NULL;
+                _cleanup_free_ char *p = NULL;
 
-                r = asprintf(&p, "%s/%s", from, fn);
+                p = strjoin(pfrom, "/", fn, NULL);
                 free(fn);
-
-                if (r < 0) {
+                if (!p) {
                         if (ret >= 0)
                                 ret = -ENOMEM;
 
-                        goto finish;
+                        return ret;
                 }
 
-                r = cg_migrate_recursive(controller, p, to, ignore_self, rem);
-                free(p);
-
+                r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
                 if (r != 0 && ret >= 0)
                         ret = r;
         }
@@ -489,17 +486,11 @@ int cg_migrate_recursive(const char *controller, const char *from, const char *t
         if (r < 0 && ret >= 0)
                 ret = r;
 
-        if (rem)
-                if ((r = cg_rmdir(controller, from, true)) < 0) {
-                        if (ret >= 0 &&
-                            r != -ENOENT &&
-                            r != -EBUSY)
-                                ret = r;
-                }
-
-finish:
-        if (d)
-                closedir(d);
+        if (rem) {
+                r = cg_rmdir(cfrom, pfrom, true);
+                if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
+                        return r;
+        }
 
         return ret;
 }
@@ -677,7 +668,7 @@ int cg_delete(const char *controller, const char *path) {
         if ((r = path_get_parent(path, &parent)) < 0)
                 return r;
 
-        r = cg_migrate_recursive(controller, path, parent, false, true);
+        r = cg_migrate_recursive(controller, path, controller, parent, false, true);
         free(parent);
 
         return r == -ENOENT ? 0 : r;
@@ -947,7 +938,6 @@ int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
         return cg_is_empty(controller, path, ignore_self);
 }
 
-
 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
         int r;
         DIR *d = NULL;
@@ -997,12 +987,12 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
         char *t = NULL, *u = NULL;
 
         assert(spec);
-        assert(controller || path);
 
         if (*spec == '/') {
 
                 if (path) {
-                        if (!(t = strdup(spec)))
+                        t = strdup(spec);
+                        if (!t)
                                 return -ENOMEM;
 
                         *path = t;
@@ -1014,13 +1004,14 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
                 return 0;
         }
 
-        if (!(e = strchr(spec, ':'))) {
-
+        e = strchr(spec, ':');
+        if (!e) {
                 if (strchr(spec, '/') || spec[0] == 0)
                         return -EINVAL;
 
                 if (controller) {
-                        if (!(t = strdup(spec)))
+                        t = strdup(spec);
+                        if (!t)
                                 return -ENOMEM;
 
                         *controller = t;
@@ -1032,20 +1023,23 @@ int cg_split_spec(const char *spec, char **controller, char **path) {
                 return 0;
         }
 
-        if (e[1] != '/' ||
-            e == spec ||
-            memchr(spec, '/', e-spec))
+        if (e[1] != '/' || e == spec || memchr(spec, '/', e-spec))
                 return -EINVAL;
 
-        if (controller)
-                if (!(t = strndup(spec, e-spec)))
+        if (controller) {
+                t = strndup(spec, e-spec);
+                if (!t)
                         return -ENOMEM;
 
-        if (path)
-                if (!(u = strdup(e+1))) {
+        }
+
+        if (path) {
+                u = strdup(e+1);
+                if (!u) {
                         free(t);
                         return -ENOMEM;
                 }
+        }
 
         if (controller)
                 *controller = t;
diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h
index af2efc3..f663fba 100644
--- a/src/shared/cgroup-util.h
+++ b/src/shared/cgroup-util.h
@@ -39,8 +39,8 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool remove, Set *s);
 int cg_kill_recursive_and_wait(const char *controller, const char *path, bool remove);
 
-int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self);
-int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool remove);
+int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self);
+int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove);
 
 int cg_split_spec(const char *spec, char **controller, char **path);
 int cg_join_spec(const char *controller, const char *path, char **spec);
diff --git a/src/shared/strv.h b/src/shared/strv.h
index 44ba3d1..fd728ef 100644
--- a/src/shared/strv.h
+++ b/src/shared/strv.h
@@ -82,4 +82,8 @@ bool strv_overlap(char **a, char **b);
 #define STRV_FOREACH_BACKWARDS(s, l)            \
         for (; (l) && ((s) >= (l)); (s)--)
 
+#define STRV_FOREACH_PAIR(x, y, l)               \
+        for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2)
+
+
 char **strv_sort(char **l);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 91467cc..075ee4b 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2025,6 +2025,110 @@ static int kill_unit(DBusConnection *bus, char **args) {
         return 0;
 }
 
+static int set_cgroup(DBusConnection *bus, char **args) {
+        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+        DBusError error;
+        const char *method;
+        DBusMessageIter iter;
+        int r;
+        _cleanup_free_ char *n = NULL;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        method =
+                streq(args[0], "set-cgroup")  ? "SetUnitControlGroups" :
+                streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
+                                              : "UnsetUnitControlGroupAttributes";
+
+        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",
+                        method);
+        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;
+        }
+
+        return 0;
+}
+
+static int set_cgroup_attr(DBusConnection *bus, char **args) {
+        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+        DBusError error;
+        DBusMessageIter iter, sub, sub2;
+        int r;
+        char **x, **y;
+        _cleanup_free_ char *n = NULL;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        if (strv_length(args) % 2 != 0) {
+                log_error("Expecting an uneven number of arguments!");
+                return -EINVAL;
+        }
+
+        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",
+                        "SetUnitControlGroupAttributes");
+        if (!m)
+                return log_oom();
+
+        dbus_message_iter_init_append(m, &iter);
+        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
+            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
+                return log_oom();
+
+        STRV_FOREACH_PAIR(x, y, args + 2) {
+                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
+                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
+                    !dbus_message_iter_close_container(&sub, &sub2))
+                        return log_oom();
+        }
+
+        if (!dbus_message_iter_close_container(&iter, &sub))
+                return -ENOMEM;
+
+        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;
+        }
+
+        return 0;
+}
+
 typedef struct ExecStatusInfo {
         char *name;
 
@@ -4076,6 +4180,12 @@ 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"
+               "  set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
+               "                                  Set control group attribute\n"
+               "  unset-cgroup-attr [NAME] [ATTR...]\n"
+               "                                  Unset control group attribute\n"
                "  load [NAME...]                  Load one or more units\n\n"
                "Unit File Commands:\n"
                "  list-unit-files                 List installed unit files\n"
@@ -5051,6 +5161,10 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "condreload",            MORE,  2, start_unit        }, /* For compatibility with ALTLinux */
                 { "condrestart",           MORE,  2, start_unit        }, /* For compatibility with RH */
                 { "isolate",               EQUAL, 2, start_unit        },
+                { "set-cgroup",            MORE,  2, set_cgroup        },
+                { "unset-cgroup",          MORE,  2, set_cgroup        },
+                { "set-cgroup-attr",       MORE,  2, set_cgroup_attr   },
+                { "unset-cgroup-attr",     MORE,  2, set_cgroup        },
                 { "kill",                  MORE,  2, kill_unit         },
                 { "is-active",             MORE,  2, check_unit_active },
                 { "check",                 MORE,  2, check_unit_active },
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
index 6d64a4e..96aca1f 100644
--- a/src/test/test-cgroup.c
+++ b/src/test/test-cgroup.c
@@ -65,7 +65,7 @@ int main(int argc, char*argv[]) {
         assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0);
         assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0);
 
-        assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", "/test-a", false, false) > 0);
+        assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", false, false) > 0);
 
         assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) == 0);
         assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);

commit 748ebafa7a10d4e1f168dd8ae0193124cdf4226e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jan 12 00:09:22 2013 +0100

    systemctl: honour inhibitors only when running unprivileged

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index bfa4d45..91467cc 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1791,7 +1791,16 @@ static int check_inhibitors(DBusConnection *bus, enum action a) {
         int r;
         unsigned c = 0;
 
-        if (arg_ignore_inhibitors)
+        if (!bus)
+                return 0;
+
+        if (arg_ignore_inhibitors || arg_force > 0)
+                return 0;
+
+        if (arg_when > 0)
+                return 0;
+
+        if (geteuid() == 0)
                 return 0;
 
         if (!on_tty())
@@ -1890,6 +1899,10 @@ static int start_special(DBusConnection *bus, char **args) {
 
         a = verb_to_action(args[0]);
 
+        r = check_inhibitors(bus, a);
+        if (r < 0)
+                return r;
+
         if (arg_force >= 2 && geteuid() != 0) {
                 log_error("Must be root.");
                 return -EPERM;
@@ -1909,12 +1922,6 @@ static int start_special(DBusConnection *bus, char **args) {
              a == ACTION_EXIT))
                 return daemon_reload(bus, args);
 
-        if (arg_force <= 0) {
-                r = check_inhibitors(bus, a);
-                if (r < 0)
-                        return r;
-        }
-
         /* first try logind, to allow authentication with polkit */
         if (geteuid() != 0 &&
             (a == ACTION_POWEROFF ||
@@ -5304,11 +5311,9 @@ static _noreturn_ void halt_now(enum action a) {
 static int halt_main(DBusConnection *bus) {
         int r;
 
-        if (arg_when <= 0 && arg_force <= 0) {
-                r = check_inhibitors(bus, arg_action);
-                if (r < 0)
-                        return r;
-        }
+        r = check_inhibitors(bus, arg_action);
+        if (r < 0)
+                return r;
 
         if (geteuid() != 0) {
                 /* Try logind if we are a normal user and no special

commit d255133d8edc84662d2370a77414505a800d1922
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jan 12 00:00:22 2013 +0100

    systemctl: don't hit an assert if we try to reboot and dbus is dead
    
    https://bugzilla.redhat.com/show_bug.cgi?id=889624

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 0def1a2..bfa4d45 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1738,6 +1738,9 @@ static int reboot_with_logind(DBusConnection *bus, enum action a) {
         const char *method;
         dbus_bool_t interactive = true;
 
+        if (!bus)
+                return -EIO;
+
         polkit_agent_open_if_enabled();
 
         switch (a) {

commit 60f9ba0b94a4a86751d9a8c8b210cf07fc0962ba
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 11 23:59:41 2013 +0100

    systemctl: rework is-active and is-failed code

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index bf76a0e..0def1a2 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1341,20 +1341,25 @@ static int wait_for_jobs(DBusConnection *bus, Set *s) {
         return r;
 }
 
-static int check_one_unit(DBusConnection *bus, char *name, char **check_states, bool quiet) {
-        DBusMessage *reply = NULL;
+static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         DBusMessageIter iter, sub;
         const char
                 *interface = "org.freedesktop.systemd1.Unit",
                 *property = "ActiveState";
-        const char *path = NULL;
-        const char *state;
+        const char *state, *path;
+        _cleanup_free_ char *n = NULL;
+        DBusError error;
         int r;
-        char *n;
 
         assert(name);
 
+        dbus_error_init(&error);
+
         n = unit_name_mangle(name);
+        if (!n)
+                return log_oom();
+
         r = bus_method_call_with_reply (
                         bus,
                         "org.freedesktop.systemd1",
@@ -1362,26 +1367,28 @@ static int check_one_unit(DBusConnection *bus, char *name, char **check_states,
                         "org.freedesktop.systemd1.Manager",
                         "GetUnit",
                         &reply,
-                        NULL,
-                        DBUS_TYPE_STRING, n ? &n : &name,
+                        &error,
+                        DBUS_TYPE_STRING, &n,
                         DBUS_TYPE_INVALID);
-        free(n);
-        if (r) {
-                if ((r != -ENOMEM) && (!quiet))
+        if (r < 0) {
+                dbus_error_free(&error);
+
+                if (!quiet)
                         puts("unknown");
-                goto finish;
+                return 0;
         }
 
         if (!dbus_message_get_args(reply, NULL,
                                    DBUS_TYPE_OBJECT_PATH, &path,
                                    DBUS_TYPE_INVALID)) {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return -EIO;
         }
 
         dbus_message_unref(reply);
-        r = bus_method_call_with_reply (
+        reply = NULL;
+
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         path,
@@ -1392,22 +1399,23 @@ static int check_one_unit(DBusConnection *bus, char *name, char **check_states,
                         DBUS_TYPE_STRING, &interface,
                         DBUS_TYPE_STRING, &property,
                         DBUS_TYPE_INVALID);
-        if (r)
-                goto finish;
+        if (r < 0) {
+                if (!quiet)
+                        puts("unknown");
+                return 0;
+        }
 
         if (!dbus_message_iter_init(reply, &iter) ||
             dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return r;
         }
 
         dbus_message_iter_recurse(&iter, &sub);
 
         if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)  {
                 log_error("Failed to parse reply.");
-                r = -EIO;
-                goto finish;
+                return r;
         }
 
         dbus_message_iter_get_basic(&sub, &state);
@@ -1415,16 +1423,7 @@ static int check_one_unit(DBusConnection *bus, char *name, char **check_states,
         if (!quiet)
                 puts(state);
 
-        if (strv_find(check_states, state))
-                r = 0;
-        else
-                r = 3; /* According to LSB: "program is not running" */
-
-finish:
-        if (reply)
-                dbus_message_unref(reply);
-
-        return r;
+        return strv_find(check_states, state) ? 1 : 0;
 }
 
 static void check_triggering_units(
@@ -1433,7 +1432,6 @@ static void check_triggering_units(
 
         _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         DBusMessageIter iter, sub;
-        char *service_trigger = NULL;
         const char *interface = "org.freedesktop.systemd1.Unit",
                    *triggered_by_property = "TriggeredBy";
 
@@ -1453,7 +1451,7 @@ static void check_triggering_units(
                 return;
         }
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         unit_path,
@@ -1464,7 +1462,7 @@ static void check_triggering_units(
                         DBUS_TYPE_STRING, &interface,
                         DBUS_TYPE_STRING, &triggered_by_property,
                         DBUS_TYPE_INVALID);
-        if (r)
+        if (r < 0)
                 return;
 
         if (!dbus_message_iter_init(reply, &iter) ||
@@ -1478,7 +1476,12 @@ static void check_triggering_units(
         sub = iter;
 
         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                char **check_states = NULL;
+                const char * const check_states[] = {
+                        "active",
+                        "reloading",
+                        NULL
+                };
+                const char *service_trigger;
 
                 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
                         log_error("Failed to parse reply.");
@@ -1487,16 +1490,15 @@ static void check_triggering_units(
 
                 dbus_message_iter_get_basic(&sub, &service_trigger);
 
-                check_states = strv_new("active", "reloading", NULL);
-                r = check_one_unit(bus, service_trigger, check_states, true);
-                strv_free(check_states);
+                r = check_one_unit(bus, service_trigger, (char**) check_states, true);
                 if (r < 0)
                         return;
-                if (r == 0) {
+                if (r > 0) {
                         if (print_warning_label) {
                                 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
                                 print_warning_label = false;
                         }
+
                         log_warning("  %s", service_trigger);
                 }
 
@@ -1930,6 +1932,12 @@ static int start_special(DBusConnection *bus, char **args) {
 }
 
 static int check_unit_active(DBusConnection *bus, char **args) {
+        const char * const check_states[] = {
+                "active",
+                "reloading",
+                NULL
+        };
+
         char **name;
         int r = 3; /* According to LSB: "program is not running" */
 
@@ -1937,12 +1945,12 @@ static int check_unit_active(DBusConnection *bus, char **args) {
         assert(args);
 
         STRV_FOREACH(name, args+1) {
-                char **check_states = strv_new("active", "reloading", NULL);
-                int state = check_one_unit(bus, *name, check_states, arg_quiet);
-                strv_free(check_states);
+                int state;
+
+                state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
                 if (state < 0)
                         return state;
-                if (state == 0)
+                if (state > 0)
                         r = 0;
         }
 
@@ -1950,6 +1958,11 @@ static int check_unit_active(DBusConnection *bus, char **args) {
 }
 
 static int check_unit_failed(DBusConnection *bus, char **args) {
+        const char * const check_states[] = {
+                "failed",
+                NULL
+        };
+
         char **name;
         int r = 1;
 
@@ -1957,12 +1970,12 @@ static int check_unit_failed(DBusConnection *bus, char **args) {
         assert(args);
 
         STRV_FOREACH(name, args+1) {
-                char **check_states = strv_new("failed", NULL);
-                int state = check_one_unit(bus, *name, check_states, arg_quiet);
-                strv_free(check_states);
+                int state;
+
+                state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
                 if (state < 0)
                         return state;
-                if (state == 0)
+                if (state > 0)
                         r = 0;
         }
 
@@ -1970,17 +1983,21 @@ static int check_unit_failed(DBusConnection *bus, char **args) {
 }
 
 static int kill_unit(DBusConnection *bus, char **args) {
+        char **name;
         int r = 0;
-        char **name, *n;
 
+        assert(bus);
         assert(args);
 
         if (!arg_kill_who)
                 arg_kill_who = "all";
 
         STRV_FOREACH(name, args+1) {
+                _cleanup_free_ char *n = NULL;
+
                 n = unit_name_mangle(*name);
-                r = bus_method_call_with_reply (
+
+                r = bus_method_call_with_reply(
                                 bus,
                                 "org.freedesktop.systemd1",
                                 "/org/freedesktop/systemd1",
@@ -1992,8 +2009,7 @@ static int kill_unit(DBusConnection *bus, char **args) {
                                 DBUS_TYPE_STRING, &arg_kill_who,
                                 DBUS_TYPE_INT32, &arg_signal,
                                 DBUS_TYPE_INVALID);
-                free(n);
-                if (r)
+                if (r < 0)
                         return r;
         }
         return 0;
@@ -3446,6 +3462,7 @@ static int set_environment(DBusConnection *bus, char **args) {
         int r;
 
         assert(bus);
+        assert(args);
 
         dbus_error_init(&error);
 

commit 83dd76170d425ea149b74254083b2ce8add18dd8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 11 23:39:23 2013 +0100

    core: fix double free

diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
index d53e77f..52ebfea 100644
--- a/src/core/load-dropin.c
+++ b/src/core/load-dropin.c
@@ -168,7 +168,8 @@ int unit_load_dropin(Unit *u) {
         }
 
         if (!strv_isempty(strv)) {
-                _cleanup_strv_free_ char **files = NULL, **f;
+                _cleanup_strv_free_ char **files = NULL;
+                char **f;
 
                 r = conf_files_list_strv(&files, ".conf", (const char**) strv);
                 if (r < 0) {
@@ -183,6 +184,5 @@ int unit_load_dropin(Unit *u) {
                 }
         }
 
-
         return 0;
 }



More information about the systemd-commits mailing list