Commit 0a83cbbb by Serge Hallyn

snapshot: enforce keeping same backing store type (v2)

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: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com>
parent a771fe18
...@@ -476,6 +476,7 @@ static const struct bdev_ops dir_ops = { ...@@ -476,6 +476,7 @@ static const struct bdev_ops dir_ops = {
.clone_paths = &dir_clonepaths, .clone_paths = &dir_clonepaths,
.destroy = &dir_destroy, .destroy = &dir_destroy,
.create = &dir_create, .create = &dir_create,
.can_snapshot = false,
}; };
...@@ -733,6 +734,7 @@ static const struct bdev_ops zfs_ops = { ...@@ -733,6 +734,7 @@ static const struct bdev_ops zfs_ops = {
.clone_paths = &zfs_clonepaths, .clone_paths = &zfs_clonepaths,
.destroy = &zfs_destroy, .destroy = &zfs_destroy,
.create = &zfs_create, .create = &zfs_create,
.can_snapshot = true,
}; };
// //
...@@ -1132,6 +1134,7 @@ static const struct bdev_ops lvm_ops = { ...@@ -1132,6 +1134,7 @@ static const struct bdev_ops lvm_ops = {
.clone_paths = &lvm_clonepaths, .clone_paths = &lvm_clonepaths,
.destroy = &lvm_destroy, .destroy = &lvm_destroy,
.create = &lvm_create, .create = &lvm_create,
.can_snapshot = true,
}; };
// //
...@@ -1429,6 +1432,7 @@ static const struct bdev_ops btrfs_ops = { ...@@ -1429,6 +1432,7 @@ static const struct bdev_ops btrfs_ops = {
.clone_paths = &btrfs_clonepaths, .clone_paths = &btrfs_clonepaths,
.destroy = &btrfs_destroy, .destroy = &btrfs_destroy,
.create = &btrfs_create, .create = &btrfs_create,
.can_snapshot = true,
}; };
// //
...@@ -1699,6 +1703,7 @@ static const struct bdev_ops loop_ops = { ...@@ -1699,6 +1703,7 @@ static const struct bdev_ops loop_ops = {
.clone_paths = &loop_clonepaths, .clone_paths = &loop_clonepaths,
.destroy = &loop_destroy, .destroy = &loop_destroy,
.create = &loop_create, .create = &loop_create,
.can_snapshot = false,
}; };
// //
...@@ -1932,6 +1937,7 @@ static const struct bdev_ops overlayfs_ops = { ...@@ -1932,6 +1937,7 @@ static const struct bdev_ops overlayfs_ops = {
.clone_paths = &overlayfs_clonepaths, .clone_paths = &overlayfs_clonepaths,
.destroy = &overlayfs_destroy, .destroy = &overlayfs_destroy,
.create = &overlayfs_create, .create = &overlayfs_create,
.can_snapshot = true,
}; };
static const struct bdev_type bdevs[] = { static const struct bdev_type bdevs[] = {
...@@ -2012,11 +2018,14 @@ struct bdev *bdev_init(const char *src, const char *dst, const char *data) ...@@ -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, struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname,
const char *oldpath, const char *lxcpath, const char *bdevtype, 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) int *needs_rdep)
{ {
struct bdev *orig, *new; struct bdev *orig, *new;
pid_t pid; 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 /* 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 * 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, ...@@ -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 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"; bdevtype = "overlayfs";
*needs_rdep = 0; *needs_rdep = 0;
......
...@@ -62,6 +62,7 @@ struct bdev_ops { ...@@ -62,6 +62,7 @@ struct bdev_ops {
int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname, int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, const char *cname, const char *oldpath, const char *lxcpath,
int snap, unsigned long newsize); 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); ...@@ -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, struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname,
const char *oldpath, const char *lxcpath, const char *bdevtype, 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); int *needs_rdep);
struct bdev *bdev_create(const char *dest, const char *type, struct bdev *bdev_create(const char *dest, const char *type,
const char *cname, struct bdev_specs *specs); const char *cname, struct bdev_specs *specs);
......
...@@ -2282,7 +2282,7 @@ static int copy_storage(struct lxc_container *c0, struct lxc_container *c, ...@@ -2282,7 +2282,7 @@ static int copy_storage(struct lxc_container *c0, struct lxc_container *c,
int need_rdep; int need_rdep;
bdev = bdev_copy(c0->lxc_conf->rootfs.path, c0->name, c->name, 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); bdevdata, newsize, &need_rdep);
if (!bdev) { if (!bdev) {
ERROR("Error copying storage"); ERROR("Error copying storage");
...@@ -2624,7 +2624,12 @@ static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile) ...@@ -2624,7 +2624,12 @@ static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
if (ret < 0 || ret >= 20) if (ret < 0 || ret >= 20)
return -1; 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); c2 = c->clone(c, newname, snappath, flags, NULL, NULL, 0, NULL);
if (!c2) { if (!c2) {
ERROR("clone of %s:%s failed\n", c->config_path, c->name); ERROR("clone of %s:%s failed\n", c->config_path, c->name);
......
...@@ -36,7 +36,9 @@ extern "C" { ...@@ -36,7 +36,9 @@ extern "C" {
#define LXC_CLONE_KEEPNAME (1 << 0) /*!< Do not edit the rootfs to change the hostname */ #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_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_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_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 */ #define LXC_CREATE_MAXFLAGS (1 << 1) /*!< Number of \c LXC_CREATE* flags */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment