Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
{ .name = "rbd", .ops = &rbd_ops, },
{ .name = "btrfs", .ops = &btrfs_ops, },
{ .name = "aufs", .ops = &aufs_ops, },
{ .name = "rbd", .ops = &rbd_ops, },
{ .name = "btrfs", .ops = &btrfs_ops, },
{ .name = "aufs", .ops = &aufs_ops, },
+ { .name = "overlay", .ops = &ovl_ops, },
{ .name = "overlayfs", .ops = &ovl_ops, },
{ .name = "loop", .ops = &loop_ops, },
{ .name = "nbd", .ops = &nbd_ops, },
{ .name = "overlayfs", .ops = &ovl_ops, },
{ .name = "loop", .ops = &loop_ops, },
{ .name = "nbd", .ops = &nbd_ops, },
*/
if (!bdevtype && !keepbdevtype && snap &&
strcmp(orig->type, "dir") == 0)
*/
if (!bdevtype && !keepbdevtype && snap &&
strcmp(orig->type, "dir") == 0)
- bdevtype = "overlayfs";
if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
- ERROR("Unsupported snapshot type for unprivileged users");
+ ERROR("Unsupported snapshot type \"%s\" for unprivileged users",
+ bdevtype ? bdevtype : "(null)");
bdev_put(orig);
return NULL;
}
bdev_put(orig);
return NULL;
}
*needs_rdep = 0;
if (bdevtype && strcmp(orig->type, "dir") == 0 &&
(strcmp(bdevtype, "aufs") == 0 ||
*needs_rdep = 0;
if (bdevtype && strcmp(orig->type, "dir") == 0 &&
(strcmp(bdevtype, "aufs") == 0 ||
- strcmp(bdevtype, "overlayfs") == 0)) {
+ strcmp(bdevtype, "overlayfs") == 0 ||
+ strcmp(bdevtype, "overlay") == 0)) {
*needs_rdep = 1;
} else if (snap && strcmp(orig->type, "lvm") == 0 &&
!lvm_is_thin_volume(orig->src)) {
*needs_rdep = 1;
} else if (snap && strcmp(orig->type, "lvm") == 0 &&
!lvm_is_thin_volume(orig->src)) {
- src_no_prefix = lxc_storage_get_path(new->src, new->type);
-
+ if (!strcmp(new->type, "overlay") || !strcmp(new->type, "overlayfs"))
+ src_no_prefix = ovl_get_lower(new->src);
+ else
+ src_no_prefix = lxc_storage_get_path(new->src, new->type);
if (am_unpriv() && chown_mapped_root(src_no_prefix, c0->lxc_conf) < 0)
WARN("Failed to update ownership of %s", new->dest);
if (am_unpriv() && chown_mapped_root(src_no_prefix, c0->lxc_conf) < 0)
WARN("Failed to update ownership of %s", new->dest);
#include "lxccontainer.h"
#include "lxcoverlay.h"
#include "lxcrsync.h"
#include "lxccontainer.h"
#include "lxcoverlay.h"
#include "lxcrsync.h"
+#include "storage_utils.h"
#include "utils.h"
lxc_log_define(lxcoverlay, lxc);
#include "utils.h"
lxc_log_define(lxcoverlay, lxc);
static char *ovl_name;
static char *ovl_version[] = {"overlay", "overlayfs"};
static char *ovl_name;
static char *ovl_version[] = {"overlay", "overlayfs"};
-/* defined in lxccontainer.c: needs to become common helper */
-extern char *dir_new_path(char *src, const char *oldname, const char *name,
- const char *oldpath, const char *lxcpath);
-
static char *ovl_detect_name(void);
static int ovl_do_rsync(struct bdev *orig, struct bdev *new,
struct lxc_conf *conf);
static char *ovl_detect_name(void);
static int ovl_do_rsync(struct bdev *orig, struct bdev *new,
struct lxc_conf *conf);
- ERROR("overlayfs is only for snapshot clones");
+ ERROR("overlay is only for snapshot clones");
return -22;
}
if (!orig->src || !orig->dest)
return -1;
return -22;
}
if (!orig->src || !orig->dest)
return -1;
- new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath);
+ new->dest = lxc_string_join(
+ "/", (const char *[]){lxcpath, cname, "rootfs", NULL}, false);
if (!new->dest)
return -1;
if (!new->dest)
return -1;
if (mkdir_p(new->dest, 0755) < 0)
return -1;
if (mkdir_p(new->dest, 0755) < 0)
return -1;
free(delta);
return -ENOMEM;
}
free(delta);
return -ENOMEM;
}
- ret = snprintf(new->src, len, "overlayfs:%s:%s", src, delta);
+ ret = snprintf(new->src, len, "overlay:%s:%s", src, delta);
free(delta);
if (ret < 0 || ret >= len)
free(delta);
if (ret < 0 || ret >= len)
- return -ENOMEM;
- } else if (strcmp(orig->type, "overlayfs") == 0) {
+ return -1;
+ } else if (!strcmp(orig->type, "overlayfs") || !strcmp(orig->type, "overlay")) {
/*
* What exactly do we want to do here? I think we want to use
* the original lowerdir, with a private delta which is
/*
* What exactly do we want to do here? I think we want to use
* the original lowerdir, with a private delta which is
char *osrc, *odelta, *nsrc, *ndelta, *work;
char *lastslash;
int len, ret, lastslashidx;
char *osrc, *odelta, *nsrc, *ndelta, *work;
char *lastslash;
int len, ret, lastslashidx;
- if (!(osrc = strdup(orig->src)))
+
+ osrc = strdup(orig->src);
+ if (!osrc) {
+ SYSERROR("Failed to duplicate \"%s\"", orig->src);
nsrc = strchr(osrc, ':') + 1;
nsrc = strchr(osrc, ':') + 1;
- if (nsrc != osrc + 10 || (odelta = strchr(nsrc, ':')) == NULL) {
+ if ((nsrc != osrc + 8) && (nsrc != osrc + 10)) {
+ free(osrc);
+ ERROR("Detected \":\" in \"%s\" at wrong position", osrc);
+ return -22;
+ }
+
+ odelta = strchr(nsrc, ':');
+ if (!odelta) {
+ ERROR("Failed to find \":\" in \"%s\"", nsrc);
*odelta = '\0';
odelta++;
*odelta = '\0';
odelta++;
- ndelta = dir_new_path(odelta, oldname, cname, oldpath, lxcpath);
- if (!ndelta) {
+ ndelta = lxc_string_join("/", (const char *[]){lxcpath, cname, "rootfs", NULL}, false);
+ if (!ndelta) {
+ ERROR("Failed to create new path");
- }
- if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) {
- SYSERROR("error: mkdir %s", ndelta);
+ }
+
+ ret = mkdir(ndelta, 0755);
+ if (ret < 0 && errno != EEXIST) {
free(osrc);
free(ndelta);
free(osrc);
free(ndelta);
+ SYSERROR("Failed to create \"%s\"", ndelta);
if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
WARN("Failed to update ownership of %s", ndelta);
if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
WARN("Failed to update ownership of %s", ndelta);
if (!lastslash) {
free(osrc);
free(ndelta);
if (!lastslash) {
free(osrc);
free(ndelta);
+ ERROR("Failed to detect \"/\" in \"%s\"", ndelta);
return -1;
}
lastslash++;
return -1;
}
lastslash++;
if (!work) {
free(osrc);
free(ndelta);
if (!work) {
free(osrc);
free(ndelta);
+ ERROR("Failed to allocate memory");
return -1;
}
strncpy(work, ndelta, lastslashidx + 1);
strcpy(work + lastslashidx, "olwork");
return -1;
}
strncpy(work, ndelta, lastslashidx + 1);
strcpy(work + lastslashidx, "olwork");
- if ((mkdir(work, 0755) < 0) && errno != EEXIST) {
- SYSERROR("error: mkdir %s", work);
+ ret = mkdir(work, 0755);
+ if (ret < 0 && errno != EEXIST) {
free(osrc);
free(ndelta);
free(work);
free(osrc);
free(ndelta);
free(work);
+ SYSERROR("Failed to create \"%s\"", ndelta);
if (am_unpriv() && chown_mapped_root(work, conf) < 0)
WARN("Failed to update ownership of %s", work);
free(work);
if (am_unpriv() && chown_mapped_root(work, conf) < 0)
WARN("Failed to update ownership of %s", work);
free(work);
- len = strlen(nsrc) + strlen(ndelta) + 12;
+ len = strlen(nsrc) + strlen(ndelta) + 10;
new->src = malloc(len);
if (!new->src) {
free(osrc);
free(ndelta);
new->src = malloc(len);
if (!new->src) {
free(osrc);
free(ndelta);
+ ERROR("Failed to allocate memory");
- ret = snprintf(new->src, len, "overlayfs:%s:%s", nsrc, ndelta);
+ ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
free(osrc);
free(ndelta);
free(osrc);
free(ndelta);
- if (ret < 0 || ret >= len)
- return -ENOMEM;
+ if (ret < 0 || ret >= len) {
+ ERROR("Failed to create string");
+ return -1;
+ }
return ovl_do_rsync(orig, new, conf);
} else {
return ovl_do_rsync(orig, new, conf);
} else {
- ERROR("overlayfs clone of %s container is not yet supported",
+ ERROR("overlay clone of %s container is not yet supported",
orig->type);
/*
* Note, supporting this will require ovl_mount supporting
orig->type);
/*
* Note, supporting this will require ovl_mount supporting
- * to say 'lxc-create -t ubuntu -n o1 -B overlayfs' means you want
+ * to say 'lxc-create -t ubuntu -n o1 -B overlay' means you want
* $lxcpath/$lxcname/rootfs to have the created container, while all
* changes after starting the container are written to
* $lxcpath/$lxcname/delta0
* $lxcpath/$lxcname/rootfs to have the created container, while all
* changes after starting the container are written to
* $lxcpath/$lxcname/delta0
- // overlayfs:lower:upper
- newlen = (2 * len) + strlen("overlayfs:") + 2;
+ // overlay:lower:upper
+ newlen = (2 * len) + strlen("overlay:") + 2;
bdev->src = malloc(newlen);
if (!bdev->src) {
ERROR("Out of memory");
return -1;
}
bdev->src = malloc(newlen);
if (!bdev->src) {
ERROR("Out of memory");
return -1;
}
- ret = snprintf(bdev->src, newlen, "overlayfs:%s:%s", dest, delta);
+ ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta);
if (ret < 0 || ret >= newlen)
return -1;
if (ret < 0 || ret >= newlen)
return -1;
int ovl_destroy(struct bdev *orig)
{
int ovl_destroy(struct bdev *orig)
{
+ bool ovl;
+ char *upper = orig->src;
- if (strncmp(orig->src, "overlayfs:", 10) != 0)
+ ovl = !strncmp(upper, "overlay:", 8);
+ if (!ovl && strncmp(upper, "overlayfs:", 10))
- upper = strchr(orig->src + 10, ':');
+
+ if (ovl)
+ upper += 8;
+ else
+ upper += 10;
+
+ upper = strchr(upper, ':');
if (!upper)
return -22;
upper++;
if (!upper)
return -22;
upper++;
return lxc_rmdir_onedev(upper, NULL);
}
return lxc_rmdir_onedev(upper, NULL);
}
-char *ovl_getlower(char *p)
-{
- char *p1 = strchr(p, ':');
- if (p1)
- *p1 = '\0';
- return p;
-}
-
int ovl_mount(struct bdev *bdev)
{
char *tmp, *options, *dup, *lower, *upper;
int ovl_mount(struct bdev *bdev)
{
char *tmp, *options, *dup, *lower, *upper;
char *mntdata;
int ret, ret2;
char *mntdata;
int ret, ret2;
- if (strcmp(bdev->type, "overlayfs"))
+ if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
if (!bdev->src || !bdev->dest)
return -22;
if (!bdev->src || !bdev->dest)
return -22;
ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
MS_MGC_VAL | mntflags, options_work);
if (ret < 0) {
ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
MS_MGC_VAL | mntflags, options_work);
if (ret < 0) {
- INFO("Overlayfs: Error mounting %s onto %s with options %s. "
+ INFO("Overlay: Error mounting %s onto %s with options %s. "
"Retrying without workdir: %s.",
lower, bdev->dest, options_work, strerror(errno));
"Retrying without workdir: %s.",
lower, bdev->dest, options_work, strerror(errno));
ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
MS_MGC_VAL | mntflags, options);
if (ret < 0)
ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
MS_MGC_VAL | mntflags, options);
if (ret < 0)
- SYSERROR("Overlayfs: Error mounting %s onto %s with "
+ SYSERROR("Overlay: Error mounting %s onto %s with "
"options %s: %s.",
lower, bdev->dest, options,
strerror(errno));
else
"options %s: %s.",
lower, bdev->dest, options,
strerror(errno));
else
- INFO("Overlayfs: Mounted %s onto %s with options %s.",
+ INFO("Overlay: Mounted %s onto %s with options %s.",
lower, bdev->dest, options);
} else {
lower, bdev->dest, options);
} else {
- INFO("Overlayfs: Mounted %s onto %s with options %s.", lower,
+ INFO("Overlay: Mounted %s onto %s with options %s.", lower,
bdev->dest, options_work);
}
return ret;
bdev->dest, options_work);
}
return ret;
int ovl_umount(struct bdev *bdev)
{
int ovl_umount(struct bdev *bdev)
{
- if (strcmp(bdev->type, "overlayfs"))
+ if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
if (!bdev->src || !bdev->dest)
return -22;
if (!bdev->src || !bdev->dest)
return -22;
return umount(bdev->dest);
}
return umount(bdev->dest);
}
+char *ovl_get_lower(const char *rootfs_path)
+{
+ char *s1;
+ s1 = strstr(rootfs_path, ":/");
+ if (!s1)
+ return NULL;
+ s1++;
+
+ s1 = strstr(s1, ":/");
+ if (!s1)
+ return NULL;
+ s1++;
+
+ return s1;
+}
+
char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
{
char *rootfsdir = NULL;
char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
{
char *rootfsdir = NULL;
else
ret = ovl_rsync(&rdata);
if (ret)
else
ret = ovl_rsync(&rdata);
if (ret)
- ERROR("copying overlayfs delta");
+ ERROR("copying overlay delta");
* To be called from functions in lxccontainer.c: Get lower directory for
* overlay rootfs.
*/
* To be called from functions in lxccontainer.c: Get lower directory for
* overlay rootfs.
*/
-char *ovl_getlower(char *p);
+char *ovl_get_lower(const char *rootfs_path);
/*
* Get rootfs path for overlay backed containers. Allocated memory must be freed
/*
* Get rootfs path for overlay backed containers. Allocated memory must be freed
// overlayfs -- which is also allowed)
if (strcmp(b->type, "dir") == 0 ||
strcmp(b->type, "aufs") == 0 ||
// overlayfs -- which is also allowed)
if (strcmp(b->type, "dir") == 0 ||
strcmp(b->type, "aufs") == 0 ||
+ strcmp(b->type, "overlay") == 0 ||
strcmp(b->type, "overlayfs") == 0 ||
strcmp(b->type, "btrfs") == 0 ||
strcmp(b->type, "loop") == 0)
strcmp(b->type, "overlayfs") == 0 ||
strcmp(b->type, "btrfs") == 0 ||
strcmp(b->type, "loop") == 0)
// and loop. In particular, not zfs, btrfs, or lvm.
if (strcmp(t, "dir") == 0 ||
strcmp(t, "aufs") == 0 ||
// and loop. In particular, not zfs, btrfs, or lvm.
if (strcmp(t, "dir") == 0 ||
strcmp(t, "aufs") == 0 ||
+ strcmp(t, "overlay") == 0 ||
strcmp(t, "overlayfs") == 0 ||
strcmp(t, "btrfs") == 0 ||
strcmp(t, "loop") == 0)
strcmp(t, "overlayfs") == 0 ||
strcmp(t, "btrfs") == 0 ||
strcmp(t, "loop") == 0)
{
uid_t rootuid, rootgid;
unsigned long val;
{
uid_t rootuid, rootgid;
unsigned long val;
- char *chownpath = path;
int hostuid, hostgid, ret;
struct stat sb;
char map1[100], map2[100], map3[100], map4[100], map5[100];
int hostuid, hostgid, ret;
struct stat sb;
char map1[100], map2[100], map3[100], map4[100], map5[100];
- /*
- * In case of overlay, we want only the writeable layer to be chowned
- */
- if (strncmp(path, "overlayfs:", 10) == 0 || strncmp(path, "aufs:", 5) == 0) {
- chownpath = strchr(path, ':');
- if (!chownpath) {
- ERROR("Bad overlay path: %s", path);
- return -1;
- }
- chownpath = strchr(chownpath + 1, ':');
- if (!chownpath) {
- ERROR("Bad overlay path: %s", path);
- return -1;
- }
- chownpath++;
- }
- path = chownpath;
if (hostuid == 0) {
if (chown(path, rootuid, rootgid) < 0) {
ERROR("Error chowning %s", path);
if (hostuid == 0) {
if (chown(path, rootuid, rootgid) < 0) {
ERROR("Error chowning %s", path);
sudo lxc-clone -o o1 -n n1 -s -L|-fssize fssize -v|--vgname vgname \
-p|--lvprefix lvprefix -t|--fstype fstype -B backingstore
sudo lxc-clone -o o1 -n n1 -s -L|-fssize fssize -v|--vgname vgname \
-p|--lvprefix lvprefix -t|--fstype fstype -B backingstore
--s [ implies overlayfs]
--s -B overlayfs
+-s [ implies overlay]
+-s -B overlay
-s -B aufs
only rootfs gets converted (copied/snapshotted) on clone.
-s -B aufs
only rootfs gets converted (copied/snapshotted) on clone.
if (bdev_is_dir(c->lxc_conf, c->lxc_conf->rootfs.path)) {
ERROR("Snapshot of directory-backed container requested.");
ERROR("Making a copy-clone. If you do want snapshots, then");
if (bdev_is_dir(c->lxc_conf, c->lxc_conf->rootfs.path)) {
ERROR("Snapshot of directory-backed container requested.");
ERROR("Making a copy-clone. If you do want snapshots, then");
- ERROR("please create an aufs or overlayfs clone first, snapshot that");
+ ERROR("please create an aufs or overlay clone first, snapshot that");
ERROR("and keep the original container pristine.");
flags &= ~LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT;
}
ERROR("and keep the original container pristine.");
flags &= ~LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT;
}