[lxc-devel] [PATCH] Add remove_snapshots_entry() (rebased - v2)

Christian Brauner christianvanbrauner at gmail.com
Mon Sep 14 23:25:09 UTC 2015


On Mon, Sep 14, 2015 at 10:54:34PM +0000, Serge Hallyn wrote:
> Does it help if we simply define c->delete_with_snapshot_clones(), and have
> src/lxc/destroy.c use that?  Then we can contain mod_all_rdeps to being a
> static function in src/lxc/lxccontainer.c  If not, remind me where else we
> would've needed the mod_all_rdeps?

lxc_destroy.c does not call mod_all_rdeps() directly at all. It reads in the
lxc_snapshots file from the container all at once and finds each container
listed in it and passes it to c->destroy(c). So we should be good regarding
locks on this side. Here is the relevant bit from lxc_destroy.c (omitting the
reading in part of the lxc_snapshots file):

		while ((lxcpath = strtok_r(!counter ? buf : NULL, "\n", &scratch))) {
			if (!(lxcname = strtok_r(NULL, "\n", &scratch)))
				break;
			c1 = lxc_container_new(lxcname, lxcpath);
			if (!c1)
				goto next;
			if (!c1->destroy(c1)) {
				fprintf(stderr, "Destroying snapshot %s of %s failed\n", lxcname, my_args.name);
				lxc_container_put(c1);
				free(buf);
				return -1;
			}
			lxc_container_put(c1);
next:
			counter++;
		}

What I was worried about is the implementation in start.c:

When we have ephemeral containers that delete themselves we need to make sure
that they update the lxc_snapshots file before they die. One way to achieve this
is to have a mod_all_rdeps() version or something similar in start.c.
Specifically modifying this function to update the lxc_snapshots file:

        static void lxc_destroy_container_on_signal(struct lxc_handler *handler,
        					    const char *name)
        {
        	char destroy[MAXPATHLEN];
        	bool bret = true;
        	int ret = 0;
        	struct lxc_container *c;
        	if (handler->conf && handler->conf->rootfs.path && handler->conf->rootfs.mount) {
        		bret = do_destroy_container(handler->conf);
        		if (!bret) {
        			ERROR("Error destroying rootfs for %s", name);
        			return;
        		}
        	}
        	INFO("Destroyed rootfs for %s", name);
        
        	ret = snprintf(destroy, MAXPATHLEN, "%s/%s", handler->lxcpath, name);
        	if (ret < 0 || ret >= MAXPATHLEN) {
        		ERROR("Error printing path for %s", name);
        		ERROR("Error destroying directory for %s", name);
        		return;
        	}
        
        	c = lxc_container_new(name, handler->lxcpath);
        	if (c) {
        		if (container_disk_lock(c)) {
        			INFO("Could not update lxc_snapshots file");
        			lxc_container_put(c);
        		} else {
        			mod_all_rdeps(c, false);
        			container_disk_unlock(c);
        			lxc_container_put(c);
        		}
        	}
        
Right here we should update the lxc_snapshots file. Making mod_all_rdeps() is
the option you suggested. We can either have a special function for start.c or
make one of the functions mod_all_rdeps() or mod_rdep() public. Making
mod_rdep() or mod_all_rdeps() public involves binding in the lxccontainer.h file
into place we might not want them. So the easiest thing seems to be to have a
mod_rdep() function specific to start.c which takes in a lxc_container struct
and protects it with container_disk_lock(). Or do you have another idea?

        	if (am_unpriv())
        		ret = userns_exec_1(handler->conf, lxc_rmdir_onedev_wrapper, destroy);
        	else
        		ret = lxc_rmdir_onedev(destroy, NULL);
        
        	if (ret < 0) {
        		ERROR("Error destroying directory for %s", name);
        		return;
        	}
        	INFO("Destroyed directory for %s", name);
        }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20150915/8c2e9ee9/attachment.sig>


More information about the lxc-devel mailing list