]> err.no Git - systemd/commitdiff
cgroup: when trimming cgroup trees, honour sticky bit of tasks file
authorLennart Poettering <lennart@poettering.net>
Sun, 21 Aug 2011 19:00:41 +0000 (21:00 +0200)
committerLennart Poettering <lennart@poettering.net>
Sun, 21 Aug 2011 19:00:41 +0000 (21:00 +0200)
src/cgroup-util.c
src/util.c

index ec48ea63b4d0db188c7ba247953d64f0cfa20b88..5fb248470e2fa7f4ed52a4ecab8ae1e1a0733152 100644 (file)
@@ -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) {
index ecfe450dcac5dd3c8bf33497ec8759b7f2d80cb8..e31e0f575abae17bdfe117a0f022c53d18c77f4e 100644 (file)
@@ -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;
                 }