int cg_migrate_recursive_fallback( const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) { int r; assert(cfrom); assert(pfrom); assert(cto); assert(pto); r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem); if (r < 0) { char prefix[strlen(pto) + 1]; /* This didn't work? Then let's try all prefixes of the destination */ PATH_FOREACH_PREFIX(prefix, pto) { r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem); if (r >= 0) break; }
int cg_migrate_recursive( const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) { _cleanup_closedir_ DIR *d = NULL; int r, ret = 0; char *fn; assert(cfrom); assert(pfrom); assert(cto); assert(pto); ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self); r = cg_enumerate_subgroups(cfrom, pfrom, &d); if (r < 0) { if (ret >= 0 && r != -ENOENT) return r; return ret; } while ((r = cg_read_subgroup(d, &fn)) > 0) { _cleanup_free_ char *p = NULL; p = strjoin(pfrom, "/", fn, NULL); free(fn); if (!p) { if (ret >= 0) return -ENOMEM; return ret; } r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem); if (r != 0 && ret >= 0) ret = r; } if (r < 0 && ret >= 0) ret = r; if (rem) { r = cg_rmdir(cfrom, pfrom); if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY) return r; } return ret; }
int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool rem) { int r, ret = 0; DIR *d = NULL; char *fn; assert(controller); assert(from); assert(to); ret = cg_migrate(controller, from, to, ignore_self); if ((r = cg_enumerate_subgroups(controller, from, &d)) < 0) { if (ret >= 0 && r != -ENOENT) ret = r; goto finish; } while ((r = cg_read_subgroup(d, &fn)) > 0) { char *p = NULL; r = asprintf(&p, "%s/%s", from, fn); free(fn); if (r < 0) { if (ret >= 0) ret = -ENOMEM; goto finish; } r = cg_migrate_recursive(controller, p, to, ignore_self, rem); free(p); if (r != 0 && ret >= 0) ret = r; } if (r < 0 && ret >= 0) ret = r; if (rem) if ((r = cg_rmdir(controller, from, true)) < 0) { if (ret >= 0 && r != -ENOENT && r != -EBUSY) ret = r; } finish: if (d) closedir(d); return ret; }
int cg_delete(const char *controller, const char *path) { char *parent; int r; assert(controller); assert(path); if ((r = parent_of_path(path, &parent)) < 0) return r; r = cg_migrate_recursive(controller, path, parent, false, true); free(parent); return r == -ENOENT ? 0 : r; }
int main(int argc, char*argv[]) { char *path; char *c, *p; 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(SYSTEMD_CGROUP_CONTROLLER, getpid(), &path) == 0); assert_se(streq(path, "/test-b")); free(path); assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) == 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(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", 0) == 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(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", NULL, &path) == 0); assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d")); free(path); 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(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0); assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0); assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", false, 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(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) > 0); assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) == 0); cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false); assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0); assert_se(cg_delete(SYSTEMD_CGROUP_CONTROLLER, "/test-a") >= 0); assert_se(cg_split_spec("foobar:/", &c, &p) == 0); assert(streq(c, "foobar")); assert(streq(p, "/")); free(c); free(p); assert_se(cg_split_spec("foobar:", &c, &p) < 0); assert_se(cg_split_spec("foobar:asdfd", &c, &p) < 0); assert_se(cg_split_spec(":///", &c, &p) < 0); assert_se(cg_split_spec(":", &c, &p) < 0); assert_se(cg_split_spec("", &c, &p) < 0); assert_se(cg_split_spec("fo/obar:/", &c, &p) < 0); assert_se(cg_split_spec("/", &c, &p) >= 0); assert(c == NULL); assert(streq(p, "/")); free(p); assert_se(cg_split_spec("foo", &c, &p) >= 0); assert(streq(c, "foo")); assert(p == NULL); free(c); return 0; }