mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-08 04:36:21 +00:00
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 <christian.brauner@ubuntu.com>
This commit is contained in:
parent
dcf0ffdf41
commit
bd8ef4e4da
@ -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)
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
struct generic_userns_exec_data wrap;
|
|
||||||
|
|
||||||
wrap.origuid = 0;
|
|
||||||
wrap.d = NULL;
|
|
||||||
wrap.path = path;
|
|
||||||
wrap.conf = conf;
|
|
||||||
|
|
||||||
if (conf && !lxc_list_empty(&conf->id_map))
|
|
||||||
r = userns_exec_1(conf, rmdir_wrapper, &wrap, "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)
|
static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct cgfsng_handler_data *d = hdata;
|
struct cgfsng_handler_data *d = hdata;
|
||||||
|
struct generic_userns_exec_data wrap;
|
||||||
|
|
||||||
if (!d)
|
if (!d)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (d->container_cgroup && hierarchies) {
|
wrap.origuid = 0;
|
||||||
int i;
|
wrap.d = hdata;
|
||||||
for (i = 0; hierarchies[i]; i++) {
|
wrap.conf = conf;
|
||||||
struct hierarchy *h = hierarchies[i];
|
|
||||||
if (h->fullcgpath) {
|
if (conf && !lxc_list_empty(&conf->id_map))
|
||||||
recursive_destroy(h->fullcgpath, conf);
|
ret = userns_exec_1(conf, cgroup_rmdir_wrapper, &wrap,
|
||||||
free(h->fullcgpath);
|
"cgroup_rmdir_wrapper");
|
||||||
h->fullcgpath = NULL;
|
else
|
||||||
}
|
ret = cgroup_rmdir(d->container_cgroup);
|
||||||
}
|
if (ret < 0) {
|
||||||
|
WARN("Failed to destroy cgroups");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_handler_data(d);
|
free_handler_data(d);
|
||||||
|
Loading…
Reference in New Issue
Block a user