+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);
+}
+