[systemd-commits] 7 commits - Makefile.am src/cgroup.c src/cgroup.h src/cgroup-show.c src/cgroup-show.h src/cgroup-util.c src/cgroup-util.h src/dbus.c src/dbus-manager.c src/load-dropin.c src/load-fragment.c src/macro.h src/manager.c src/manager.h src/pam-module.c src/service.c src/systemctl.c src/systemd-cgls.c src/test-cgroup.c src/unit.c src/util.c

Lennart Poettering lennart at kemper.freedesktop.org
Sat Jul 10 15:52:39 PDT 2010


 Makefile.am         |   22 +--
 src/cgroup-show.c   |   48 +++---
 src/cgroup-show.h   |    4 
 src/cgroup-util.c   |  374 ++++++++++++++++++++++++++++++++--------------------
 src/cgroup-util.h   |   12 +
 src/cgroup.c        |  118 ++++++++++------
 src/cgroup.h        |    5 
 src/dbus-manager.c  |    2 
 src/dbus.c          |   24 +--
 src/load-dropin.c   |   12 +
 src/load-fragment.c |    8 -
 src/macro.h         |    6 
 src/manager.c       |  111 +++++++++++----
 src/manager.h       |    3 
 src/pam-module.c    |   28 +--
 src/service.c       |    1 
 src/systemctl.c     |    7 
 src/systemd-cgls.c  |    8 -
 src/test-cgroup.c   |   54 +++----
 src/unit.c          |   14 +
 src/util.c          |    3 
 21 files changed, 546 insertions(+), 318 deletions(-)

New commits:
commit 7740296dcf581bbaaffa74f6f97a97d1def85e12
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jul 11 00:52:28 2010 +0200

    service: fix minor memory leak

diff --git a/src/service.c b/src/service.c
index b837cb8..481c044 100644
--- a/src/service.c
+++ b/src/service.c
@@ -631,6 +631,7 @@ static int service_load_sysv_path(Service *s, const char *path) {
                                         goto finish;
                                 }
 
+                                free(u->meta.description);
                                 u->meta.description = d;
 
                         } else if (startswith_no_case(t, "X-Interactive:")) {
commit 65e92d67b676183dcb3e632198d8f4b04cb04c81
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jul 11 00:52:19 2010 +0200

    manager: free dbus error when ignoring it

diff --git a/src/manager.c b/src/manager.c
index 5125db2..d26541d 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -1343,20 +1343,26 @@ static int transaction_add_job_and_dependencies(
                                         goto fail;
 
                         SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
-                                if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !override, override, e, NULL)) < 0 && r != -EBADR)
-                                        log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, strerror(-r));
+                                if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, !override, override, e, NULL)) < 0 && r != -EBADR) {
+                                        log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
+                                        dbus_error_free(e);
+                                }
 
                         SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_WANTS], i)
-                                if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, false, e, NULL)) < 0)
-                                        log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, strerror(-r));
+                                if ((r = transaction_add_job_and_dependencies(m, JOB_START, dep, ret, false, false, e, NULL)) < 0) {
+                                        log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
+                                        dbus_error_free(e);
+                                }
 
                         SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUISITE], i)
                                 if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, true, override, e, NULL)) < 0 && r != -EBADR)
                                         goto fail;
 
                         SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
-                                if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !override, override, e, NULL)) < 0 && r != -EBADR)
-                                        log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, strerror(-r));
+                                if ((r = transaction_add_job_and_dependencies(m, JOB_VERIFY_ACTIVE, dep, ret, !override, override, e, NULL)) < 0 && r != -EBADR) {
+                                        log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r));
+                                        dbus_error_free(e);
+                                }
 
                         SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_CONFLICTS], i)
                                 if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, dep, ret, true, override, e, NULL)) < 0 && r != -EBADR)
commit fe51822e7120e89566cf76278d0b78ec7db4b43a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jul 11 00:52:00 2010 +0200

    manager: introduce unit path cache to minimize disk accesses

diff --git a/src/load-dropin.c b/src/load-dropin.c
index bdf3dd2..9ba1201 100644
--- a/src/load-dropin.c
+++ b/src/load-dropin.c
@@ -84,7 +84,11 @@ int unit_load_dropin(Unit *u) {
                         if (asprintf(&path, "%s/%s.wants", *p, t) < 0)
                                 return -ENOMEM;
 
-                        r = iterate_dir(u, path);
+                        if (u->meta.manager->unit_path_cache &&
+                            !set_get(u->meta.manager->unit_path_cache, path))
+                                r = 0;
+                        else
+                                r = iterate_dir(u, path);
                         free(path);
 
                         if (r < 0)
@@ -103,7 +107,11 @@ int unit_load_dropin(Unit *u) {
                                 if (r < 0)
                                         return -ENOMEM;
 
-                                r = iterate_dir(u, path);
+                                if (u->meta.manager->unit_path_cache &&
+                                    !set_get(u->meta.manager->unit_path_cache, path))
+                                        r = 0;
+                                else
+                                        r = iterate_dir(u, path);
                                 free(path);
 
                                 if (r < 0)
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 6a71d42..394aa02 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -1690,7 +1690,13 @@ static int load_from_path(Unit *u, const char *path) {
                                 goto finish;
                         }
 
-                        if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
+                        if (u->meta.manager->unit_path_cache &&
+                            !set_get(u->meta.manager->unit_path_cache, filename))
+                                r = -ENOENT;
+                        else
+                                r = open_follow(&filename, &f, symlink_names, &id);
+
+                        if (r < 0) {
                                 char *sn;
 
                                 free(filename);
diff --git a/src/manager.c b/src/manager.c
index a7e24eb..5125db2 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -36,6 +36,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <dirent.h>
 
 #include "manager.h"
 #include "hashmap.h"
@@ -478,11 +479,71 @@ int manager_coldplug(Manager *m) {
         return r;
 }
 
+static void manager_build_unit_path_cache(Manager *m) {
+        char **i;
+        DIR *d = NULL;
+        int r;
+
+        assert(m);
+
+        set_free_free(m->unit_path_cache);
+
+        if (!(m->unit_path_cache = set_new(string_hash_func, string_compare_func))) {
+                log_error("Failed to allocate unit path cache.");
+                return;
+        }
+
+        /* This simply builds a list of files we know exist, so that
+         * we don't always have to go to disk */
+
+        STRV_FOREACH(i, m->lookup_paths.unit_path) {
+                struct dirent *de;
+
+                if (!(d = opendir(*i))) {
+                        log_error("Failed to open directory: %m");
+                        continue;
+                }
+
+                while ((de = readdir(d))) {
+                        char *p;
+
+                        if (ignore_file(de->d_name))
+                                continue;
+
+                        if (asprintf(&p, "%s/%s", streq(*i, "/") ? "" : *i, de->d_name) < 0) {
+                                r = -ENOMEM;
+                                goto fail;
+                        }
+
+                        if ((r = set_put(m->unit_path_cache, p)) < 0) {
+                                free(p);
+                                goto fail;
+                        }
+                }
+
+                closedir(d);
+                d = NULL;
+        }
+
+        return;
+
+fail:
+        log_error("Failed to build unit path cache: %s", strerror(-r));
+
+        set_free_free(m->unit_path_cache);
+        m->unit_path_cache = NULL;
+
+        if (d)
+                closedir(d);
+}
+
 int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
         int r, q;
 
         assert(m);
 
+        manager_build_unit_path_cache(m);
+
         /* First, enumerate what we can from all config files */
         r = manager_enumerate(m);
 
@@ -1993,6 +2054,10 @@ int manager_loop(Manager *m) {
         assert(m);
         m->exit_code = MANAGER_RUNNING;
 
+        /* Release the path cache */
+        set_free_free(m->unit_path_cache);
+        m->unit_path_cache = NULL;
+
         /* There might still be some zombies hanging around from
          * before we were exec()'ed. Leat's reap them */
         if ((r = manager_dispatch_sigchld(m)) < 0)
diff --git a/src/manager.h b/src/manager.h
index f3bf96e..0eceab9 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -134,6 +134,7 @@ struct Manager {
         unsigned n_snapshots;
 
         LookupPaths lookup_paths;
+        Set *unit_path_cache;
 
         char **environment;
 
commit 9014a8bd7a88aa4794b730e7fccf7838a00ad351
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jul 11 00:51:28 2010 +0200

    dbus: suppress duplicate message when reusing bus for system and session

diff --git a/src/dbus.c b/src/dbus.c
index 7f8b6a0..0b93db5 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -758,7 +758,6 @@ static void bus_new_connection(
 
 static int bus_init_system(Manager *m) {
         DBusError error;
-        char *id;
         int r;
 
         assert(m);
@@ -800,10 +799,13 @@ static int bus_init_system(Manager *m) {
                 goto fail;
         }
 
-        log_info("Successfully connected to system D-Bus bus %s as %s",
-                 strnull((id = dbus_connection_get_server_id(m->system_bus))),
-                 strnull(dbus_bus_get_unique_name(m->system_bus)));
-        dbus_free(id);
+        if (m->api_bus != m->system_bus) {
+                char *id;
+                log_info("Successfully connected to system D-Bus bus %s as %s",
+                         strnull((id = dbus_connection_get_server_id(m->system_bus))),
+                         strnull(dbus_bus_get_unique_name(m->system_bus)));
+                dbus_free(id);
+        }
 
         return 0;
 
@@ -816,7 +818,6 @@ fail:
 
 static int bus_init_api(Manager *m) {
         DBusError error;
-        char *id;
         int r;
 
         assert(m);
@@ -884,10 +885,13 @@ static int bus_init_api(Manager *m) {
         if ((r = query_name_list(m)) < 0)
                 goto fail;
 
-        log_info("Successfully connected to API D-Bus bus %s as %s",
-                 strnull((id = dbus_connection_get_server_id(m->api_bus))),
-                 strnull(dbus_bus_get_unique_name(m->api_bus)));
-        dbus_free(id);
+        if (m->api_bus != m->system_bus) {
+                char *id;
+                log_info("Successfully connected to API D-Bus bus %s as %s",
+                         strnull((id = dbus_connection_get_server_id(m->api_bus))),
+                         strnull(dbus_bus_get_unique_name(m->api_bus)));
+                dbus_free(id);
+        }
 
         return 0;
 
commit c6c18be35bb1d300d0b62a568783cc1c477f7151
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jul 11 00:50:49 2010 +0200

    cgroup: kill processes, not tasks and other cgroup changes

diff --git a/Makefile.am b/Makefile.am
index 57b8aa5..422d37e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -483,15 +483,18 @@ systemctl_SOURCES = \
 	src/systemctl.c \
 	src/utmp-wtmp.c \
 	src/dbus-common.c \
-	src/cgroup-show.c
+	src/cgroup-show.c \
+	src/cgroup-util.c
 
 systemctl_CFLAGS = \
 	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
+	$(DBUS_CFLAGS) \
+	$(CGROUP_CLAGS)
 
 systemctl_LDADD = \
 	libsystemd-basic.la \
-	$(DBUS_LIBS)
+	$(DBUS_LIBS) \
+	$(CGROUP_LIBS)
 
 systemd_notify_SOURCES = \
 	src/notify.c \
@@ -516,13 +519,16 @@ systemd_install_CFLAGS = \
 
 systemd_cgls_SOURCES = \
 	src/systemd-cgls.c \
-	src/cgroup-show.c
-
-systemd_cgls_LDADD = \
-	libsystemd-basic.la
+	src/cgroup-show.c \
+	src/cgroup-util.c
 
 systemd_cgls_CFLAGS = \
-	$(AM_CFLAGS)
+	$(AM_CFLAGS) \
+	$(CGROUP_CLAGS)
+
+systemd_cgls_LDADD = \
+	libsystemd-basic.la \
+	$(CGROUP_LIBS)
 
 systemadm_SOURCES = \
 	src/systemadm.vala \
diff --git a/src/cgroup-show.c b/src/cgroup-show.c
index 44efa1a..17183ce 100644
--- a/src/cgroup-show.c
+++ b/src/cgroup-show.c
@@ -26,6 +26,7 @@
 
 #include "util.h"
 #include "macro.h"
+#include "cgroup-util.h"
 #include "cgroup-show.h"
 
 static int compare(const void *a, const void *b) {
@@ -40,8 +41,11 @@ static int compare(const void *a, const void *b) {
 
 static char *get_cgroup_path(const char *name) {
 
-        if (startswith(name, "name=systemd:"))
-                name += 13;
+        if (!name)
+                return strdup("/cgroup/systemd");
+
+        if (startswith(name, SYSTEMD_CGROUP_CONTROLLER ":"))
+                name += sizeof(SYSTEMD_CGROUP_CONTROLLER);
 
         if (path_startswith(name, "/cgroup"))
                 return strdup(name);
@@ -60,14 +64,14 @@ static unsigned ilog10(unsigned long ul) {
         return n;
 }
 
-static int show_cgroup_full(const char *name, const char *prefix, unsigned n_columns, bool more) {
+static int show_cgroup_full(const char *path, const char *prefix, unsigned n_columns, bool more) {
         char *fn;
         FILE *f;
         size_t n = 0, n_allocated = 0;
         pid_t *pids = NULL;
         char *p;
+        pid_t pid, biggest = 0;
         int r;
-        unsigned long biggest = 0;
 
         if (n_columns <= 0)
                 n_columns = columns();
@@ -75,7 +79,7 @@ static int show_cgroup_full(const char *name, const char *prefix, unsigned n_col
         if (!prefix)
                 prefix = "";
 
-        if (!(p = get_cgroup_path(name)))
+        if (!(p = get_cgroup_path(path)))
                 return -ENOMEM;
 
         r = asprintf(&fn, "%s/cgroup.procs", p);
@@ -90,14 +94,7 @@ static int show_cgroup_full(const char *name, const char *prefix, unsigned n_col
         if (!f)
                 return -errno;
 
-        while (!feof(f)) {
-                unsigned long ul;
-
-                if (fscanf(f, "%lu", &ul) != 1)
-                        break;
-
-                if (ul <= 0)
-                        continue;
+        while ((r = cg_read_pid(f, &pid)) > 0) {
 
                 if (n >= n_allocated) {
                         pid_t *npids;
@@ -113,12 +110,15 @@ static int show_cgroup_full(const char *name, const char *prefix, unsigned n_col
                 }
 
                 assert(n < n_allocated);
-                pids[n++] = (pid_t) ul;
+                pids[n++] = pid;
 
-                if (ul > biggest)
-                        biggest = ul;
+                if (pid > biggest)
+                        biggest = pid;
         }
 
+        if (r < 0)
+                goto finish;
+
         if (n > 0) {
                 unsigned i, m;
 
@@ -171,11 +171,11 @@ finish:
         return r;
 }
 
-int show_cgroup(const char *name, const char *prefix, unsigned n_columns) {
-        return show_cgroup_full(name, prefix, n_columns, false);
+int show_cgroup(const char *path, const char *prefix, unsigned n_columns) {
+        return show_cgroup_full(path, prefix, n_columns, false);
 }
 
-int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_columns) {
+int show_cgroup_recursive(const char *path, const char *prefix, unsigned n_columns) {
         DIR *d;
         char *last = NULL;
         char *p1 = NULL, *p2 = NULL, *fn = NULL;
@@ -183,15 +183,13 @@ int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_colum
         bool shown_pids = false;
         int r;
 
-        assert(name);
-
         if (n_columns <= 0)
                 n_columns = columns();
 
         if (!prefix)
                 prefix = "";
 
-        if (!(fn = get_cgroup_path(name)))
+        if (!(fn = get_cgroup_path(path)))
                 return -ENOMEM;
 
         if (!(d = opendir(fn))) {
@@ -208,7 +206,7 @@ int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_colum
                         continue;
 
                 if (!shown_pids) {
-                        show_cgroup_full(name, prefix, n_columns, true);
+                        show_cgroup_full(path, prefix, n_columns, true);
                         shown_pids = true;
                 }
 
@@ -227,14 +225,14 @@ int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_colum
                         last = NULL;
                 }
 
-                if (asprintf(&last, "%s/%s", name, de->d_name) < 0) {
+                if (asprintf(&last, "%s/%s", strempty(path), de->d_name) < 0) {
                         r = -ENOMEM;
                         goto finish;
                 }
         }
 
         if (!shown_pids)
-                show_cgroup_full(name, prefix, n_columns, !!last);
+                show_cgroup_full(path, prefix, n_columns, !!last);
 
         if (last) {
                 printf("%s\342\224\224 %s\n", prefix, file_name_from_path(last));
diff --git a/src/cgroup-show.h b/src/cgroup-show.h
index 1f0c319..09a436a 100644
--- a/src/cgroup-show.h
+++ b/src/cgroup-show.h
@@ -22,7 +22,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-int show_cgroup(const char *name, const char *prefix, unsigned columns);
-int show_cgroup_recursive(const char *name, const char *prefix, unsigned columns);
+int show_cgroup(const char *path, const char *prefix, unsigned columns);
+int show_cgroup_recursive(const char *path, const char *prefix, unsigned columns);
 
 #endif
diff --git a/src/cgroup-util.c b/src/cgroup-util.c
index 002c131..0b8678c 100644
--- a/src/cgroup-util.c
+++ b/src/cgroup-util.c
@@ -33,6 +33,15 @@
 #include "macro.h"
 #include "util.h"
 
+/*
+   Currently, the only remaining functionality from libcgroup we call
+   here is:
+
+   - cgroup_get_subsys_mount_point()
+   - cgroup_walk_tree_begin()/cgroup_walk_tree_next()
+   - cgroup_delete_cgroup_ext()
+ */
+
 int cg_translate_error(int error, int _errno) {
 
         switch (error) {
@@ -73,11 +82,78 @@ static struct cgroup* cg_new(const char *controller, const char *path) {
         return cgroup;
 }
 
+int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
+        char *fs;
+        int r;
+        FILE *f;
+
+        assert(controller);
+        assert(path);
+        assert(_f);
+
+        if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 0)
+                return r;
+
+        f = fopen(fs, "re");
+        free(fs);
+
+        if (!f)
+                return -errno;
+
+        *_f = f;
+        return 0;
+}
+
+int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
+        char *fs;
+        int r;
+        FILE *f;
+
+        assert(controller);
+        assert(path);
+        assert(_f);
+
+        if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
+                return r;
+
+        f = fopen(fs, "re");
+        free(fs);
+
+        if (!f)
+                return -errno;
+
+        *_f = f;
+        return 0;
+}
+
+int cg_read_pid(FILE *f, pid_t *_pid) {
+        unsigned long ul;
+
+        /* Note that the cgroup.procs might contain duplicates! See
+         * cgroups.txt for details. */
+
+        errno = 0;
+        if (fscanf(f, "%lu", &ul) != 1) {
+
+                if (feof(f))
+                        return 0;
+
+                return errno ? -errno : -EIO;
+        }
+
+        if (ul <= 0)
+                return -EIO;
+
+        *_pid = (pid_t) ul;
+        return 1;
+}
+
 int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) {
         bool killed = false, done = false;
         Set *s;
         pid_t my_pid;
         int r, ret = 0;
+        FILE *f = NULL;
 
         assert(controller);
         assert(path);
@@ -93,23 +169,22 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self)
         my_pid = getpid();
 
         do {
-                void *iterator = NULL;
-                pid_t pid = 0;
-
+                pid_t pid;
                 done = true;
 
-                r = cgroup_get_task_begin(path, controller, &iterator, &pid);
-                while (r == 0) {
+                if ((r = cg_enumerate_processes(controller, path, &f)) < 0)
+                        goto finish;
+
+                while ((r = cg_read_pid(f, &pid)) > 0) {
 
                         if (pid == my_pid && ignore_self)
-                                goto next;
+                                continue;
 
-                        if (set_get(s, INT_TO_PTR(pid)) == INT_TO_PTR(pid))
-                                goto next;
+                        if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
+                                continue;
 
                         /* If we haven't killed this process yet, kill
                          * it */
-
                         if (kill(pid, sig) < 0 && errno != ESRCH) {
                                 if (ret == 0)
                                         ret = -errno;
@@ -118,22 +193,12 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self)
                         killed = true;
                         done = false;
 
-                        if ((r = set_put(s, INT_TO_PTR(pid))) < 0)
-                                goto loop_exit;
-
-                next:
-                        r = cgroup_get_task_next(&iterator, &pid);
+                        if ((r = set_put(s, LONG_TO_PTR(pid))) < 0)
+                                break;
                 }
 
-                if (r == 0 || r == ECGEOF)
-                        r = 0;
-                else if (r == ECGOTHER && errno == ENOENT)
-                        r = -ESRCH;
-                else
-                        r = cg_translate_error(r, errno);
-
-        loop_exit:
-                assert_se(cgroup_get_task_end(&iterator) == 0);
+                fclose(f);
+                f = NULL;
 
                 /* To avoid racing against processes which fork
                  * quicker than we can kill them we repeat this until
@@ -141,14 +206,18 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self)
 
         } while (!done && r >= 0);
 
+finish:
         set_free(s);
 
-        if (ret < 0)
-                return ret;
+        if (f)
+                fclose(f);
 
         if (r < 0)
                 return r;
 
+        if (ret < 0)
+                return ret;
+
         return !!killed;
 }
 
@@ -237,63 +306,53 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path) {
 
 int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
         bool migrated = false, done = false;
-        struct cgroup *dest;
         int r, ret = 0;
         pid_t my_pid;
+        FILE *f = NULL;
 
         assert(controller);
         assert(from);
         assert(to);
 
-        if (!(dest = cg_new(controller, to)))
-                return -ENOMEM;
-
         my_pid = getpid();
 
         do {
-                void *iterator = NULL;
-                pid_t pid = 0;
-
+                pid_t pid;
                 done = true;
 
-                r = cgroup_get_task_begin(from, controller, &iterator, &pid);
-                while (r == 0) {
+                if ((r = cg_enumerate_tasks(controller, from, &f)) < 0)
+                        goto finish;
+
+                while ((r = cg_read_pid(f, &pid)) > 0) {
 
                         if (pid == my_pid && ignore_self)
-                                goto next;
+                                continue;
 
-                        if ((r = cgroup_attach_task_pid(dest, pid)) != 0) {
+                        if ((r = cg_attach(controller, to, pid)) < 0) {
                                 if (ret == 0)
-                                        r = cg_translate_error(r, errno);
+                                        ret = -r;
                         }
 
                         migrated = true;
                         done = false;
-
-                next:
-
-                        r = cgroup_get_task_next(&iterator, &pid);
                 }
 
-                if (r == 0 || r == ECGEOF)
-                        r = 0;
-                else if (r == ECGOTHER && errno == ENOENT)
-                        r = -ESRCH;
-                else
-                        r = cg_translate_error(r, errno);
-
-                assert_se(cgroup_get_task_end(&iterator) == 0);
+                fclose(f);
+                f = NULL;
 
         } while (!done && r >= 0);
 
-        cgroup_free(&dest);
+finish:
 
-        if (ret < 0)
-                return ret;
+        if (f)
+                fclose(f);
 
         if (r < 0)
                 return r;
 
+        if (ret < 0)
+                return ret;
+
         return !!migrated;
 }
 
@@ -354,18 +413,24 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch
         int r;
 
         assert(controller);
-        assert(path);
 
         if ((r = cgroup_get_subsys_mount_point(controller, &mp)) != 0)
                 return cg_translate_error(r, errno);
 
-        if (suffix)
+        if (path && suffix)
                 r = asprintf(fs, "%s/%s/%s", mp, path, suffix);
-        else
+        else if (path)
                 r = asprintf(fs, "%s/%s", mp, path);
+        else if (suffix)
+                r = asprintf(fs, "%s/%s", mp, suffix);
+        else {
+                path_kill_slashes(mp);
+                *fs = mp;
+                return 0;
+        }
 
         free(mp);
-
+        path_kill_slashes(*fs);
         return r < 0 ? -ENOMEM : 0;
 }
 
@@ -409,83 +474,59 @@ finish:
 }
 
 int cg_create(const char *controller, const char *path) {
-        struct cgroup *cg;
+        char *fs;
         int r;
 
         assert(controller);
         assert(path);
 
-        if (!(cg = cg_new(controller, path)))
-                return -ENOMEM;
-
-        if ((r = cgroup_create_cgroup(cg, 1)) != 0) {
-                r = cg_translate_error(r, errno);
-                goto finish;
-        }
-
-        r = 0;
+        if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
+                return r;
 
-finish:
-        cgroup_free(&cg);
+        r = mkdir_p(fs, 0755);
+        free(fs);
 
         return r;
 }
 
 int cg_attach(const char *controller, const char *path, pid_t pid) {
-        struct cgroup *cg;
+        char *fs;
         int r;
+        char c[32];
 
         assert(controller);
         assert(path);
         assert(pid >= 0);
 
-        if (!(cg = cg_new(controller, path)))
-                return -ENOMEM;
+        if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
+                return r;
 
         if (pid == 0)
                 pid = getpid();
 
-        if ((r = cgroup_attach_task_pid(cg, pid))) {
-                r = cg_translate_error(r, errno);
-                goto finish;
-        }
-
-        r = 0;
+        snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
+        char_array_0(c);
 
-finish:
-        cgroup_free(&cg);
+        r = write_one_line_file(fs, c);
+        free(fs);
 
         return r;
 }
 
 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
-        struct cgroup *cg;
         int r;
 
         assert(controller);
         assert(path);
         assert(pid >= 0);
 
-        if (!(cg = cg_new(controller, path)))
-                return -ENOMEM;
-
-        if ((r = cgroup_create_cgroup(cg, 1)) != 0) {
-                r = cg_translate_error(r, errno);
-                goto finish;
-        }
-
-        if (pid == 0)
-                pid = getpid();
-
-        if ((r = cgroup_attach_task_pid(cg, pid))) {
-                r = cg_translate_error(r, errno);
-                goto finish;
-        }
+        if ((r = cg_create(controller, path)) < 0)
+                return r;
 
-        r = 0;
+        if ((r = cg_attach(controller, path, pid)) < 0)
+                return r;
 
-finish:
-        cgroup_free(&cg);
+        /* This does not remove the cgroup on failure */
 
         return r;
 }
@@ -525,40 +566,82 @@ int cg_set_task_access(const char *controller, const char *path, mode_t mode, ui
 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
         int r;
         char *p = NULL;
+        FILE *f;
+        char *fs;
+        size_t cs;
 
         assert(controller);
-        assert(pid > 0);
         assert(path);
+        assert(pid >= 0);
 
-        if ((r = cgroup_get_current_controller_path(pid, controller, &p)) != 0)
-                return cg_translate_error(r, errno);
+        if (pid == 0)
+                pid = getpid();
 
-        assert(p);
+        if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
+                return -ENOMEM;
 
-        *path = p;
-        return 0;
+        f = fopen(fs, "re");
+        free(fs);
+
+        cs = strlen(controller);
+
+        while (!feof(f)) {
+                char line[LINE_MAX];
+                char *l;
+
+                errno = 0;
+                if (!(fgets(line, sizeof(line), f))) {
+                        if (feof(f))
+                                break;
+
+                        r = errno ? -errno : -EIO;
+                        goto finish;
+                }
+
+                truncate_nl(line);
+
+                if (!(l = strchr(line, ':')))
+                        continue;
+
+                l++;
+                if (strncmp(l, controller, cs) != 0)
+                        continue;
+
+                if (l[cs] != ':')
+                        continue;
+
+                if (!(p = strdup(l + cs + 1))) {
+                        r = -ENOMEM;
+                        goto finish;
+                }
+
+                *path = p;
+                r = 0;
+                goto finish;
+        }
+
+        r = -ENOENT;
+
+finish:
+        fclose(f);
+
+        return r;
 }
 
 int cg_install_release_agent(const char *controller, const char *agent) {
-        char *mp = NULL, *path = NULL, *contents = NULL, *line = NULL, *sc;
+        char *fs = NULL, *contents = NULL, *line = NULL, *sc;
         int r;
 
         assert(controller);
         assert(agent);
 
-        if ((r = cgroup_get_subsys_mount_point(controller, &mp)) != 0)
-                return cg_translate_error(r, errno);
-
-        if (asprintf(&path, "%s/release_agent", mp) < 0) {
-                r = -ENOMEM;
-                goto finish;
-        }
+        if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
+                return r;
 
-        if ((r = read_one_line_file(path, &contents)) < 0)
+        if ((r = read_one_line_file(fs, &contents)) < 0)
                 goto finish;
 
         sc = strstrip(contents);
-
         if (sc[0] == 0) {
 
                 if (asprintf(&line, "%s\n", agent) < 0) {
@@ -566,7 +649,7 @@ int cg_install_release_agent(const char *controller, const char *agent) {
                         goto finish;
                 }
 
-                if ((r = write_one_line_file(path, line)) < 0)
+                if ((r = write_one_line_file(fs, line)) < 0)
                         goto finish;
 
         } else if (!streq(sc, agent)) {
@@ -574,33 +657,33 @@ int cg_install_release_agent(const char *controller, const char *agent) {
                 goto finish;
         }
 
-        free(path);
-        path = NULL;
-        if (asprintf(&path, "%s/notify_on_release", mp) < 0) {
+        free(fs);
+        fs = NULL;
+        if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0) {
                 r = -ENOMEM;
                 goto finish;
         }
 
         free(contents);
         contents = NULL;
-        if ((r = read_one_line_file(path, &contents)) < 0)
+        if ((r = read_one_line_file(fs, &contents)) < 0)
                 goto finish;
 
         sc = strstrip(contents);
 
         if (streq(sc, "0")) {
-                if ((r = write_one_line_file(path, "1\n")) < 0)
+                if ((r = write_one_line_file(fs, "1\n")) < 0)
                         goto finish;
+
+                r = 1;
         } else if (!streq(sc, "1")) {
                 r = -EIO;
                 goto finish;
-        }
-
-        r = 0;
+        } else
+                r = 0;
 
 finish:
-        free(mp);
-        free(path);
+        free(fs);
         free(contents);
         free(line);
 
@@ -608,36 +691,32 @@ finish:
 }
 
 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
-        void *iterator = NULL;
-        pid_t pid = 0;
+        pid_t pid;
         int r;
+        FILE *f;
+        bool found = false;
 
         assert(controller);
         assert(path);
 
-        r = cgroup_get_task_begin(path, controller, &iterator, &pid);
-        while (r == 0) {
+        if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
+                return r;
 
-                if (ignore_self&& pid == getpid())
-                        goto next;
+        while ((r = cg_read_pid(f, &pid)) > 0) {
 
-                break;
+                if (ignore_self && pid == getpid())
+                        continue;
 
-        next:
-                r = cgroup_get_task_next(&iterator, &pid);
+                found = true;
+                break;
         }
 
+        fclose(f);
 
-        if (r == ECGEOF)
-                r = 1;
-        else if (r != 0)
-                r = cg_translate_error(r, errno);
-        else
-                r = 0;
-
-        assert_se(cgroup_get_task_end(&iterator) == 0);
+        if (r < 0)
+                return r;
 
-        return r;
+        return !found;
 }
 
 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
@@ -692,3 +771,12 @@ int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_
 
         return ret;
 }
+
+int cg_init(void) {
+        int r;
+
+        if ((r = cgroup_init()) != 0)
+                return cg_translate_error(r, errno);
+
+        return 0;
+}
diff --git a/src/cgroup-util.h b/src/cgroup-util.h
index 4ada71b..716c635 100644
--- a/src/cgroup-util.h
+++ b/src/cgroup-util.h
@@ -23,9 +23,19 @@
 ***/
 
 #include <sys/types.h>
+#include <stdio.h>
+
+#include "set.h"
+
+#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
 
 int cg_translate_error(int error, int _errno);
 
+int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
+int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f);
+
+int cg_read_pid(FILE *f, pid_t *_pid);
+
 int cg_kill(const char *controller, const char *path, int sig, bool ignore_self);
 int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self);
 int cg_kill_recursive_and_wait(const char *controller, const char *path);
@@ -51,4 +61,6 @@ int cg_install_release_agent(const char *controller, const char *agent);
 int cg_is_empty(const char *controller, const char *path, bool ignore_self);
 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self);
 
+int cg_init(void);
+
 #endif
diff --git a/src/cgroup.c b/src/cgroup.c
index 83fe2ef..7397b52 100644
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -25,8 +25,7 @@
 #include <sys/types.h>
 #include <signal.h>
 #include <sys/mount.h>
-
-#include <libcgroup.h>
+#include <fcntl.h>
 
 #include "cgroup.h"
 #include "cgroup-util.h"
@@ -210,71 +209,91 @@ int cgroup_bonding_is_empty_list(CGroupBonding *first) {
 }
 
 int manager_setup_cgroup(Manager *m) {
-        char *cp;
+        char *current = NULL, *path = NULL;
         int r;
-        pid_t pid;
         char suffix[32];
 
         assert(m);
 
-        if ((r = cgroup_init()) != 0) {
-                log_error("Failed to initialize libcg: %s", cgroup_strerror(r));
-                return cg_translate_error(r, errno);
+        /* 1. Initialize libcg */
+        if ((r = cg_init()) < 0) {
+                log_error("Failed to initialize libcg: %s", strerror(-r));
+                goto finish;
         }
 
-        free(m->cgroup_mount_point);
-        m->cgroup_mount_point = NULL;
-        if ((r = cgroup_get_subsys_mount_point(SYSTEMD_CGROUP_CONTROLLER, &m->cgroup_mount_point)))
-                return cg_translate_error(r, errno);
-
-        pid = getpid();
-
-        if ((r = cgroup_get_current_controller_path(pid, SYSTEMD_CGROUP_CONTROLLER, &cp)))
-                return cg_translate_error(r, errno);
+        /* 2. Determine hierarchy */
+        if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current)) < 0)
+                goto finish;
 
-        snprintf(suffix, sizeof(suffix), "/systemd-%u", (unsigned) pid);
+        snprintf(suffix, sizeof(suffix), "/systemd-%lu", (unsigned long) getpid());
         char_array_0(suffix);
 
         free(m->cgroup_hierarchy);
-
-        if (endswith(cp, suffix))
+        if (endswith(current, suffix)) {
                 /* We probably got reexecuted and can continue to use our root cgroup */
-                m->cgroup_hierarchy = cp;
-        else {
-                /* We need a new root cgroup */
+                m->cgroup_hierarchy = current;
+                current = NULL;
 
+        } else {
+                /* We need a new root cgroup */
                 m->cgroup_hierarchy = NULL;
-                r = asprintf(&m->cgroup_hierarchy, "%s%s", streq(cp, "/") ? "" : cp, suffix);
-                free(cp);
-
-                if (r < 0)
-                        return -ENOMEM;
+                if ((r = asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix)) < 0) {
+                        r = -ENOMEM;
+                        goto finish;
+                }
         }
 
-        log_debug("Using cgroup controller <" SYSTEMD_CGROUP_CONTROLLER ">, hierarchy mounted at <%s>, using root group <%s>.",
-                  m->cgroup_mount_point,
-                  m->cgroup_hierarchy);
+        /* 3. Show data */
+        if ((r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, NULL, &path)) < 0)
+                goto finish;
 
+        log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
+
+        /* 4. Install agent */
         if ((r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, CGROUP_AGENT_PATH)) < 0)
                 log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
+        else if (r > 0)
+                log_debug("Installed release agent.");
         else
-                log_debug("Installed release agent, or already installed.");
+                log_debug("Release agent already installed.");
 
-        if ((r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0)) < 0)
+        /* 5. Realize the group */
+        if ((r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0)) < 0) {
                 log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
-        else
-                log_debug("Created root group.");
+                goto finish;
+        }
+
+        /* 6. And pin it, so that it cannot be unmounted */
+        if (m->pin_cgroupfs_fd >= 0)
+                close_nointr_nofail(m->pin_cgroupfs_fd);
+
+        if ((m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK)) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        log_debug("Created root group.");
+
+finish:
+        free(current);
+        free(path);
 
         return r;
 }
 
-int manager_shutdown_cgroup(Manager *m) {
+void manager_shutdown_cgroup(Manager *m, bool delete) {
         assert(m);
 
-        if (!m->cgroup_hierarchy)
-                return 0;
+        if (delete && m->cgroup_hierarchy)
+                cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
 
-        return cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
+        if (m->pin_cgroupfs_fd >= 0) {
+                close_nointr_nofail(m->pin_cgroupfs_fd);
+                m->pin_cgroupfs_fd = -1;
+        }
+
+        free(m->cgroup_hierarchy);
+        m->cgroup_hierarchy = NULL;
 }
 
 int cgroup_notify_empty(Manager *m, const char *group) {
diff --git a/src/cgroup.h b/src/cgroup.h
index a7ca8ab..45d0439 100644
--- a/src/cgroup.h
+++ b/src/cgroup.h
@@ -26,8 +26,6 @@ typedef struct CGroupBonding CGroupBonding;
 
 #include "unit.h"
 
-#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
-
 /* Binds a cgroup to a name */
 struct CGroupBonding {
         char *controller;
@@ -76,7 +74,7 @@ char *cgroup_bonding_to_string(CGroupBonding *b);
 #include "manager.h"
 
 int manager_setup_cgroup(Manager *m);
-int manager_shutdown_cgroup(Manager *m);
+void manager_shutdown_cgroup(Manager *m, bool delete);
 
 int cgroup_notify_empty(Manager *m, const char *group);
 
diff --git a/src/dbus-manager.c b/src/dbus-manager.c
index 5daccb1..f52b06e 100644
--- a/src/dbus-manager.c
+++ b/src/dbus-manager.c
@@ -121,6 +121,7 @@
         "  <property name=\"SysVInitPath\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"SysVRcndPath\" type=\"as\" access=\"read\"/>\n" \
         "  <property name=\"NotifySocket\" type=\"s\" access=\"read\"/>\n" \
+        "  <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
         " </interface>\n"
 
 #define INTROSPECTION_BEGIN                                             \
@@ -229,6 +230,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
                 { "org.freedesktop.systemd1.Manager", "SysVInitPath",  bus_property_append_strv,      "as", m->lookup_paths.sysvinit_path },
                 { "org.freedesktop.systemd1.Manager", "SysVRcndPath",  bus_property_append_strv,      "as", m->lookup_paths.sysvrcnd_path },
                 { "org.freedesktop.systemd1.Manager", "NotifySocket",  bus_property_append_string,    "s",  m->notify_socket   },
+                { "org.freedesktop.systemd1.Manager", "ControlGroupHierarchy", bus_property_append_string, "s", m->cgroup_hierarchy },
                 { NULL, NULL, NULL, NULL, NULL }
         };
 
diff --git a/src/macro.h b/src/macro.h
index d00e70b..7bd57b3 100644
--- a/src/macro.h
+++ b/src/macro.h
@@ -108,12 +108,18 @@ static inline size_t ALIGN(size_t l) {
 #define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
 #define UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
 
+#define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
+#define ULONG_TO_PTR(u) ((void*) ((uintptr_t) (u)))
+
 #define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
 #define INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
 
 #define TO_INT32(p) ((int32_t) ((intptr_t) (p)))
 #define INT32_TO_PTR(u) ((void*) ((intptr_t) (u)))
 
+#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
+#define LONG_TO_PTR(u) ((void*) ((intptr_t) (u)))
+
 #define memzero(x,l) (memset((x), 0, (l)))
 #define zero(x) (memzero(&(x), sizeof(x)))
 
diff --git a/src/manager.c b/src/manager.c
index 8d016b9..a7e24eb 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -186,7 +186,6 @@ static int manager_setup_signals(Manager *m) {
 int manager_new(ManagerRunningAs running_as, Manager **_m) {
         Manager *m;
         int r = -ENOMEM;
-        char *p;
 
         assert(_m);
         assert(running_as >= 0);
@@ -245,14 +244,6 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) {
         if ((r = bus_init(m)) < 0)
                 goto fail;
 
-        if (asprintf(&p, "%s/%s", m->cgroup_mount_point, m->cgroup_hierarchy) < 0) {
-                r = -ENOMEM;
-                goto fail;
-        }
-
-        m->pin_cgroupfs_fd = open(p, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
-        free(p);
-
         *_m = m;
         return 0;
 
@@ -420,8 +411,7 @@ void manager_free(Manager *m) {
 
         /* If we reexecute ourselves, we keep the root cgroup
          * around */
-        if (m->exit_code != MANAGER_REEXECUTE)
-                manager_shutdown_cgroup(m);
+        manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
 
         bus_done(m);
 
@@ -443,13 +433,8 @@ void manager_free(Manager *m) {
         lookup_paths_free(&m->lookup_paths);
         strv_free(m->environment);
 
-        free(m->cgroup_hierarchy);
-        free(m->cgroup_mount_point);
-
         hashmap_free(m->cgroup_bondings);
-
-        if (m->pin_cgroupfs_fd >= 0)
-                close_nointr_nofail(m->pin_cgroupfs_fd);
+        set_free_free(m->unit_path_cache);
 
         free(m);
 }
@@ -1664,7 +1649,7 @@ static int manager_process_notify_fd(Manager *m) {
 
                 ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
 
-                if (!(u = hashmap_get(m->watch_pids, UINT32_TO_PTR(ucred->pid))))
+                if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid))))
                         if (!(u = cgroup_unit_by_pid(m, ucred->pid))) {
                                 log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
                                 continue;
@@ -1729,7 +1714,7 @@ static int manager_dispatch_sigchld(Manager *m) {
                         return r;
 
                 /* And now figure out the unit this belongs to */
-                if (!(u = hashmap_get(m->watch_pids, UINT32_TO_PTR(si.si_pid))))
+                if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid))))
                         u = cgroup_unit_by_pid(m, si.si_pid);
 
                 /* And now, we actually reap the zombie. */
@@ -1752,9 +1737,9 @@ static int manager_dispatch_sigchld(Manager *m) {
                 if (!u)
                         continue;
 
-                log_debug("Child %llu belongs to %s", (long long unsigned) si.si_pid, u->meta.id);
+                log_debug("Child %lu belongs to %s", (long unsigned) si.si_pid, u->meta.id);
 
-                hashmap_remove(m->watch_pids, UINT32_TO_PTR(si.si_pid));
+                hashmap_remove(m->watch_pids, LONG_TO_PTR(si.si_pid));
                 UNIT_VTABLE(u)->sigchld_event(u, si.si_pid, si.si_code, si.si_status);
         }
 
diff --git a/src/manager.h b/src/manager.h
index e5915d3..f3bf96e 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -171,7 +171,6 @@ struct Manager {
 
         /* Data specific to the cgroup subsystem */
         Hashmap *cgroup_bondings; /* path string => CGroupBonding object 1:n */
-        char *cgroup_mount_point;
         char *cgroup_hierarchy;
 
         usec_t gc_queue_timestamp;
diff --git a/src/pam-module.c b/src/pam-module.c
index 1834dd9..1441987 100644
--- a/src/pam-module.c
+++ b/src/pam-module.c
@@ -217,17 +217,17 @@ static int create_user_group(pam_handle_t *handle, const char *group, struct pas
         assert(group);
 
         if (attach)
-                r = cg_create_and_attach("name=systemd", group, 0);
+                r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, group, 0);
         else
-                r = cg_create("name=systemd", group);
+                r = cg_create(SYSTEMD_CGROUP_CONTROLLER, group);
 
         if (r < 0) {
                 pam_syslog(handle, LOG_ERR, "Failed to create cgroup: %s", strerror(-r));
                 return PAM_SESSION_ERR;
         }
 
-        if ((r = cg_set_task_access("name=systemd", group, 0755, pw->pw_uid, pw->pw_gid)) < 0 ||
-            (r = cg_set_group_access("name=systemd", group, 0755, pw->pw_uid, pw->pw_gid)) < 0) {
+        if ((r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, group, 0755, pw->pw_uid, pw->pw_gid)) < 0 ||
+            (r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, group, 0755, pw->pw_uid, pw->pw_gid)) < 0) {
                 pam_syslog(handle, LOG_ERR, "Failed to change access modes: %s", strerror(-r));
                 return PAM_SESSION_ERR;
         }
@@ -258,8 +258,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
         if (sd_booted() <= 0)
                 return PAM_SUCCESS;
 
-        if ((r = cgroup_init()) != 0) {
-                pam_syslog(handle, LOG_ERR, "libcgroup initialization failed: %s", cgroup_strerror(r));
+        if ((r = cg_init()) < 0) {
+                pam_syslog(handle, LOG_ERR, "libcgroup initialization failed: %s", strerror(-r));
                 r = PAM_SESSION_ERR;
                 goto finish;
         }
@@ -361,7 +361,7 @@ static int session_remains(pam_handle_t *handle, const char *user_path) {
 
         zero(info);
 
-        r = cgroup_walk_tree_begin("name=systemd", user_path, 0, &iterator, &info, &level);
+        r = cgroup_walk_tree_begin(SYSTEMD_CGROUP_CONTROLLER, user_path, 0, &iterator, &info, &level);
         while (r == 0) {
 
                 if (info.type != CGROUP_FILE_TYPE_DIR)
@@ -440,7 +440,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
 
                 if (kill_session)  {
                         /* Kill processes in session cgroup */
-                        if ((r = cg_kill_recursive_and_wait("name=systemd", session_path)) < 0)
+                        if ((r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, session_path)) < 0)
                                 pam_syslog(handle, LOG_ERR, "Failed to kill session cgroup: %s", strerror(-r));
 
                 } else  {
@@ -450,7 +450,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
                          * yet. */
                         create_user_group(handle, nosession_path, pw, 0);
 
-                        if ((r = cg_migrate_recursive("name=systemd", session_path, nosession_path, false)) < 0)
+                        if ((r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, session_path, nosession_path, false)) < 0)
                                 pam_syslog(handle, LOG_ERR, "Failed to migrate session cgroup: %s", strerror(-r));
                 }
 
@@ -458,13 +458,13 @@ _public_ PAM_EXTERN int pam_sm_close_session(
                 if (r < 0)
                         pam_syslog(handle, LOG_INFO, "Couldn't empty session cgroup, not deleting.");
                 else {
-                        if ((r = cg_delete("name=systemd", session_path)) < 0)
+                        if ((r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, session_path)) < 0)
                                 pam_syslog(handle, LOG_ERR, "Failed to delete session cgroup: %s", strerror(-r));
                 }
         }
 
         /* GC user tree */
-        cg_trim("name=systemd", user_path, false);
+        cg_trim(SYSTEMD_CGROUP_CONTROLLER, user_path, false);
 
         if ((r = session_remains(handle, user_path)) < 0)
                 pam_syslog(handle, LOG_ERR, "Failed to determine whether a session remains: %s", strerror(-r));
@@ -473,11 +473,11 @@ _public_ PAM_EXTERN int pam_sm_close_session(
         if (kill_user && r == 0) {
 
                 /* Kill no-session cgroup */
-                if ((r = cg_kill_recursive_and_wait("name=systemd", user_path)) < 0)
+                if ((r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, user_path)) < 0)
                         pam_syslog(handle, LOG_ERR, "Failed to kill user cgroup: %s", strerror(-r));
         } else {
 
-                if ((r = cg_is_empty_recursive("name=systemd", user_path, true)) < 0)
+                if ((r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, user_path, true)) < 0)
                         pam_syslog(handle, LOG_ERR, "Failed to check user cgroup: %s", strerror(-r));
 
                 /* If we managed to kill somebody, don't cleanup the cgroup. */
@@ -489,7 +489,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
                 const char *runtime_dir;
 
                 /* Remove user cgroup */
-                if ((r = cg_delete("name=systemd", user_path)) < 0)
+                if ((r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, user_path)) < 0)
                         pam_syslog(handle, LOG_ERR, "Failed to delete user cgroup: %s", strerror(-r));
 
                 /* This will migrate us to the /user cgroup. */
diff --git a/src/systemctl.c b/src/systemctl.c
index 53b6b47..799f57d 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -43,6 +43,7 @@
 #include "strv.h"
 #include "dbus-common.h"
 #include "cgroup-show.h"
+#include "cgroup-util.h"
 #include "list.h"
 
 static const char *arg_type = NULL;
@@ -1053,6 +1054,7 @@ typedef struct UnitStatusInfo {
 
 static void print_status_info(UnitStatusInfo *i) {
         ExecStatusInfo *p;
+        int r;
 
         assert(i);
 
@@ -1183,7 +1185,10 @@ static void print_status_info(UnitStatusInfo *i) {
                 else
                         c = 0;
 
-                show_cgroup_recursive(i->default_control_group, "\t\t  ", c);
+                if ((r = cg_init()) < 0)
+                        log_error("Failed to initialize libcg: %s", strerror(-r));
+                else
+                        show_cgroup_recursive(i->default_control_group, "\t\t  ", c);
         }
 }
 
diff --git a/src/systemd-cgls.c b/src/systemd-cgls.c
index 6614f0f..bd8d263 100644
--- a/src/systemd-cgls.c
+++ b/src/systemd-cgls.c
@@ -27,6 +27,7 @@
 #include <string.h>
 
 #include "cgroup-show.h"
+#include "cgroup-util.h"
 #include "log.h"
 #include "util.h"
 
@@ -82,6 +83,11 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        if (cg_init() < 0) {
+                log_error("Failed to initialize libcg: %s", strerror(-r));
+                goto finish;
+        }
+
         if (optind < argc) {
                 unsigned i;
 
@@ -105,7 +111,7 @@ int main(int argc, char *argv[]) {
                         printf("Working Directory %s:\n", p);
                         r = show_cgroup_recursive(p, NULL, 0);
                 } else
-                        r = show_cgroup_recursive("", NULL, 0);
+                        r = show_cgroup_recursive(NULL, NULL, 0);
 
                 free(p);
         }
diff --git a/src/test-cgroup.c b/src/test-cgroup.c
index 389df6d..45e7f0f 100644
--- a/src/test-cgroup.c
+++ b/src/test-cgroup.c
@@ -22,8 +22,6 @@
 #include <unistd.h>
 #include <string.h>
 
-#include <libcgroup.h>
-
 #include "cgroup-util.h"
 #include "util.h"
 #include "log.h"
@@ -31,54 +29,54 @@
 int main(int argc, char*argv[]) {
         char *path;
 
-        assert_se(cgroup_init() == 0);
+        assert_se(cg_init() >= 0);
 
-        assert_se(cg_create("name=systemd", "/test-a") == 0);
-        assert_se(cg_create("name=systemd", "/test-a") == 0);
-        assert_se(cg_create("name=systemd", "/test-b") == 0);
-        assert_se(cg_create("name=systemd", "/test-b/test-c") == 0);
-        assert_se(cg_create_and_attach("name=systemd", "/test-b", 0) == 0);
+        assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
+        assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
+        assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
+        assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-c") == 0);
+        assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0) == 0);
 
-        assert_se(cg_get_by_pid("name=systemd", getpid(), &path) == 0);
+        assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
         assert_se(streq(path, "/test-b"));
         free(path);
 
-        assert_se(cg_attach("name=systemd", "/test-a", 0) == 0);
+        assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) == 0);
 
-        assert_se(cg_get_by_pid("name=systemd", getpid(), &path) == 0);
+        assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
         assert_se(path_equal(path, "/test-a"));
         free(path);
 
-        assert_se(cg_create_and_attach("name=systemd", "/test-b/test-d", 0) == 0);
+        assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", 0) == 0);
 
-        assert_se(cg_get_by_pid("name=systemd", getpid(), &path) == 0);
+        assert_se(cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0);
         assert_se(path_equal(path, "/test-b/test-d"));
         free(path);
 
-        assert_se(cg_get_path("name=systemd", "/test-b/test-d", NULL, &path) == 0);
+        assert_se(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", NULL, &path) == 0);
         assert_se(path_equal(path, "/cgroup/systemd/test-b/test-d"));
         free(path);
 
-        assert_se(cg_is_empty("name=systemd", "/test-a", false) > 0);
-        assert_se(cg_is_empty("name=systemd", "/test-b", false) > 0);
-        assert_se(cg_is_empty_recursive("name=systemd", "/test-a", false) > 0);
-        assert_se(cg_is_empty_recursive("name=systemd", "/test-b", false) == 0);
+        assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
+        assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 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);
 
-        assert_se(cg_kill_recursive("name=systemd", "/test-a", 0, false) == 0);
-        assert_se(cg_kill_recursive("name=systemd", "/test-b", 0, false) > 0);
+        assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false) == 0);
+        assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false) > 0);
 
-        assert_se(cg_migrate_recursive("name=systemd", "/test-b", "/test-a", false) == 0);
+        assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", "/test-a", false) == 0);
 
-        assert_se(cg_is_empty_recursive("name=systemd", "/test-a", false) == 0);
-        assert_se(cg_is_empty_recursive("name=systemd", "/test-b", 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);
 
-        assert_se(cg_kill_recursive("name=systemd", "/test-a", 0, false) > 0);
-        assert_se(cg_kill_recursive("name=systemd", "/test-b", 0, false) == 0);
+        assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false) > 0);
+        assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false) == 0);
 
-        cg_trim("name=systemd", "/", false);
+        cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false);
 
-        assert_se(cg_delete("name=systemd", "/test-b") < 0);
-        assert_se(cg_delete("name=systemd", "/test-a") == 0);
+        assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0);
+        assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
 
         return 0;
 }
diff --git a/src/unit.c b/src/unit.c
index 5d51f99..b362fd3 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -39,6 +39,7 @@
 #include "specifier.h"
 #include "dbus-unit.h"
 #include "special.h"
+#include "cgroup-util.h"
 
 const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
         [UNIT_SERVICE] = &service_vtable,
@@ -1144,14 +1145,14 @@ int unit_watch_pid(Unit *u, pid_t pid) {
         /* Watch a specific PID. We only support one unit watching
          * each PID for now. */
 
-        return hashmap_put(u->meta.manager->watch_pids, UINT32_TO_PTR(pid), u);
+        return hashmap_put(u->meta.manager->watch_pids, LONG_TO_PTR(pid), u);
 }
 
 void unit_unwatch_pid(Unit *u, pid_t pid) {
         assert(u);
         assert(pid >= 1);
 
-        hashmap_remove_value(u->meta.manager->watch_pids, UINT32_TO_PTR(pid), u);
+        hashmap_remove_value(u->meta.manager->watch_pids, LONG_TO_PTR(pid), u);
 }
 
 int unit_watch_timer(Unit *u, usec_t delay, Watch *w) {
diff --git a/src/util.c b/src/util.c
index fa3969b..69eb14b 100644
--- a/src/util.c
+++ b/src/util.c
@@ -956,7 +956,6 @@ int mkdir_parents(const char *path, mode_t mode) {
                         return -ENOMEM;
 
                 r = mkdir(t, mode);
-
                 free(t);
 
                 if (r < 0 && errno != EEXIST)
@@ -972,7 +971,7 @@ int mkdir_p(const char *path, mode_t mode) {
         if ((r = mkdir_parents(path, mode)) < 0)
                 return r;
 
-        if (mkdir(path, mode) < 0)
+        if (mkdir(path, mode) < 0 && errno != EEXIST)
                 return -errno;
 
         return 0;
commit 55096547212928b0ba83fca2595cae0d66d3c0b0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 10 17:38:50 2010 +0200

    cgroup: make cgroup controller name a constant

diff --git a/src/cgroup.c b/src/cgroup.c
index 244a602..83fe2ef 100644
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -222,18 +222,14 @@ int manager_setup_cgroup(Manager *m) {
                 return cg_translate_error(r, errno);
         }
 
-        free(m->cgroup_controller);
-        if (!(m->cgroup_controller = strdup("name=systemd")))
-                return -ENOMEM;
-
         free(m->cgroup_mount_point);
         m->cgroup_mount_point = NULL;
-        if ((r = cgroup_get_subsys_mount_point(m->cgroup_controller, &m->cgroup_mount_point)))
+        if ((r = cgroup_get_subsys_mount_point(SYSTEMD_CGROUP_CONTROLLER, &m->cgroup_mount_point)))
                 return cg_translate_error(r, errno);
 
         pid = getpid();
 
-        if ((r = cgroup_get_current_controller_path(pid, m->cgroup_controller, &cp)))
+        if ((r = cgroup_get_current_controller_path(pid, SYSTEMD_CGROUP_CONTROLLER, &cp)))
                 return cg_translate_error(r, errno);
 
         snprintf(suffix, sizeof(suffix), "/systemd-%u", (unsigned) pid);
@@ -255,17 +251,16 @@ int manager_setup_cgroup(Manager *m) {
                         return -ENOMEM;
         }
 
-        log_debug("Using cgroup controller <%s>, hierarchy mounted at <%s>, using root group <%s>.",
-                  m->cgroup_controller,
+        log_debug("Using cgroup controller <" SYSTEMD_CGROUP_CONTROLLER ">, hierarchy mounted at <%s>, using root group <%s>.",
                   m->cgroup_mount_point,
                   m->cgroup_hierarchy);
 
-        if ((r = cg_install_release_agent(m->cgroup_controller, CGROUP_AGENT_PATH)) < 0)
+        if ((r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, CGROUP_AGENT_PATH)) < 0)
                 log_warning("Failed to install release agent, ignoring: %s", strerror(-r));
         else
                 log_debug("Installed release agent, or already installed.");
 
-        if ((r = cg_create_and_attach(m->cgroup_controller, m->cgroup_hierarchy, 0)) < 0)
+        if ((r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy, 0)) < 0)
                 log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
         else
                 log_debug("Created root group.");
@@ -276,10 +271,10 @@ int manager_setup_cgroup(Manager *m) {
 int manager_shutdown_cgroup(Manager *m) {
         assert(m);
 
-        if (!m->cgroup_controller || !m->cgroup_hierarchy)
+        if (!m->cgroup_hierarchy)
                 return 0;
 
-        return cg_delete(m->cgroup_controller, m->cgroup_hierarchy);
+        return cg_delete(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_hierarchy);
 }
 
 int cgroup_notify_empty(Manager *m, const char *group) {
@@ -324,7 +319,7 @@ Unit* cgroup_unit_by_pid(Manager *m, pid_t pid) {
         if (pid <= 1)
                 return NULL;
 
-        if ((r = cg_get_by_pid(m->cgroup_controller, pid, &group)))
+        if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &group)))
                 return NULL;
 
         l = hashmap_get(m->cgroup_bondings, group);
diff --git a/src/cgroup.h b/src/cgroup.h
index 05c858c..a7ca8ab 100644
--- a/src/cgroup.h
+++ b/src/cgroup.h
@@ -26,6 +26,8 @@ typedef struct CGroupBonding CGroupBonding;
 
 #include "unit.h"
 
+#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
+
 /* Binds a cgroup to a name */
 struct CGroupBonding {
         char *controller;
diff --git a/src/manager.c b/src/manager.c
index 524d125..8d016b9 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -443,7 +443,6 @@ void manager_free(Manager *m) {
         lookup_paths_free(&m->lookup_paths);
         strv_free(m->environment);
 
-        free(m->cgroup_controller);
         free(m->cgroup_hierarchy);
         free(m->cgroup_mount_point);
 
diff --git a/src/manager.h b/src/manager.h
index b44ffe2..e5915d3 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -171,7 +171,6 @@ struct Manager {
 
         /* Data specific to the cgroup subsystem */
         Hashmap *cgroup_bondings; /* path string => CGroupBonding object 1:n */
-        char *cgroup_controller;
         char *cgroup_mount_point;
         char *cgroup_hierarchy;
 
diff --git a/src/unit.c b/src/unit.c
index 18faae2..5d51f99 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -1598,7 +1598,7 @@ int unit_add_cgroup_from_text(Unit *u, const char *name) {
         if (n > 0)
                 controller = strndup(name, n);
         else
-                controller = strdup(u->meta.manager->cgroup_controller);
+                controller = strdup(SYSTEMD_CGROUP_CONTROLLER);
 
         if (!controller) {
                 r = -ENOMEM;
@@ -1647,7 +1647,7 @@ int unit_add_default_cgroup(Unit *u) {
         if (!(b = new0(CGroupBonding, 1)))
                 return -ENOMEM;
 
-        if (!(b->controller = strdup(u->meta.manager->cgroup_controller)))
+        if (!(b->controller = strdup(SYSTEMD_CGROUP_CONTROLLER)))
                 goto fail;
 
         if (!(b->path = default_cgroup_path(u)))
@@ -1672,7 +1672,7 @@ fail:
 CGroupBonding* unit_get_default_cgroup(Unit *u) {
         assert(u);
 
-        return cgroup_bonding_find_list(u->meta.cgroup_bondings, u->meta.manager->cgroup_controller);
+        return cgroup_bonding_find_list(u->meta.cgroup_bondings, SYSTEMD_CGROUP_CONTROLLER);
 }
 
 int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
commit fb385181517aa97fc5b379380cde0c2567f5f444
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 10 17:34:42 2010 +0200

    unit: trim cgroups when going down

diff --git a/src/cgroup.c b/src/cgroup.c
index 27130a9..244a602 100644
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -101,6 +101,20 @@ void cgroup_bonding_free_list(CGroupBonding *first) {
                 cgroup_bonding_free(b);
 }
 
+void cgroup_bonding_trim(CGroupBonding *b, bool delete_root) {
+        assert(b);
+
+        if (b->realized && b->only_us && b->clean_up)
+                cg_trim(b->controller, b->path, delete_root);
+}
+
+void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root) {
+        CGroupBonding *b;
+
+        LIST_FOREACH(by_unit, b, first)
+                cgroup_bonding_trim(b, delete_root);
+}
+
 int cgroup_bonding_install(CGroupBonding *b, pid_t pid) {
         int r;
 
diff --git a/src/cgroup.h b/src/cgroup.h
index 11d2aba..05c858c 100644
--- a/src/cgroup.h
+++ b/src/cgroup.h
@@ -61,6 +61,9 @@ int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid);
 int cgroup_bonding_kill(CGroupBonding *b, int sig);
 int cgroup_bonding_kill_list(CGroupBonding *first, int sig);
 
+void cgroup_bonding_trim(CGroupBonding *first, bool delete_root);
+void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root);
+
 int cgroup_bonding_is_empty(CGroupBonding *b);
 int cgroup_bonding_is_empty_list(CGroupBonding *first);
 
diff --git a/src/unit.c b/src/unit.c
index c287310..18faae2 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -973,6 +973,9 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
         if (ns != os && ns == UNIT_MAINTENANCE)
                 log_notice("Unit %s entered maintenance state.", u->meta.id);
 
+        if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
+                cgroup_bonding_trim_list(u->meta.cgroup_bondings, true);
+
         timer_unit_notify(u, ns);
         path_unit_notify(u, ns);
 


More information about the systemd-commits mailing list