Stéphane noticed that lxc-snapshot of a dir-backed container created an overlayfs container. The expectation is that the user can continue to modify the original container and later make a new snapshot, but this doesn't work with the existing behavior - the overlayfs clone will end up with the modified contents.
So add a 'LXC_CLONE_KEEPBDEVTYPE' flag, which c->snapshot() passes to c->clone(). Also add a LXC_CLONE_MAYBE_SNAPSHOT. If this is set and a backing store does not support snapshotting, then proceed with a copy clone. Signed-off-by: Serge Hallyn <[email protected]> --- src/lxc/bdev.c | 21 +++++++++++++++++++-- src/lxc/bdev.h | 3 ++- src/lxc/lxccontainer.c | 9 +++++++-- src/lxc/lxccontainer.h | 4 +++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c index 4770117..f5d750d 100644 --- a/src/lxc/bdev.c +++ b/src/lxc/bdev.c @@ -476,6 +476,7 @@ static const struct bdev_ops dir_ops = { .clone_paths = &dir_clonepaths, .destroy = &dir_destroy, .create = &dir_create, + .can_snapshot = false, }; @@ -733,6 +734,7 @@ static const struct bdev_ops zfs_ops = { .clone_paths = &zfs_clonepaths, .destroy = &zfs_destroy, .create = &zfs_create, + .can_snapshot = true, }; // @@ -1132,6 +1134,7 @@ static const struct bdev_ops lvm_ops = { .clone_paths = &lvm_clonepaths, .destroy = &lvm_destroy, .create = &lvm_create, + .can_snapshot = true, }; // @@ -1429,6 +1432,7 @@ static const struct bdev_ops btrfs_ops = { .clone_paths = &btrfs_clonepaths, .destroy = &btrfs_destroy, .create = &btrfs_create, + .can_snapshot = true, }; // @@ -1699,6 +1703,7 @@ static const struct bdev_ops loop_ops = { .clone_paths = &loop_clonepaths, .destroy = &loop_destroy, .create = &loop_create, + .can_snapshot = false, }; // @@ -1932,6 +1937,7 @@ static const struct bdev_ops overlayfs_ops = { .clone_paths = &overlayfs_clonepaths, .destroy = &overlayfs_destroy, .create = &overlayfs_create, + .can_snapshot = true, }; static const struct bdev_type bdevs[] = { @@ -2012,11 +2018,14 @@ struct bdev *bdev_init(const char *src, const char *dst, const char *data) */ struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, const char *bdevtype, - int snap, const char *bdevdata, unsigned long newsize, + int flags, const char *bdevdata, unsigned long newsize, int *needs_rdep) { struct bdev *orig, *new; pid_t pid; + bool snap = flags & LXC_CLONE_SNAPSHOT; + bool maybe_snap = flags & LXC_CLONE_MAYBE_SNAPSHOT; + bool keepbdevtype = flags & LXC_CLONE_KEEPBDEVTYPE; /* if the container name doesn't show up in the rootfs path, then * we don't know how to come up with a new name @@ -2050,9 +2059,17 @@ struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname, } /* + * special case for snapshot - if caller requested maybe_snapshot and + * keepbdevtype and backing store is directory, then proceed with a copy + * clone rather than returning error + */ + if (maybe_snap && keepbdevtype && !bdevtype && !orig->ops->can_snapshot) + snap = false; + + /* * If newtype is NULL and snapshot is set, then use overlayfs */ - if (!bdevtype && snap && strcmp(orig->type , "dir") == 0) + if (!bdevtype && !keepbdevtype && snap && strcmp(orig->type , "dir") == 0) bdevtype = "overlayfs"; *needs_rdep = 0; diff --git a/src/lxc/bdev.h b/src/lxc/bdev.h index f4b3d29..f4c0214 100644 --- a/src/lxc/bdev.h +++ b/src/lxc/bdev.h @@ -62,6 +62,7 @@ struct bdev_ops { int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, unsigned long newsize); + bool can_snapshot; }; /* @@ -99,7 +100,7 @@ struct bdev *bdev_init(const char *src, const char *dst, const char *data); struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, const char *bdevtype, - int snap, const char *bdevdata, unsigned long newsize, + int flags, const char *bdevdata, unsigned long newsize, int *needs_rdep); struct bdev *bdev_create(const char *dest, const char *type, const char *cname, struct bdev_specs *specs); diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index e991e59..75f6ce3 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -2282,7 +2282,7 @@ static int copy_storage(struct lxc_container *c0, struct lxc_container *c, int need_rdep; bdev = bdev_copy(c0->lxc_conf->rootfs.path, c0->name, c->name, - c0->config_path, c->config_path, newtype, !!(flags & LXC_CLONE_SNAPSHOT), + c0->config_path, c->config_path, newtype, flags, bdevdata, newsize, &need_rdep); if (!bdev) { ERROR("Error copying storage"); @@ -2624,7 +2624,12 @@ static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile) if (ret < 0 || ret >= 20) return -1; - flags = LXC_CLONE_SNAPSHOT | LXC_CLONE_KEEPMACADDR | LXC_CLONE_KEEPNAME; + /* + * We pass LXC_CLONE_SNAPSHOT to make sure that a rdepends file entry is + * created in the original container + */ + flags = LXC_CLONE_SNAPSHOT | LXC_CLONE_KEEPMACADDR | LXC_CLONE_KEEPNAME | + LXC_CLONE_KEEPBDEVTYPE | LXC_CLONE_MAYBE_SNAPSHOT; c2 = c->clone(c, newname, snappath, flags, NULL, NULL, 0, NULL); if (!c2) { ERROR("clone of %s:%s failed\n", c->config_path, c->name); diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h index f62ff8f..fe2dbc2 100644 --- a/src/lxc/lxccontainer.h +++ b/src/lxc/lxccontainer.h @@ -36,7 +36,9 @@ extern "C" { #define LXC_CLONE_KEEPNAME (1 << 0) /*!< Do not edit the rootfs to change the hostname */ #define LXC_CLONE_KEEPMACADDR (1 << 1) /*!< Do not change the MAC address on network interfaces */ #define LXC_CLONE_SNAPSHOT (1 << 2) /*!< Snapshot the original filesystem(s) */ -#define LXC_CLONE_MAXFLAGS (1 << 3) /*!< Number of \c LXC_CLONE_* flags */ +#define LXC_CLONE_KEEPBDEVTYPE (1 << 3) /*!< Use the same bdev type */ +#define LXC_CLONE_MAYBE_SNAPSHOT (1 << 4) /*!< Snapshot only if bdev supports it, else copy */ +#define LXC_CLONE_MAXFLAGS (1 << 5) /*!< Number of \c LXC_CLONE_* flags */ #define LXC_CREATE_QUIET (1 << 0) /*!< Redirect \c stdin to \c /dev/zero and \c stdout and \c stderr to \c /dev/null */ #define LXC_CREATE_MAXFLAGS (1 << 1) /*!< Number of \c LXC_CREATE* flags */ -- 1.8.5.2 _______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
