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: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent dcf0ffdf
...@@ -1206,7 +1206,7 @@ out_free: ...@@ -1206,7 +1206,7 @@ out_free:
return NULL; return NULL;
} }
static int cgroup_rmdir(char *dirname) static int recursive_destroy(char *dirname)
{ {
int ret; int ret;
struct dirent *direntp; struct dirent *direntp;
...@@ -1241,32 +1241,57 @@ static int cgroup_rmdir(char *dirname) ...@@ -1241,32 +1241,57 @@ static int cgroup_rmdir(char *dirname)
if (!S_ISDIR(mystat.st_mode)) if (!S_ISDIR(mystat.st_mode))
goto next; goto next;
ret = cgroup_rmdir(pathname); ret = recursive_destroy(pathname);
if (ret < 0) if (ret < 0)
r = -1; r = -1;
next: next:
free(pathname); free(pathname);
} }
ret = rmdir(dirname); ret = rmdir(dirname);
if (ret < 0) { if (ret < 0) {
if (!r) if (!r)
WARN("Failed to delete \"%s\": %s", dirname, WARN("%s - Failed to delete \"%s\"", strerror(errno),
strerror(errno)); dirname);
r = -1; r = -1;
} }
ret = closedir(dir); ret = closedir(dir);
if (ret < 0) { if (ret < 0) {
if (!r) if (!r)
WARN("Failed to delete \"%s\": %s", dirname, WARN("%s - Failed to delete \"%s\"", strerror(errno),
strerror(errno)); dirname);
r = -1; r = -1;
} }
return r; 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 generic_userns_exec_data {
struct cgfsng_handler_data *d; struct cgfsng_handler_data *d;
struct lxc_conf *conf; struct lxc_conf *conf;
...@@ -1274,7 +1299,7 @@ struct generic_userns_exec_data { ...@@ -1274,7 +1299,7 @@ struct generic_userns_exec_data {
char *path; char *path;
}; };
static int rmdir_wrapper(void *data) static int cgroup_rmdir_wrapper(void *data)
{ {
struct generic_userns_exec_data *arg = data; struct generic_userns_exec_data *arg = data;
uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid; uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid;
...@@ -1287,45 +1312,30 @@ static int rmdir_wrapper(void *data) ...@@ -1287,45 +1312,30 @@ static int rmdir_wrapper(void *data)
if (setgroups(0, NULL) < 0 && errno != EPERM) if (setgroups(0, NULL) < 0 && errno != EPERM)
SYSERROR("Failed to clear groups"); 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; struct generic_userns_exec_data wrap;
if (!d)
return;
wrap.origuid = 0; wrap.origuid = 0;
wrap.d = NULL; wrap.d = hdata;
wrap.path = path;
wrap.conf = conf; wrap.conf = conf;
if (conf && !lxc_list_empty(&conf->id_map)) 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 else
r = cgroup_rmdir(path); ret = cgroup_rmdir(d->container_cgroup);
if (ret < 0) {
if (r < 0) WARN("Failed to destroy cgroups");
ERROR("Error destroying %s", path);
}
static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
{
struct cgfsng_handler_data *d = hdata;
if (!d)
return; 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); free_handler_data(d);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment