From 6e54330c46bdfedaedbf4b677e557d550bdcb276 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 27 Jun 2018 11:37:57 +0200 Subject: [PATCH] conf: introduce lxc.rootfs.managed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This introduces a new config key lxc.rootfs.managed which can be used to indicate whether this LXC instance is managing the container storage. If LXC is not managing the storage then LXC will not modify the container storage. For example, an API call to c->destroy(c) will then run any destroy hooks but will not destroy the actual rootfs (Unless, of course, the hook does so behind LXC's back.). Signed-off-by: Christian Brauner CC: Wolfgang Bumiller CC: Stéphane Graber CC: Serge Hallyn CC: 2xsec --- src/lxc/conf.c | 1 + src/lxc/conf.h | 2 ++ src/lxc/confile.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/lxc/confile_utils.c | 15 +++++++++++++++ src/lxc/confile_utils.h | 1 + src/lxc/lxccontainer.c | 21 ++++++++++++++------- 6 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 3cbebfb6ad..ce63d5ba55 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2760,6 +2760,7 @@ struct lxc_conf *lxc_conf_init(void) free(new); return NULL; } + new->rootfs.managed = true; new->logfd = -1; lxc_list_init(&new->cgroup); lxc_list_init(&new->cgroup2); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 2c70303a21..6f947f1f35 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -154,6 +154,7 @@ struct lxc_tty_info { * @options : mount options * @mountflags : the portion of @options that are flags * @data : the porition of @options that are not flags + * @managed : whether it is managed by LXC */ struct lxc_rootfs { char *path; @@ -162,6 +163,7 @@ struct lxc_rootfs { char *options; unsigned long mountflags; char *data; + bool managed; }; /* diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 326782eac3..b24fcfe179 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -141,6 +141,7 @@ lxc_config_define(no_new_privs); lxc_config_define(personality); lxc_config_define(prlimit); lxc_config_define(pty_max); +lxc_config_define(rootfs_managed); lxc_config_define(rootfs_mount); lxc_config_define(rootfs_options); lxc_config_define(rootfs_path); @@ -226,6 +227,7 @@ static struct lxc_config_t config[] = { { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, }, { "lxc.prlimit", set_config_prlimit, get_config_prlimit, clr_config_prlimit, }, { "lxc.pty.max", set_config_pty_max, get_config_pty_max, clr_config_pty_max, }, + { "lxc.rootfs.managed", set_config_rootfs_managed, get_config_rootfs_managed, clr_config_rootfs_managed, }, { "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, clr_config_rootfs_mount, }, { "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, clr_config_rootfs_options, }, { "lxc.rootfs.path", set_config_rootfs_path, get_config_rootfs_path, clr_config_rootfs_path, }, @@ -2134,6 +2136,31 @@ static int set_config_rootfs_path(const char *key, const char *value, return ret; } +static int set_config_rootfs_managed(const char *key, const char *value, + struct lxc_conf *lxc_conf, void *data) +{ + unsigned int val = 0; + + if (lxc_config_value_empty(value)) { + lxc_conf->rootfs.managed = true; + return 0; + } + + if (lxc_safe_uint(value, &val) < 0) + return -EINVAL; + + switch (val) { + case 0: + lxc_conf->rootfs.managed = false; + return 0; + case 1: + lxc_conf->rootfs.managed = true; + return 0; + } + + return -EINVAL; +} + static int set_config_rootfs_mount(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { @@ -3356,6 +3383,12 @@ static int get_config_rootfs_path(const char *key, char *retv, int inlen, return lxc_get_conf_str(retv, inlen, c->rootfs.path); } +static int get_config_rootfs_managed(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) +{ + return lxc_get_conf_bool(c, retv, inlen, c->rootfs.managed); +} + static int get_config_rootfs_mount(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { @@ -3976,6 +4009,13 @@ static inline int clr_config_rootfs_path(const char *key, struct lxc_conf *c, return 0; } +static inline int clr_config_rootfs_managed(const char *key, struct lxc_conf *c, + void *data) +{ + c->rootfs.managed = true; + return 0; +} + static inline int clr_config_rootfs_mount(const char *key, struct lxc_conf *c, void *data) { diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c index 2bb46d17bc..a83d4aea92 100644 --- a/src/lxc/confile_utils.c +++ b/src/lxc/confile_utils.c @@ -672,6 +672,21 @@ int lxc_get_conf_str(char *retv, int inlen, const char *value) return value_len; } +int lxc_get_conf_bool(struct lxc_conf *c, char *retv, int inlen, bool v) +{ + int len; + int fulllen = 0; + + if (!retv) + inlen = 0; + else + memset(retv, 0, inlen); + + strprint(retv, inlen, "%d", v); + + return fulllen; +} + int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v) { int len; diff --git a/src/lxc/confile_utils.h b/src/lxc/confile_utils.h index b58ce47b2d..caa2b8849d 100644 --- a/src/lxc/confile_utils.h +++ b/src/lxc/confile_utils.h @@ -86,6 +86,7 @@ extern bool lxc_config_net_hwaddr(const char *line); extern void update_hwaddr(const char *line); extern bool new_hwaddr(char *hwaddr); extern int lxc_get_conf_str(char *retv, int inlen, const char *value); +extern int lxc_get_conf_bool(struct lxc_conf *c, char *retv, int inlen, bool v); extern int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v); extern int lxc_get_conf_size_t(struct lxc_conf *c, char *retv, int inlen, size_t v); extern int lxc_get_conf_uint64(struct lxc_conf *c, char *retv, int inlen, uint64_t v); diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 1b9c0fb6dd..4fb063462f 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -2973,6 +2973,10 @@ static bool container_destroy(struct lxc_container *c, } } + /* LXC is not managing the storage of the container. */ + if (conf && !conf->rootfs.managed) + goto on_success; + if (conf && conf->rootfs.path && conf->rootfs.mount) { if (!do_destroy_container(conf)) { ERROR("Error destroying rootfs for %s", c->name); @@ -3045,6 +3049,7 @@ static bool container_destroy(struct lxc_container *c, } INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name); +on_success: bret = true; out: @@ -3060,14 +3065,16 @@ static bool do_lxcapi_destroy(struct lxc_container *c) if (!c || !lxcapi_is_defined(c)) return false; - if (has_snapshots(c)) { - ERROR("Container %s has snapshots; not removing", c->name); - return false; - } + if (c->lxc_conf && c->lxc_conf->rootfs.managed) { + if (has_snapshots(c)) { + ERROR("Container %s has snapshots; not removing", c->name); + return false; + } - if (has_fs_snapshots(c)) { - ERROR("container %s has snapshots on its rootfs", c->name); - return false; + if (has_fs_snapshots(c)) { + ERROR("container %s has snapshots on its rootfs", c->name); + return false; + } } return container_destroy(c, NULL);