- if (streq(controller, "systemd")) {
- /* Within the systemd unit hierarchy we do not allow changes. */
- if (path_startswith(path, "/system")) {
- log_warning_unit(u->id, "Manipulating the systemd:/system cgroup hierarchy is not permitted.");
- free(path);
- free(controller);
- return -EPERM;
- }
- }
-
- 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;
- }
-
- b = new0(CGroupBonding, 1);
- if (!b) {
- r = -ENOMEM;
- goto fail;
- }
-
- b->controller = controller;
- b->path = path;
- b->ours = ours;
- b->essential = streq(controller, SYSTEMD_CGROUP_CONTROLLER);
-
- r = unit_add_cgroup(u, b);
- if (r < 0)
- goto fail;
-
- if (ret)
- *ret = b;
-
- return 1;
-
-fail:
- free(path);
- free(controller);
- free(b);
-
- return r;
-}
-
-static int unit_add_one_default_cgroup(Unit *u, const char *controller) {
- CGroupBonding *b = NULL;
- int r = -ENOMEM;
-
- assert(u);
-
- if (controller && !cg_controller_is_valid(controller, true))
- return -EINVAL;
-
- if (!controller)
- controller = SYSTEMD_CGROUP_CONTROLLER;
-
- if (cgroup_bonding_find_list(u->cgroup_bondings, controller))
- return 0;
-
- b = new0(CGroupBonding, 1);
- if (!b)
- return -ENOMEM;
-
- b->controller = strdup(controller);
- if (!b->controller)
- goto fail;
-
- b->path = unit_default_cgroup_path(u);
- if (!b->path)
- goto fail;
-
- b->ours = true;
- b->essential = streq(controller, SYSTEMD_CGROUP_CONTROLLER);
-
- r = unit_add_cgroup(u, b);
- if (r < 0)
- goto fail;
-
- return 1;
-
-fail:
- free(b->path);
- free(b->controller);
- free(b);
-
- return r;
-}
-
-int unit_add_default_slice(Unit *u) {
- Unit *slice;
- int r;
-
- assert(u);
-
- if (UNIT_DEREF(u->slice))
- return 0;
-
- if (u->manager->running_as != SYSTEMD_SYSTEM)
- return 0;
-
- r = manager_load_unit(u->manager, SPECIAL_SYSTEM_SLICE, NULL, NULL, &slice);
- if (r < 0)
- return r;
-
- unit_ref_set(&u->slice, slice);
- return 0;
-}
-
-int unit_add_default_cgroups(Unit *u) {
- CGroupAttribute *a;
- char **c;
- int r;
-
- assert(u);
-
- /* Adds in the default cgroups, if they weren't specified
- * otherwise. */
-
- if (!u->manager->cgroup_hierarchy)
- return 0;
-
- r = unit_add_one_default_cgroup(u, NULL);
- if (r < 0)
- return r;
-
- STRV_FOREACH(c, u->manager->default_controllers)
- unit_add_one_default_cgroup(u, *c);
-
- LIST_FOREACH(by_unit, a, u->cgroup_attributes)
- unit_add_one_default_cgroup(u, a->controller);
-
- return 0;
-}
-
-CGroupBonding* unit_get_default_cgroup(Unit *u) {
- assert(u);
-
- return cgroup_bonding_find_list(u->cgroup_bondings, NULL);
-}
-
-int unit_add_cgroup_attribute(
- Unit *u,
- const CGroupSemantics *semantics,
- const char *controller,
- const char *name,
- const char *value,
- CGroupAttribute **ret) {
-
- _cleanup_free_ char *c = NULL;
- CGroupAttribute *a;
- int r;
-
- assert(u);
- assert(value);
-
- if (semantics) {
- /* Semantics always take precedence */
- if (semantics->name)
- name = semantics->name;
-
- if (semantics->controller)
- controller = semantics->controller;
- }
-
- if (!name)
- return -EINVAL;
-
- if (!controller) {
- r = cg_controller_from_attr(name, &c);
- if (r < 0)
- return -EINVAL;
-
- controller = c;
- }
-
- if (!controller ||
- streq(controller, SYSTEMD_CGROUP_CONTROLLER) ||
- streq(controller, "systemd"))
- return -EINVAL;
-
- if (!filename_is_safe(name))
- return -EINVAL;
-
- if (!cg_controller_is_valid(controller, false))
- return -EINVAL;
-
- /* Check if this attribute already exists. Note that we will
- * explicitly check for the value here too, as there are
- * attributes which accept multiple values. */
- a = cgroup_attribute_find_list(u->cgroup_attributes, controller, name);
- if (a) {
- if (streq(value, a->value)) {
- /* Exactly the same value is always OK, let's ignore this */
- if (ret)
- *ret = a;
-
- return 0;
- }
-
- if (semantics && !semantics->multiple) {
- char *v;
-
- /* If this is a single-item entry, we can
- * simply patch the existing attribute */
-
- 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)
- return -ENOMEM;
-
- if (c) {
- a->controller = c;
- c = NULL;
- } else
- a->controller = strdup(controller);
-
- a->name = strdup(name);
- a->value = strdup(value);
-
- if (!a->controller || !a->name || !a->value) {
- free(a->controller);
- free(a->name);
- free(a->value);
- free(a);
- return -ENOMEM;
- }
-
- a->semantics = semantics;
- a->unit = u;
-
- LIST_PREPEND(CGroupAttribute, by_unit, u->cgroup_attributes, a);
-
- if (ret)
- *ret = a;
-
- return 1;