[lxc-devel] [lxc/master] cgroups: implement monitor cgroup deletion
brauner on Github
lxc-bot at linuxcontainers.org
Sun Sep 23 22:08:47 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1074 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180923/c8868750/attachment.bin>
-------------- next part --------------
From a4e55b420a3d83166f0363922273e706fa479b04 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 23 Sep 2018 17:55:27 +0200
Subject: [PATCH 1/2] cgfsng: s/cgfsng_destroy/cgfsng_payload_destroy/g
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/cgroups/cgfsng.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 3df279377..1523e4d59 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1102,7 +1102,8 @@ static int cgroup_rmdir_wrapper(void *data)
return cgroup_rmdir(arg->hierarchies, arg->container_cgroup);
}
-__cgfsng_ops static void cgfsng_destroy(struct cgroup_ops *ops, struct lxc_handler *handler)
+__cgfsng_ops__ static void cgfsng_payload_destroy(struct cgroup_ops *ops,
+ struct lxc_handler *handler)
{
int ret;
struct generic_userns_exec_data wrap;
@@ -2672,7 +2673,7 @@ struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
}
cgfsng_ops->data_init = cgfsng_data_init;
- cgfsng_ops->destroy = cgfsng_destroy;
+ cgfsng_ops->destroy = cgfsng_payload_destroy;
cgfsng_ops->monitor_create = cgfsng_monitor_create;
cgfsng_ops->monitor_enter = cgfsng_monitor_enter;
cgfsng_ops->payload_create = cgfsng_payload_create;
From 79d2db4443f7ce4cfbf756e48930251de894c5c4 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 23 Sep 2018 20:11:56 +0200
Subject: [PATCH 2/2] cgfsng: add cgfsng_monitor_destroy()
Since we switched to the new cgroup scoping scheme that places the
container payload into lxc.payload/<container-name> and
lxc.monitor/<container-name> deletion becomes slightly more complicated.
The monitor will be able to rm_rf(lxc.payload/<container-name>) but will
not be able to rm_rf(lxc.monitor/<container-name>) since it will be
located in that cgroup and it will thus be populated.
My current solution to this is to create a lxc.pivot cgroup that only
exists so that the monitor process on container stop can pivot into it,
call rm_rf(lxc.monitor/<container-name>) and can then exit. This group
has not function whatsoever apart from this and can thus be shared by
all monitor processes.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/cgroups/cgfsng.c | 62 ++++++++++++++++++++++++++++++++++++++--
src/lxc/cgroups/cgroup.h | 3 +-
src/lxc/start.c | 13 ++++++---
src/lxc/start.h | 3 ++
4 files changed, 73 insertions(+), 8 deletions(-)
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 1523e4d59..dd27860bc 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1102,8 +1102,8 @@ static int cgroup_rmdir_wrapper(void *data)
return cgroup_rmdir(arg->hierarchies, arg->container_cgroup);
}
-__cgfsng_ops__ static void cgfsng_payload_destroy(struct cgroup_ops *ops,
- struct lxc_handler *handler)
+__cgfsng_ops static void cgfsng_payload_destroy(struct cgroup_ops *ops,
+ struct lxc_handler *handler)
{
int ret;
struct generic_userns_exec_data wrap;
@@ -1124,6 +1124,61 @@ __cgfsng_ops__ static void cgfsng_payload_destroy(struct cgroup_ops *ops,
}
}
+__cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops,
+ struct lxc_handler *handler)
+{
+ int len;
+ char *pivot_path;
+ struct lxc_conf *conf = handler->conf;
+ char pidstr[25];
+
+ if (!ops->hierarchies)
+ return;
+
+ len = snprintf(pidstr, 25, "%d", handler->monitor_pid);
+ if (len < 0 || len >= 25)
+ return;
+
+ for (int i = 0; ops->hierarchies[i]; i++) {
+ int ret;
+ char *monitor_cgroup;
+ struct hierarchy *h = ops->hierarchies[i];
+
+ if (!h->monitor_full_path)
+ continue;
+
+ if (conf && conf->cgroup_meta.dir)
+ monitor_cgroup = lxc_string_join("/",
+ (const char *[]){conf->cgroup_meta.dir,
+ "lxc.pivot",
+ NULL},
+ false);
+ else
+ monitor_cgroup = must_make_path("lxc.pivot", NULL);
+ if (!monitor_cgroup)
+ return;
+
+ pivot_path = must_make_path(h->mountpoint, h->container_base_path,
+ monitor_cgroup, "cgroup.procs", NULL);
+ free(monitor_cgroup);
+
+ ret = mkdir_p(pivot_path, 0755);
+ if (ret < 0 && errno != EEXIST)
+ goto next;
+
+ ret = lxc_write_to_file(pivot_path, pidstr, len, false, 0666);
+ if (ret != 0)
+ goto next;
+
+ ret = recursive_destroy(h->monitor_full_path);
+ if (ret < 0)
+ WARN("Failed to destroy \"%s\"", h->monitor_full_path);
+
+ next:
+ free(pivot_path);
+ }
+}
+
static bool cg_unified_create_cgroup(struct hierarchy *h, char *cgname)
{
size_t i, parts_len;
@@ -2673,7 +2728,8 @@ struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
}
cgfsng_ops->data_init = cgfsng_data_init;
- cgfsng_ops->destroy = cgfsng_payload_destroy;
+ cgfsng_ops->payload_destroy = cgfsng_payload_destroy;
+ cgfsng_ops->monitor_destroy = cgfsng_monitor_destroy;
cgfsng_ops->monitor_create = cgfsng_monitor_create;
cgfsng_ops->monitor_enter = cgfsng_monitor_enter;
cgfsng_ops->payload_create = cgfsng_payload_create;
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index 16b880942..f40313aed 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -128,7 +128,8 @@ struct cgroup_ops {
cgroup_layout_t cgroup_layout;
bool (*data_init)(struct cgroup_ops *ops);
- void (*destroy)(struct cgroup_ops *ops, struct lxc_handler *handler);
+ void (*payload_destroy)(struct cgroup_ops *ops, struct lxc_handler *handler);
+ void (*monitor_destroy)(struct cgroup_ops *ops, struct lxc_handler *handler);
bool (*monitor_create)(struct cgroup_ops *ops, struct lxc_handler *handler);
bool (*monitor_enter)(struct cgroup_ops *ops, pid_t pid);
bool (*payload_create)(struct cgroup_ops *ops, struct lxc_handler *handler);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 0629e90c4..27b677f72 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -725,6 +725,8 @@ int lxc_init(const char *name, struct lxc_handler *handler)
const char *loglevel;
struct lxc_conf *conf = handler->conf;
+ handler->monitor_pid = lxc_raw_getpid();
+
lsm_init();
TRACE("Initialized LSM");
@@ -857,7 +859,8 @@ int lxc_init(const char *name, struct lxc_handler *handler)
return 0;
out_destroy_cgroups:
- handler->cgroup_ops->destroy(handler->cgroup_ops, handler);
+ handler->cgroup_ops->payload_destroy(handler->cgroup_ops, handler);
+ handler->cgroup_ops->monitor_destroy(handler->cgroup_ops, handler);
out_delete_terminal:
lxc_terminal_delete(&handler->conf->console);
@@ -951,8 +954,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
lsm_process_cleanup(handler->conf, handler->lxcpath);
- cgroup_ops->destroy(cgroup_ops, handler);
- cgroup_exit(cgroup_ops);
+ cgroup_ops->payload_destroy(cgroup_ops, handler);
if (handler->conf->reboot == REBOOT_NONE) {
/* For all new state clients simply close the command socket.
@@ -1022,6 +1024,9 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
if (handler->conf->ephemeral == 1 && handler->conf->reboot != REBOOT_REQ)
lxc_destroy_container_on_signal(handler, name);
+ cgroup_ops->monitor_destroy(cgroup_ops, handler);
+ cgroup_exit(cgroup_ops);
+
lxc_free_handler(handler);
}
@@ -1971,7 +1976,7 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
goto out_fini_nonet;
}
- if (!cgroup_ops->monitor_enter(cgroup_ops, lxc_raw_getpid())) {
+ if (!cgroup_ops->monitor_enter(cgroup_ops, handler->monitor_pid)) {
ERROR("Failed to enter monitor cgroup");
goto out_fini_nonet;
}
diff --git a/src/lxc/start.h b/src/lxc/start.h
index bcb852e8b..c3e68f3ae 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -103,6 +103,9 @@ struct lxc_handler {
/* The child's pid. */
pid_t pid;
+ /* The monitor's pid. */
+ pid_t monitor_pid;
+
/* Whether the child has already exited. */
bool init_died;
More information about the lxc-devel
mailing list