When creating ephemeral containers that have the option lxc.ephemeral = 1 set in their config, they will be destroyed on shutdown. As they are simple overlay clones of an existing container they should be registered in the lxc_snapshots file of the original container to stay consistent and adhere to the expectancies of the users. Most of all, it ensure that we cannot remove a container that has clones, even if they are just ephemeral snapshot-clones. The function adds further consistency because remove_snapshots_entry() ensures that ephemeral clone-snapshots deregister themselves from the lxc_snapshots file when they are destroyed.
Signed-off-by: Christian Brauner <christianvanbrau...@gmail.com> --- src/lxc/start.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/src/lxc/start.c b/src/lxc/start.c index 8fe08a1..f58d9a4 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -33,6 +33,7 @@ #include <fcntl.h> #include <grp.h> #include <poll.h> +#include <sys/mman.h> #include <sys/param.h> #include <sys/file.h> #include <sys/mount.h> @@ -83,6 +84,7 @@ const struct ns_info ns_info[LXC_NS_MAX] = { [LXC_NS_NET] = {"net", CLONE_NEWNET} }; +static void remove_snapshot_entry(struct lxc_handler *handler, const char *name); static bool do_destroy_container(struct lxc_conf *conf); static int lxc_rmdir_onedev_wrapper(void *data); static void lxc_destroy_container_on_signal(struct lxc_handler *handler, @@ -1322,6 +1324,8 @@ static void lxc_destroy_container_on_signal(struct lxc_handler *handler, return; } + remove_snapshot_entry(handler, name); + if (am_unpriv()) ret = userns_exec_1(handler->conf, lxc_rmdir_onedev_wrapper, destroy); else @@ -1349,3 +1353,122 @@ static bool do_destroy_container(struct lxc_conf *conf) { return bdev_destroy(conf); } +static void remove_snapshot_entry(struct lxc_handler *handler, const char *name) +{ + char rdepfile[MAXPATHLEN]; + char path[MAXPATHLEN]; + char newpath[MAXPATHLEN]; + char *base = NULL; + char *buf = NULL; + char *del = NULL; + char *scratch = NULL; + char *origpath = NULL; + char *origname = NULL; + int ret = 0; + int bytes = 0; + int fd = -1; + size_t len = 0; + struct stat fbuf; + + ret = snprintf(rdepfile, MAXPATHLEN, "%s/%s/lxc_rdepends", handler->lxcpath, name); + if (ret < 0 || ret >= MAXPATHLEN) + return; + + fd = open(rdepfile, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return; + + ret = fstat(fd, &fbuf); + if (ret < 0) { + close(fd); + return; + } + + base = calloc(fbuf.st_size + 1, sizeof(char)); + if (!base) { + close(fd); + return; + } + + ret = read(fd, (void *)base, fbuf.st_size); + if (ret <= 0) { + free(base); + close(fd); + return; + } + + origpath = strtok_r(base, "\n", &scratch); + if (!origpath) { + free(base); + close(fd); + return; + } + + origname = strtok_r(NULL, "\n", &scratch); + if (!origname) { + free(base); + close(fd); + return; + } + + close(fd); + + ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", origpath, origname); + if (ret < 0 || ret >= MAXPATHLEN) { + free(base); + return; + } + free(base); + + ret = snprintf(newpath, MAXPATHLEN, "%s\n%s\n", handler->lxcpath, name); + if (ret < 0 || ret >= MAXPATHLEN) + return; + + fd = open(path, O_RDWR | O_CLOEXEC); + if (fd < 0) + return; + + ret = fstat(fd, &fbuf); + if (ret < 0) { + close(fd); + return; + } + + if (fbuf.st_size != 0) { + /* write terminating \0-byte to file */ + if (pwrite(fd, "", 1, fbuf.st_size) <= 0) { + close(fd); + return; + } + + buf = mmap(NULL, fbuf.st_size + 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (buf == MAP_FAILED) { + SYSERROR("Failed to create mapping %s", path); + close(fd); + return; + } + + len = strlen(newpath); + while ((del = strstr((char *)buf, newpath))) { + memmove(del, del + len, strlen(del) - len + 1); + bytes += len; + } + + munmap(buf, fbuf.st_size + 1); + if (ftruncate(fd, fbuf.st_size - bytes) < 0) { + SYSERROR("Failed to truncate file %s", path); + close(fd); + return; + } + } + + close(fd); + + /* If the lxc-snapshot file is empty, remove it. */ + if (stat(path, &fbuf) < 0) + return; + if (!fbuf.st_size) { + remove(path); + } +} + -- 2.5.1 _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel