From: Christian Brauner Date: Thu, 4 Jan 2018 14:28:12 +0000 (+0100) Subject: cgfsng: only establish mapping once X-Git-Tag: lxc-2.0.10~428 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8b90f56638abe30f3a79a841c7cc89ddf7ad7146;p=thirdparty%2Flxc.git cgfsng: only establish mapping once 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 --- diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index e3e5bc1df..5fd576b2c 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -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);