From ba1151756438bde89a4be3a107133656151a2646 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sat, 15 Jul 2017 21:49:44 +0200 Subject: [PATCH] overlay: simplify and adapt to "overlay" Signed-off-by: Christian Brauner --- src/lxc/bdev/bdev.c | 15 ++-- src/lxc/bdev/lxcoverlay.c | 134 +++++++++++++++++++++++------------ src/lxc/bdev/lxcoverlay.h | 2 +- src/lxc/bdev/storage_utils.c | 2 + src/lxc/conf.c | 18 ----- src/lxc/lxccontainer.c | 6 +- 6 files changed, 105 insertions(+), 72 deletions(-) diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c index ffc9d46a0..8f1d0145c 100644 --- a/src/lxc/bdev/bdev.c +++ b/src/lxc/bdev/bdev.c @@ -194,6 +194,7 @@ static const struct bdev_type bdevs[] = { { .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, }, @@ -374,10 +375,11 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, */ if (!bdevtype && !keepbdevtype && snap && strcmp(orig->type, "dir") == 0) - bdevtype = "overlayfs"; + bdevtype = "overlay"; 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; } @@ -385,7 +387,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, *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)) { @@ -411,8 +414,10 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, goto err; } - 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); diff --git a/src/lxc/bdev/lxcoverlay.c b/src/lxc/bdev/lxcoverlay.c index 50a72e26a..85f4650a2 100644 --- a/src/lxc/bdev/lxcoverlay.c +++ b/src/lxc/bdev/lxcoverlay.c @@ -34,6 +34,7 @@ #include "lxccontainer.h" #include "lxcoverlay.h" #include "lxcrsync.h" +#include "storage_utils.h" #include "utils.h" lxc_log_define(lxcoverlay, lxc); @@ -41,10 +42,6 @@ lxc_log_define(lxcoverlay, lxc); 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); @@ -61,16 +58,18 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, char *src; if (!snap) { - ERROR("overlayfs is only for snapshot clones"); + ERROR("overlay is only for snapshot clones"); 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 (mkdir_p(new->dest, 0755) < 0) return -1; @@ -143,11 +142,11 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, 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) - 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 @@ -156,26 +155,44 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, 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); return -22; + } + 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) { free(osrc); + ERROR("Failed to find \":\" in \"%s\"", nsrc); return -22; } + *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) { free(osrc); + ERROR("Failed to create new path"); return -ENOMEM; - } - 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); + SYSERROR("Failed to create \"%s\"", ndelta); return -1; } + if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0) WARN("Failed to update ownership of %s", ndelta); @@ -187,6 +204,7 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, if (!lastslash) { free(osrc); free(ndelta); + ERROR("Failed to detect \"/\" in \"%s\"", ndelta); return -1; } lastslash++; @@ -196,37 +214,43 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, if (!work) { free(osrc); free(ndelta); + ERROR("Failed to allocate memory"); 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); + SYSERROR("Failed to create \"%s\"", ndelta); return -1; } + 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); + ERROR("Failed to allocate memory"); return -ENOMEM; } - ret = snprintf(new->src, len, "overlayfs:%s:%s", nsrc, ndelta); + ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, 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 { - 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 @@ -239,7 +263,7 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, } /* - * 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 @@ -267,14 +291,14 @@ int ovl_create(struct bdev *bdev, const char *dest, const char *n, return -1; } - // 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; } - 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; @@ -288,14 +312,23 @@ int ovl_create(struct bdev *bdev, const char *dest, const char *n, int ovl_destroy(struct bdev *orig) { - char *upper; + bool ovl; + char *upper = orig->src; - if (strncmp(orig->src, "overlayfs:", 10) != 0) + ovl = !strncmp(upper, "overlay:", 8); + if (!ovl && strncmp(upper, "overlayfs:", 10)) return -22; - upper = strchr(orig->src + 10, ':'); + + if (ovl) + upper += 8; + else + upper += 10; + + upper = strchr(upper, ':'); if (!upper) return -22; upper++; + return lxc_rmdir_onedev(upper, NULL); } @@ -310,14 +343,6 @@ int ovl_detect(const char *path) return 0; } -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; @@ -328,8 +353,9 @@ int ovl_mount(struct bdev *bdev) char *mntdata; int ret, ret2; - if (strcmp(bdev->type, "overlayfs")) + if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs")) return -22; + if (!bdev->src || !bdev->dest) return -22; @@ -423,7 +449,7 @@ int ovl_mount(struct bdev *bdev) 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)); @@ -431,15 +457,15 @@ int ovl_mount(struct bdev *bdev) 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 - INFO("Overlayfs: Mounted %s onto %s with options %s.", + INFO("Overlay: Mounted %s onto %s with options %s.", 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; @@ -447,13 +473,31 @@ int ovl_mount(struct bdev *bdev) int ovl_umount(struct bdev *bdev) { - if (strcmp(bdev->type, "overlayfs")) + if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs")) return -22; + if (!bdev->src || !bdev->dest) return -22; + 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; @@ -762,7 +806,7 @@ static int ovl_do_rsync(struct bdev *orig, struct bdev *new, struct lxc_conf *co else ret = ovl_rsync(&rdata); if (ret) - ERROR("copying overlayfs delta"); + ERROR("copying overlay delta"); return ret; } diff --git a/src/lxc/bdev/lxcoverlay.h b/src/lxc/bdev/lxcoverlay.h index 8ef277b83..fe70d3dbc 100644 --- a/src/lxc/bdev/lxcoverlay.h +++ b/src/lxc/bdev/lxcoverlay.h @@ -76,7 +76,7 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path, * 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 diff --git a/src/lxc/bdev/storage_utils.c b/src/lxc/bdev/storage_utils.c index 0cf9710fb..5e3f1fc3b 100644 --- a/src/lxc/bdev/storage_utils.c +++ b/src/lxc/bdev/storage_utils.c @@ -415,6 +415,7 @@ bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap, // 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) @@ -427,6 +428,7 @@ bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap, // 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) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index ab038d36d..317b4e8d6 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -3722,7 +3722,6 @@ int chown_mapped_root(char *path, struct lxc_conf *conf) { 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]; @@ -3758,23 +3757,6 @@ int chown_mapped_root(char *path, struct lxc_conf *conf) } rootgid = (gid_t)val; - /* - * 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); diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 663fe547d..4818eb644 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -3254,8 +3254,8 @@ static int clone_update_rootfs_wrapper(void *data) 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. @@ -3636,7 +3636,7 @@ static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile) 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; } -- 2.39.2