summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2011-08-21 21:00:41 +0200
committerLennart Poettering <lennart@poettering.net>2011-08-21 21:00:41 +0200
commite27796a03065fac50fad07d5b42682ecb1e17d46 (patch)
treec7ad138e0598486ace8313341998786c59c5705f
parentb4454c5edfab70fd1c6a0ea6836a0c2ddb61ef25 (diff)
downloadsystemd-e27796a03065fac50fad07d5b42682ecb1e17d46.tar.gz
cgroup: when trimming cgroup trees, honour sticky bit of tasks file
-rw-r--r--src/cgroup-util.c59
-rw-r--r--src/util.c2
2 files changed, 56 insertions, 5 deletions
diff --git a/src/cgroup-util.c b/src/cgroup-util.c
index ec48ea63b4..5fb248470e 100644
--- a/src/cgroup-util.c
+++ b/src/cgroup-util.c
@@ -27,6 +27,7 @@
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <ftw.h>
#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) {
diff --git a/src/util.c b/src/util.c
index ecfe450dca..e31e0f575a 100644
--- a/src/util.c
+++ b/src/util.c
@@ -3475,7 +3475,7 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky
if (honour_sticky && file_is_sticky(path) > 0)
return r;
- if (rmdir(path) < 0) {
+ if (rmdir(path) < 0 && errno != ENOENT) {
if (r == 0)
r = -errno;
}