X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcgroup-util.c;h=f74280f4952f353623325f832a03fb30e36ebb25;hp=ec48ea63b4d0db188c7ba247953d64f0cfa20b88;hb=0c85a4f3efa2883c414ed8ff59aea263b85b7687;hpb=ad293f5a94d8124ece7d1cb860952a87b1c8d98f diff --git a/src/cgroup-util.c b/src/cgroup-util.c index ec48ea63b..f74280f49 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" @@ -512,7 +513,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (_unlikely_(!good)) { int r; - r = path_is_mount_point("/sys/fs/cgroup"); + r = path_is_mount_point("/sys/fs/cgroup", false); if (r <= 0) return r < 0 ? r : -ENOENT; @@ -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) {