.clone_paths = &dir_clonepaths,
.destroy = &dir_destroy,
.create = &dir_create,
+ .can_snapshot = false,
};
.clone_paths = &zfs_clonepaths,
.destroy = &zfs_destroy,
.create = &zfs_create,
+ .can_snapshot = true,
};
//
.clone_paths = &lvm_clonepaths,
.destroy = &lvm_destroy,
.create = &lvm_create,
+ .can_snapshot = true,
};
//
.clone_paths = &btrfs_clonepaths,
.destroy = &btrfs_destroy,
.create = &btrfs_create,
+ .can_snapshot = true,
};
//
.clone_paths = &loop_clonepaths,
.destroy = &loop_destroy,
.create = &loop_create,
+ .can_snapshot = false,
};
//
.clone_paths = &overlayfs_clonepaths,
.destroy = &overlayfs_destroy,
.create = &overlayfs_create,
+ .can_snapshot = true,
};
static const struct bdev_type bdevs[] = {
*/
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
}
}
+ /*
+ * 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;
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;
};
/*
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);
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");
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);
#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 */