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);
        }

Attachment: signature.asc
Description: PGP signature

_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to