static int refresh_one( const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration, unsigned depth) { DIR *d = NULL; int r; assert(controller); assert(path); assert(a); if (depth > arg_depth) return 0; r = process(controller, path, a, b, iteration); if (r < 0) return r; r = cg_enumerate_subgroups(controller, path, &d); if (r < 0) { if (r == -ENOENT) return 0; return r; } for (;;) { char *fn, *p; r = cg_read_subgroup(d, &fn); if (r <= 0) goto finish; p = strjoin(path, "/", fn, NULL); free(fn); if (!p) { r = -ENOMEM; goto finish; } path_kill_slashes(p); r = refresh_one(controller, p, a, b, iteration, depth + 1); free(p); if (r < 0) goto finish; } finish: if (d) closedir(d); return r; }
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_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) { _cleanup_set_free_ Set *allocated_set = NULL; _cleanup_closedir_ DIR *d = NULL; int r, ret = 0; char *fn; assert(path); assert(sig >= 0); if (!s) { s = allocated_set = set_new(NULL); if (!s) return -ENOMEM; } ret = cg_kill(controller, path, sig, sigcont, ignore_self, s); r = cg_enumerate_subgroups(controller, path, &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(path, "/", fn, NULL); free(fn); if (!p) return -ENOMEM; r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s); if (ret >= 0 && r != 0) ret = r; } if (ret >= 0 && r < 0) ret = r; if (rem) { r = cg_rmdir(controller, path); if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY) return r; } return ret; }
int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) { int r; DIR *d = NULL; char *fn; assert(path); r = cg_is_empty(controller, path, ignore_self); if (r <= 0) return r; r = cg_enumerate_subgroups(controller, path, &d); if (r < 0) return r == -ENOENT ? 1 : r; while ((r = cg_read_subgroup(d, &fn)) > 0) { char *p = NULL; r = asprintf(&p, "%s/%s", path, fn); free(fn); if (r < 0) { r = -ENOMEM; goto finish; } r = cg_is_empty_recursive(controller, p, ignore_self); free(p); if (r <= 0) goto finish; } if (r >= 0) r = 1; finish: if (d) closedir(d); return r; }
static int refresh_one( const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration, unsigned depth, Group **ret) { _cleanup_closedir_ DIR *d = NULL; Group *ours = NULL; int r; assert(controller); assert(path); assert(a); if (depth > arg_depth) return 0; r = process(controller, path, a, b, iteration, &ours); if (r < 0) return r; r = cg_enumerate_subgroups(controller, path, &d); if (r == -ENOENT) return 0; if (r < 0) return r; for (;;) { _cleanup_free_ char *fn = NULL, *p = NULL; Group *child = NULL; r = cg_read_subgroup(d, &fn); if (r < 0) return r; if (r == 0) break; p = strjoin(path, "/", fn, NULL); if (!p) return -ENOMEM; path_kill_slashes(p); r = refresh_one(controller, p, a, b, iteration, depth + 1, &child); if (r < 0) return r; if (arg_recursive && IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES) && child && child->n_tasks_valid && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { /* Recursively sum up processes */ if (ours->n_tasks_valid) ours->n_tasks += child->n_tasks; else { ours->n_tasks = child->n_tasks; ours->n_tasks_valid = true; } } } if (ret) *ret = ours; return 1; }
int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) { int r, ret = 0; DIR *d = NULL; char *fn; Set *allocated_set = NULL; assert(path); assert(controller); assert(sig >= 0); if (!s) if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func))) return -ENOMEM; ret = cg_kill(controller, path, sig, sigcont, ignore_self, s); if ((r = cg_enumerate_subgroups(controller, path, &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", path, fn); free(fn); if (r < 0) { if (ret >= 0) ret = -ENOMEM; goto finish; } r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s); free(p); if (r != 0 && ret >= 0) ret = r; } if (r < 0 && ret >= 0) ret = r; if (rem) if ((r = cg_rmdir(controller, path, true)) < 0) { if (ret >= 0 && r != -ENOENT && r != -EBUSY) ret = r; } finish: if (d) closedir(d); if (allocated_set) set_free(allocated_set); return ret; }