chiark / gitweb /
logger: fix return value
[elogind.git] / unit.c
diff --git a/unit.c b/unit.c
index c27e4ec902c74ed793b5f9fbaf1837900ad75c1c..036c01648c6e017ee4d832e67d74a20e1c359fe9 100644 (file)
--- a/unit.c
+++ b/unit.c
@@ -260,6 +260,8 @@ void unit_free(Unit *u) {
 
         /* Detach from next 'bigger' objects */
 
+        cgroup_bonding_free_list(u->meta.cgroup_bondings);
+
         SET_FOREACH(t, u->meta.names, i)
                 hashmap_remove_value(u->meta.manager->units, t, u);
 
@@ -284,7 +286,7 @@ void unit_free(Unit *u) {
                 bidi_set_free(u, u->meta.dependencies[d]);
 
         free(u->meta.description);
-        free(u->meta.load_path);
+        free(u->meta.fragment_path);
 
         while ((t = set_steal_first(u->meta.names)))
                 free(t);
@@ -369,12 +371,12 @@ const char *unit_description(Unit *u) {
 }
 
 void unit_dump(Unit *u, FILE *f, const char *prefix) {
-
         char *t;
         UnitDependency d;
         Iterator i;
         char *p2;
         const char *prefix2;
+        CGroupBonding *b;
 
         assert(u);
 
@@ -397,8 +399,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, yes_no(u->meta.recursive_stop),
                 prefix, yes_no(u->meta.stop_when_unneeded));
 
-        if (u->meta.load_path)
-                fprintf(f, "%s\tLoad Path: %s\n", prefix, u->meta.load_path);
+        if (u->meta.fragment_path)
+                fprintf(f, "%s\tFragment Path: %s\n", prefix, u->meta.fragment_path);
 
         SET_FOREACH(t, u->meta.names, i)
                 fprintf(f, "%s\tName: %s\n", prefix, t);
@@ -413,6 +415,10 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                         fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), unit_id(other));
         }
 
+        LIST_FOREACH(by_unit, b, u->meta.cgroup_bondings)
+                fprintf(f, "%s\tControlGroup: %s:%s\n",
+                        prefix, b->controller, b->path);
+
         if (UNIT_VTABLE(u)->dump)
                 UNIT_VTABLE(u)->dump(u, f, prefix2);
 
@@ -478,13 +484,18 @@ int unit_start(Unit *u) {
 
         assert(u);
 
-        if (!UNIT_VTABLE(u)->start)
-                return -EBADR;
-
+        /* If this is already (being) started, then this will
+         * succeed. Note that this will even succeed if this unit is
+         * not startable by the user. This is relied on to detect when
+         * we need to wait for units and when waiting is finished. */
         state = unit_active_state(u);
         if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                 return -EALREADY;
 
+        /* If it is stopped, but we cannot start it, then fail */
+        if (!UNIT_VTABLE(u)->start)
+                return -EBADR;
+
         /* We don't suppress calls to ->start() here when we are
          * already starting, to allow this request to be used as a
          * "hurry up" call, for example when the unit is in some "auto
@@ -511,13 +522,13 @@ int unit_stop(Unit *u) {
 
         assert(u);
 
-        if (!UNIT_VTABLE(u)->stop)
-                return -EBADR;
-
         state = unit_active_state(u);
         if (state == UNIT_INACTIVE)
                 return -EALREADY;
 
+        if (!UNIT_VTABLE(u)->stop)
+                return -EBADR;
+
         if (state == UNIT_DEACTIVATING)
                 return 0;
 
@@ -967,14 +978,17 @@ int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name) {
         return 0;
 }
 
-const char *unit_path(void) {
-        char *e;
+int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name) {
+        Unit *other;
+        int r;
+
+        if ((r = manager_load_unit(u->meta.manager, name, &other)) < 0)
+                return r;
 
-        if ((e = getenv("UNIT_PATH")))
-                if (path_is_absolute(e))
-                    return e;
+        if ((r = unit_add_dependency(other, d, u)) < 0)
+                return r;
 
-        return UNIT_PATH;
+        return 0;
 }
 
 int set_unit_path(const char *p) {
@@ -997,7 +1011,7 @@ int set_unit_path(const char *p) {
                         return -ENOMEM;
         }
 
-        if (setenv("UNIT_PATH", c, 0) < 0) {
+        if (setenv("SYSTEMD_UNIT_PATH", c, 0) < 0) {
                 r = -errno;
                 free(c);
                 return r;
@@ -1006,10 +1020,10 @@ int set_unit_path(const char *p) {
         return 0;
 }
 
-char *unit_name_escape_path(const char *prefix, const char *path, const char *suffix) {
+char *unit_name_escape_path(const char *path, const char *suffix) {
         char *r, *t;
         const char *f;
-        size_t a, b, c;
+        size_t a, b;
 
         assert(path);
 
@@ -1022,22 +1036,16 @@ char *unit_name_escape_path(const char *prefix, const char *path, const char *su
          * escaping is hence reversible.
          */
 
-        if (!prefix)
-                prefix = "";
-
         if (!suffix)
                 suffix = "";
 
-        a = strlen(prefix);
-        b = strlen(path);
-        c = strlen(suffix);
+        a = strlen(path);
+        b = strlen(suffix);
 
-        if (!(r = new(char, a+b*4+c+1)))
+        if (!(r = new(char, a*4+b+1)))
                 return NULL;
 
-        memcpy(r, prefix, a);
-
-        for (f = path, t = r+a; *f; f++) {
+        for (f = path, t = r; *f; f++) {
                 if (*f == '/')
                         *(t++) = '.';
                 else if (*f == '.' || *f == '\\' || !strchr(VALID_CHARS, *f)) {
@@ -1049,7 +1057,7 @@ char *unit_name_escape_path(const char *prefix, const char *path, const char *su
                         *(t++) = *f;
         }
 
-        memcpy(t, suffix, c+1);
+        memcpy(t, suffix, b+1);
 
         return r;
 }
@@ -1071,6 +1079,138 @@ char *unit_dbus_path(Unit *u) {
         return p;
 }
 
+int unit_add_cgroup(Unit *u, CGroupBonding *b) {
+        CGroupBonding *l;
+        int r;
+
+        assert(u);
+        assert(b);
+        assert(b->path);
+
+        /* Ensure this hasn't been added yet */
+        assert(!b->unit);
+
+        l = hashmap_get(u->meta.manager->cgroup_bondings, b->path);
+        LIST_PREPEND(CGroupBonding, by_path, l, b);
+
+        if ((r = hashmap_replace(u->meta.manager->cgroup_bondings, b->path, l)) < 0) {
+                LIST_REMOVE(CGroupBonding, by_path, l, b);
+                return r;
+        }
+
+        LIST_PREPEND(CGroupBonding, by_unit, u->meta.cgroup_bondings, b);
+        b->unit = u;
+
+        return 0;
+}
+
+int unit_add_cgroup_from_text(Unit *u, const char *name) {
+        size_t n;
+        const char *p;
+        char *controller;
+        CGroupBonding *b;
+        int r;
+
+        assert(u);
+        assert(name);
+
+        /* Detect controller name */
+        n = strcspn(name, ":/");
+
+        /* Only controller name, no path? No path? */
+        if (name[n] == 0)
+                return -EINVAL;
+
+        if (n > 0) {
+                if (name[n] != ':')
+                        return -EINVAL;
+
+                p = name+n+1;
+        } else
+                p = name;
+
+        /* Insist in absolute paths */
+        if (p[0] != '/')
+                return -EINVAL;
+
+        if (!(controller = strndup(name, n)))
+                return -ENOMEM;
+
+        if (cgroup_bonding_find_list(u->meta.cgroup_bondings, controller)) {
+                free(controller);
+                return -EEXIST;
+        }
+
+        if (!(b = new0(CGroupBonding, 1))) {
+                free(controller);
+                return -ENOMEM;
+        }
+
+        b->controller = controller;
+
+        if (!(b->path = strdup(p))) {
+                r = -ENOMEM;
+                goto fail;
+        }
+
+        b->only_us = false;
+        b->clean_up = false;
+
+        if ((r = unit_add_cgroup(u, b)) < 0)
+                goto fail;
+
+        return 0;
+
+fail:
+        free(b->path);
+        free(b->controller);
+        free(b);
+
+        return r;
+}
+
+int unit_add_default_cgroup(Unit *u) {
+        CGroupBonding *b;
+        int r = -ENOMEM;
+
+        assert(u);
+
+        /* Adds in the default cgroup data, if it wasn't specified yet */
+
+        if (unit_get_default_cgroup(u))
+                return 0;
+
+        if (!(b = new0(CGroupBonding, 1)))
+                return -ENOMEM;
+
+        if (!(b->controller = strdup(u->meta.manager->cgroup_controller)))
+                goto fail;
+
+        if (asprintf(&b->path, "%s/%s", u->meta.manager->cgroup_hierarchy, unit_id(u)) < 0)
+                goto fail;
+
+        b->clean_up = true;
+        b->only_us = true;
+
+        if ((r = unit_add_cgroup(u, b)) < 0)
+                goto fail;
+
+        return 0;
+
+fail:
+        free(b->path);
+        free(b->controller);
+        free(b);
+
+        return r;
+}
+
+CGroupBonding* unit_get_default_cgroup(Unit *u) {
+        assert(u);
+
+        return cgroup_bonding_find_list(u->meta.cgroup_bondings, u->meta.manager->cgroup_controller);
+}
+
 static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
         [UNIT_SERVICE] = "service",
         [UNIT_TIMER] = "timer",