]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
snapshot: enforce keeping same backing store type (v2)
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 1 Jan 2014 19:43:35 +0000 (13:43 -0600)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Thu, 2 Jan 2014 18:12:42 +0000 (12:12 -0600)
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 <serge.hallyn@ubuntu.com>
src/lxc/bdev.c
src/lxc/bdev.h
src/lxc/lxccontainer.c
src/lxc/lxccontainer.h

index 477011734026d720a86f77e673cf74df4a73bdd8..f5d750d6ad99d0b0c8f0d74676cc60c52e5da060 100644 (file)
@@ -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
@@ -2049,10 +2058,18 @@ 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;
index f4b3d29c4eacfc27d3fe79784d4bd3ba32d4bcd2..f4c0214dda4e70cfc3c433f452be73b00f86068c 100644 (file)
@@ -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);
index e991e59da4f6ffa67da07698059aa0ce056b1754..75f6ce363de05bbff150491d5f3dfc60dafd6de3 100644 (file)
@@ -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);
index f62ff8fd164497d8395a1299246bd8aab28ce52c..fe2dbc2395d5cfacf8a1234feaeb915700cf0b13 100644 (file)
@@ -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 */