+int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name, const char *value, CGroupAttributeMapCallback map_callback) {
+ int r;
+ char *c = NULL;
+ CGroupAttribute *a;
+
+ assert(u);
+ assert(name);
+ assert(value);
+
+ if (!controller) {
+ const char *dot;
+
+ dot = strchr(name, '.');
+ if (!dot)
+ return -EINVAL;
+
+ c = strndup(name, dot - name);
+ if (!c)
+ return -ENOMEM;
+
+ controller = c;
+ }
+
+ if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
+ r = -EINVAL;
+ goto finish;
+ }
+
+ a = new0(CGroupAttribute, 1);
+ if (!a) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ 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->map_callback = map_callback;
+
+ LIST_PREPEND(CGroupAttribute, by_unit, u->meta.cgroup_attributes, a);
+
+ r = 0;
+
+finish:
+ free(c);
+ return r;
+}
+