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 | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/lxc/start.c b/src/lxc/start.c index 93c039c..f58d9a4 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -84,7 +84,7 @@ const struct ns_info ns_info[LXC_NS_MAX] = { [LXC_NS_NET] = {"net", CLONE_NEWNET} }; -static void update_clone_snapshots(struct lxc_handler *handler, const char *name); +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, @@ -1324,7 +1324,7 @@ static void lxc_destroy_container_on_signal(struct lxc_handler *handler, return; } - update_clone_snapshots(handler, name); + remove_snapshot_entry(handler, name); if (am_unpriv()) ret = userns_exec_1(handler->conf, lxc_rmdir_onedev_wrapper, destroy); @@ -1353,7 +1353,7 @@ static bool do_destroy_container(struct lxc_conf *conf) { return bdev_destroy(conf); } -static void update_clone_snapshots(struct lxc_handler *handler, const char *name) +static void remove_snapshot_entry(struct lxc_handler *handler, const char *name) { char rdepfile[MAXPATHLEN]; char path[MAXPATHLEN]; @@ -1365,9 +1365,9 @@ static void update_clone_snapshots(struct lxc_handler *handler, const char *name char *origpath = NULL; char *origname = NULL; int ret = 0; + int bytes = 0; int fd = -1; size_t len = 0; - size_t difflen = 0; struct stat fbuf; ret = snprintf(rdepfile, MAXPATHLEN, "%s/%s/lxc_rdepends", handler->lxcpath, name); @@ -1435,7 +1435,13 @@ static void update_clone_snapshots(struct lxc_handler *handler, const char *name } if (fbuf.st_size != 0) { - buf = mmap(NULL, fbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 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); @@ -1443,25 +1449,16 @@ static void update_clone_snapshots(struct lxc_handler *handler, const char *name } len = strlen(newpath); + while ((del = strstr((char *)buf, newpath))) { + memmove(del, del + len, strlen(del) - len + 1); + bytes += len; + } - /* mmap()ed memory is only \0-terminated when it is not - * a multiple of a pagesize. Hence, we'll use memmem(). */ - if ((del = memmem(buf, fbuf.st_size, newpath, len))) { - /* remove container entry */ - if (del != buf + fbuf.st_size - len) { - difflen = fbuf.st_size - (del - buf); - memmove(del, del + len, strnlen(del, difflen) - len); - } - - munmap(buf, fbuf.st_size); - - if (ftruncate(fd, fbuf.st_size - len) < 0) { - SYSERROR("Failed to truncate file %s", path); - close(fd); - return; - } - } else { - munmap(buf, fbuf.st_size); + munmap(buf, fbuf.st_size + 1); + if (ftruncate(fd, fbuf.st_size - bytes) < 0) { + SYSERROR("Failed to truncate file %s", path); + close(fd); + return; } } -- 2.5.1 _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel