Hi, Sorry for my slow response. >>> On Wed, 8 Oct 2014 18:21:19 +0000 in message "Re: [lxc-devel] lxc-clone do not work when overlayfs.v22 or higher is used" Serge Hallyn-san wrote:
> Quoting KATOH Yasufumi (ka...@jazz.email.ne.jp): > > Hi, > > > > Now, lxc-clone with overlayfs (lxc-clone -s -B overlayfs) runs internally: > > mount -t overlayfs -oupperdir=${upper},lowerdir=${lower} lower dest > > > > But, overlayfs.v22(kernel 3.15) or higher need the option "workdir=", > > so lxc-clone do not work. > > > > On 3.17 with overlayfs.v24, without workdir option: > > # mount -n -t overlayfs -o lowerdir=1,upperdir=2 overlayfs 3 > > mount: wrong fs type, bad option, bad superblock on overlayfs, > > missing codepage or helper program, or other error > > > > In some cases useful info is found in syslog - try > > dmesg | tail or so. > > # dmesg | tail > > [ 683.456473] overlayfs: missing upperdir or lowerdir or workdir > > > > On 3.17 with overlayfs.v24, with workdir option: > > # mount -n -t overlayfs -o lowerdir=1,upperdir=2,workdir=3 overlayfs 4 > > # cat /proc/mounts | grep overlayfs > > overlayfs /root/overlayfs/4 overlayfs > > rw,relatime,lowerdir=1,upperdir=2,workdir=3 0 0 > > > > See > > > > https://git.kernel.org/cgit/linux/kernel/git/mszeredi/vfs.git/tree/Documentation/filesystems/overlayfs.txt?h=overlayfs.v24 > The older version (which is still in use in the 3.16 kernel in Ubuntu 14.10) > fails with that option, so it looks like there's not much to do but try > the workdir=, then if that fails try without workdir=. > Can you send a patch to do that? I try it. But I don't know well the details of the clone process, I don't know whether this is right. This patch is * the workdir is LXCPATH/ct/olwork. * mkdir workdir when clone * mount without workdir is failed, then retry mount with workdir I've tested on: * 3.14.4 with overlayfs.v21 (not need workdir=) (priv and unpriv) * 3.17.0 with overlayfs.v24 (need workdir=) (priv and unpriv) Signed-off-by: KATOH Yasufumi <ka...@jazz.email.ne.jp> --- src/lxc/bdev.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c index 4fc10f2..69c2e7f 100644 --- a/src/lxc/bdev.c +++ b/src/lxc/bdev.c @@ -2154,10 +2154,11 @@ static int overlayfs_detect(const char *path) static int overlayfs_mount(struct bdev *bdev) { char *options, *dup, *lower, *upper; - int len; + char *options_work, *work, *worktmp; + int len, len2; unsigned long mntflags; char *mntdata; - int ret; + int ret, ret2; if (strcmp(bdev->type, "overlayfs")) return -22; @@ -2175,6 +2176,14 @@ static int overlayfs_mount(struct bdev *bdev) *upper = '\0'; upper++; + // workdir option that is needed overlayfs.v22 or higher + // workdir=$LXCDIR/ct/olwork + work = alloca(strlen(upper)+1); + strcpy(work, upper); + if (!(worktmp = rindex(work, '/'))) + return -22; + strncpy(worktmp+1, "olwork", 6); + if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) { free(mntdata); return -22; @@ -2187,21 +2196,42 @@ static int overlayfs_mount(struct bdev *bdev) len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1; options = alloca(len); ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s", upper, lower, mntdata); + + len2 = strlen(lower) + strlen(upper) + strlen(work) + + strlen("upperdir=,lowerdir=,workdir=") + strlen(mntdata) + 1; + options_work = alloca(len2); + ret2 = snprintf(options, len2, "upperdir=%s,lowerdir=%s,workdir=%s,%s", + upper, lower, work, mntdata); } else { len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=") + 1; options = alloca(len); ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper, lower); + + len2 = strlen(lower) + strlen(upper) + strlen(work) + + strlen("upperdir=,lowerdir=,workdir=") + 1; + options_work = alloca(len2); + ret2 = snprintf(options_work, len2, "upperdir=%s,lowerdir=%s,workdir=%s", + upper, lower, work); } - if (ret < 0 || ret >= len) { + if (ret < 0 || ret >= len || ret2 < 0 || ret2 >= len2) { free(mntdata); return -1; } ret = mount(lower, bdev->dest, "overlayfs", MS_MGC_VAL | mntflags, options); - if (ret < 0) - SYSERROR("overlayfs: error mounting %s onto %s options %s", + if (ret < 0) { + WARN("overlayfs: error mounting %s onto %s options %s", lower, bdev->dest, options); + // retry with workdir option + ret = mount(lower, bdev->dest, "overlayfs", MS_MGC_VAL | mntflags, options_work); + if (ret < 0) + SYSERROR("overlayfs: error mounting %s onto %s options %s", + lower, bdev->dest, options_work); + else + INFO("overlayfs: mounted %s onto %s options %s", + lower, bdev->dest, options_work); + } else INFO("overlayfs: mounted %s onto %s options %s", lower, bdev->dest, options); @@ -2265,7 +2295,7 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char WARN("Failed to update ownership of %s", new->dest); if (strcmp(orig->type, "dir") == 0) { - char *delta; + char *delta, *work; int ret, len; // if we have /var/lib/lxc/c2/rootfs, then delta will be @@ -2287,6 +2317,23 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char if (am_unpriv() && chown_mapped_root(delta, conf) < 0) WARN("Failed to update ownership of %s", delta); + // mkdir workdir that is needed on overlayfs.v22 or higher + // if we have /var/lib/lxc/c2/rootfs, then workdir will be + // /var/lib/lxc/c2/olwork + work = strdup(new->dest); + if (!work) + return -1; + + strcpy(&work[strlen(work)-6], "olwork"); + if (mkdir(work, 0755) < 0) { + SYSERROR("error: mkdir %s", work); + free(work); + return -1; + } + if (am_unpriv() && chown_mapped_root(work, conf) < 0) + WARN("Failed to update ownership of %s", work); + free(work); + // the src will be 'overlayfs:lowerdir:upperdir' len = strlen(delta) + strlen(orig->src) + 12; new->src = malloc(len); @@ -2303,7 +2350,7 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char // I think we want to use the original lowerdir, with a // private delta which is originally rsynced from the // original delta - char *osrc, *odelta, *nsrc, *ndelta; + char *osrc, *odelta, *nsrc, *ndelta, *work; int len, ret; if (!(osrc = strdup(orig->src))) return -22; @@ -2327,6 +2374,22 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char } if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0) WARN("Failed to update ownership of %s", ndelta); + + // mkdir workdir for overlayfs.v22 or later + work = strdup(ndelta); + if (!work) + return -1; + + strcpy(&work[strlen(work)-6], "olwork"); + if (mkdir(work, 0755) < 0) { + SYSERROR("error: mkdir %s", work); + free(work); + return -1; + } + if (am_unpriv() && chown_mapped_root(work, conf) < 0) + WARN("Failed to update ownership of %s", work); + free(work); + struct rsync_data_char rdata; rdata.src = odelta; rdata.dest = ndelta; -- 2.1.1 _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel