]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
cgfsng: only establish mapping once
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 4 Jan 2018 14:28:12 +0000 (15:28 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Fri, 19 Jan 2018 13:31:11 +0000 (14:31 +0100)
When we deleted cgroups for unprivileged containers we used to allocate a new
mapping and clone a new user namespace each time we delete a cgroup. This of
course meant - on a cgroup v1 system - doing this >= 10 times when all
controllers were used. Let's not to do this and only allocate and establish a
mapping once.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c

index e3e5bc1df3a3da1c8094113a026613508bec15f0..5fd576b2c04104b5db2936e95cdc7cddc9ae8003 100644 (file)
@@ -1183,7 +1183,7 @@ out_free:
        return NULL;
 }
 
-static int cgroup_rmdir(char *dirname)
+static int recursive_destroy(char *dirname)
 {
        int ret;
        struct dirent *direntp;
@@ -1218,32 +1218,57 @@ static int cgroup_rmdir(char *dirname)
                if (!S_ISDIR(mystat.st_mode))
                        goto next;
 
-               ret = cgroup_rmdir(pathname);
+               ret = recursive_destroy(pathname);
                if (ret < 0)
                        r = -1;
-next:
+       next:
                free(pathname);
        }
 
        ret = rmdir(dirname);
        if (ret < 0) {
                if (!r)
-                       WARN("Failed to delete \"%s\": %s", dirname,
-                            strerror(errno));
+                       WARN("%s - Failed to delete \"%s\"", strerror(errno),
+                            dirname);
                r = -1;
        }
 
        ret = closedir(dir);
        if (ret < 0) {
                if (!r)
-                       WARN("Failed to delete \"%s\": %s", dirname,
-                            strerror(errno));
+                       WARN("%s - Failed to delete \"%s\"", strerror(errno),
+                            dirname);
                r = -1;
        }
 
        return r;
 }
 
+static int cgroup_rmdir(char *container_cgroup)
+{
+       int i;
+
+       if (!container_cgroup || !hierarchies)
+               return 0;
+
+       for (i = 0; hierarchies[i]; i++) {
+               int ret;
+               struct hierarchy *h = hierarchies[i];
+
+               if (!h->fullcgpath)
+                       continue;
+
+               ret = recursive_destroy(h->fullcgpath);
+               if (ret < 0)
+                       WARN("Failed to destroy \"%s\"", h->fullcgpath);
+
+               free(h->fullcgpath);
+               h->fullcgpath = NULL;
+       }
+
+       return 0;
+}
+
 struct generic_userns_exec_data {
        struct cgfsng_handler_data *d;
        struct lxc_conf *conf;
@@ -1251,7 +1276,7 @@ struct generic_userns_exec_data {
        char *path;
 };
 
-static int rmdir_wrapper(void *data)
+static int cgroup_rmdir_wrapper(void *data)
 {
        struct generic_userns_exec_data *arg = data;
        uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid;
@@ -1264,45 +1289,30 @@ static int rmdir_wrapper(void *data)
        if (setgroups(0, NULL) < 0 && errno != EPERM)
                SYSERROR("Failed to clear groups");
 
-       return cgroup_rmdir(arg->path);
+       return cgroup_rmdir(arg->d->container_cgroup);
 }
 
-void recursive_destroy(char *path, struct lxc_conf *conf)
+static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
 {
-       int r;
+       int ret;
+       struct cgfsng_handler_data *d = hdata;
        struct generic_userns_exec_data wrap;
 
+       if (!d)
+               return;
+
        wrap.origuid = 0;
-       wrap.d = NULL;
-       wrap.path = path;
+       wrap.d = hdata;
        wrap.conf = conf;
 
        if (conf && !lxc_list_empty(&conf->id_map))
-               r = userns_exec_1(conf, rmdir_wrapper, &wrap, "rmdir_wrapper");
+               ret = userns_exec_1(conf, cgroup_rmdir_wrapper, &wrap,
+                                   "cgroup_rmdir_wrapper");
        else
-               r = cgroup_rmdir(path);
-
-       if (r < 0)
-               ERROR("Error destroying %s", path);
-}
-
-static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
-{
-       struct cgfsng_handler_data *d = hdata;
-
-       if (!d)
+               ret = cgroup_rmdir(d->container_cgroup);
+       if (ret < 0) {
+               WARN("Failed to destroy cgroups");
                return;
-
-       if (d->container_cgroup && hierarchies) {
-               int i;
-               for (i = 0; hierarchies[i]; i++) {
-                       struct hierarchy *h = hierarchies[i];
-                       if (h->fullcgpath) {
-                               recursive_destroy(h->fullcgpath, conf);
-                               free(h->fullcgpath);
-                               h->fullcgpath = NULL;
-                       }
-               }
        }
 
        free_handler_data(d);