The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/1761
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Signed-off-by: Christian Brauner <[email protected]>
From 6b89f639d46ad52dfbdd6a7bda27e1bcdff5fa53 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Fri, 25 Aug 2017 09:52:14 +0200 Subject: [PATCH 1/3] cgfsng: non-functional changes Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/cgroups/cgfsng.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index fc658faf2..e137b33c0 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -1199,6 +1199,7 @@ static void *cgfsng_init(struct lxc_handler *handler) static int cgroup_rmdir(char *dirname) { + int ret; struct dirent *direntp; DIR *dir; int r = 0; @@ -1208,8 +1209,8 @@ static int cgroup_rmdir(char *dirname) return -1; while ((direntp = readdir(dir))) { - struct stat mystat; char *pathname; + struct stat mystat; if (!direntp) break; @@ -1220,32 +1221,40 @@ static int cgroup_rmdir(char *dirname) pathname = must_make_path(dirname, direntp->d_name, NULL); - if (lstat(pathname, &mystat)) { + ret = lstat(pathname, &mystat); + if (ret < 0) { if (!r) - WARN("failed to stat %s", pathname); + WARN("Failed to stat %s", pathname); r = -1; goto next; } if (!S_ISDIR(mystat.st_mode)) goto next; - if (cgroup_rmdir(pathname) < 0) + + ret = cgroup_rmdir(pathname); + if (ret < 0) r = -1; next: free(pathname); } - if (rmdir(dirname) < 0) { + ret = rmdir(dirname); + if (ret < 0) { if (!r) - WARN("failed to delete %s: %s", dirname, strerror(errno)); + WARN("Failed to delete \"%s\": %s", dirname, + strerror(errno)); r = -1; } - if (closedir(dir) < 0) { + ret = closedir(dir); + if (ret < 0) { if (!r) - WARN("failed to delete %s: %s", dirname, strerror(errno)); + WARN("Failed to delete \"%s\": %s", dirname, + strerror(errno)); r = -1; } + return r; } From 631fc3b8075eac258a000de6327f089a96169054 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Fri, 25 Aug 2017 11:51:05 +0200 Subject: [PATCH 2/3] cgfsng: add container name to lxc.cgroup.dir value Say we have lxc.uts.name = c1 lxc.cgroup.dir = lxd the actual path should be lxd/c1 Right now it would just be lxd Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/cgroups/cgfsng.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index e137b33c0..fe3fd7062 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -1345,11 +1345,11 @@ static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname) */ static inline bool cgfsng_create(void *hdata) { - struct cgfsng_handler_data *d = hdata; - char *tmp, *cgname, *offset; int i; - int idx = 0; size_t len; + char *cgname, *offset, *tmp; + int idx = 0; + struct cgfsng_handler_data *d = hdata; if (!d) return false; @@ -1360,7 +1360,7 @@ static inline bool cgfsng_create(void *hdata) } if (d->cgroup_meta.dir) - tmp = strdup(d->cgroup_meta.dir); + tmp = lxc_string_join("/", (const char *[]){d->cgroup_meta.dir, d->name, NULL}, false); else tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern); if (!tmp) { From 0c5945aaadee5833cae5e927e5eba0cd5e17f5a9 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Fri, 25 Aug 2017 11:53:55 +0200 Subject: [PATCH 3/3] cgfsng: try to delete parent cgroups Say we have lxc.uts.name = c1 lxc.cgroup.dir = lxd/a/b/c the path for the container's cgroup would be lxd/a/b/c/c1 When the container is shutdown we should not just try to delete "c1" we should also try to delete "c", "b", "a", and "lxd". This is to ensure that we don't leave empty cgroups around thereby increasing the chance that we run into trouble with cgroup limits. The algorithm for this isn't too costly since we can simply stop walking upwards at the first rmdir() failure. Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/cgroups/cgfsng.c | 71 ++++++++++++++++++++++++++++++++++++++++++++---- src/lxc/confile.c | 3 -- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index fe3fd7062..8c7c8afbf 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -1272,16 +1272,18 @@ static int rmdir_wrapper(void *data) return cgroup_rmdir(path); } -void recursive_destroy(char *path, struct lxc_conf *conf) +int recursive_destroy(char *path, struct lxc_conf *conf) { int r; + if (conf && !lxc_list_empty(&conf->id_map)) r = userns_exec_1(conf, rmdir_wrapper, path, "rmdir_wrapper"); else r = cgroup_rmdir(path); - if (r < 0) ERROR("Error destroying %s", path); + + return r; } static void cgfsng_destroy(void *hdata, struct lxc_conf *conf) @@ -1293,13 +1295,70 @@ static void cgfsng_destroy(void *hdata, struct lxc_conf *conf) if (d->container_cgroup && hierarchies) { int i; + char *parent; + size_t recurse_upwards = 0; + + if (d->cgroup_meta.dir) + parent = d->cgroup_meta.dir; + else + parent = d->cgroup_pattern; + + /* skip slashes at beginning */ + while (*parent == '/') + parent++; + + /* Count the number of parent cgroups. */ + while ((parent = strchr(parent, '/'))) { + parent++; + + /* skip extraneous slashes */ + while (*parent == '/') + parent++; + + recurse_upwards++; + } + for (i = 0; hierarchies[i]; i++) { + int j, ret; struct hierarchy *h = hierarchies[i]; - if (h->fullcgpath) { - recursive_destroy(h->fullcgpath, conf); - free(h->fullcgpath); - h->fullcgpath = NULL; + + if (!h->fullcgpath) + continue; + + /* Delete the container's cgroup */ + ret = recursive_destroy(h->fullcgpath, conf); + if (ret < 0) + goto next; + + /* Delete parent cgroups as specified in the containers + * config file. This takes care of not having useless + * empty cgroups around. + */ + for (j = 0; j <= recurse_upwards; j++) { + char *s = h->fullcgpath; + + s = strrchr(s, '/'); + if (!s) + break; + *s = '\0'; + + /* If we fail to delete a cgroup we know that + * any parent cgroup also cannot be removed. + */ + ret = recursive_destroy(h->fullcgpath, conf); + if (ret < 0) + break; + + if (s == h->fullcgpath) + break; + s--; + while (*s == '/') + s--; } + +next: + free(h->fullcgpath); + h->fullcgpath = NULL; } } diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 62337289e..e66bae314 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -1431,9 +1431,6 @@ static int set_config_cgroup_dir(const char *key, const char *value, if (lxc_config_value_empty(value)) return clr_config_cgroup_dir(key, lxc_conf, NULL); - if (lxc_conf->cgroup_meta.dir) - clr_config_cgroup_dir(key, lxc_conf, NULL); - return set_config_string_item(&lxc_conf->cgroup_meta.dir, value); }
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
