X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcgroup-util.c;fp=src%2Fcgroup-util.c;h=5fb248470e2fa7f4ed52a4ecab8ae1e1a0733152;hb=e27796a03065fac50fad07d5b42682ecb1e17d46;hp=ec48ea63b4d0db188c7ba247953d64f0cfa20b88;hpb=b4454c5edfab70fd1c6a0ea6836a0c2ddb61ef25;p=elogind.git diff --git a/src/cgroup-util.c b/src/cgroup-util.c index ec48ea63b..5fb248470 100644 --- a/src/cgroup-util.c +++ b/src/cgroup-util.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "cgroup-util.h" #include "log.h" @@ -554,20 +555,70 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch return 0; } +static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { + char *p; + bool is_sticky; + + if (typeflag != FTW_DP) + return 0; + + if (ftwbuf->level < 1) + return 0; + + p = strappend(path, "/tasks"); + if (!p) { + errno = ENOMEM; + return 1; + } + + is_sticky = file_is_sticky(p) > 0; + free(p); + + if (is_sticky) + return 0; + + rmdir(path); + return 0; +} + int cg_trim(const char *controller, const char *path, bool delete_root) { char *fs; - int r; + int r = 0; assert(controller); assert(path); - if ((r = cg_get_path(controller, path, NULL, &fs)) < 0) + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) return r; - r = rm_rf(fs, true, delete_root, true); + errno = 0; + if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0) + r = errno ? -errno : -EIO; + + if (delete_root) { + bool is_sticky; + char *p; + + p = strappend(fs, "/tasks"); + if (!p) { + free(fs); + return -ENOMEM; + } + + is_sticky = file_is_sticky(p) > 0; + free(p); + + if (!is_sticky) + if (rmdir(fs) < 0 && errno != ENOENT) { + if (r == 0) + r = -errno; + } + } + free(fs); - return r == -ENOENT ? 0 : r; + return r; } int cg_delete(const char *controller, const char *path) {