[lxc-devel] [PATCH] overlayfs: overlayfs.v22 or higher needs workdir option

Serge Hallyn serge.hallyn at ubuntu.com
Thu Oct 30 21:28:31 UTC 2014


Quoting KATOH Yasufumi (karma at jazz.email.ne.jp):
> This patch creates workdir as "olwork", and retry mount with workdir
> option when mount is failed.
> It is used to prepare files before atomically swithing with
> destination, and needs to be on the same filesystem as upperdir. It's
> OK for it to be empty.
> 
> Signed-off-by: KATOH Yasufumi <karma at jazz.email.ne.jp>

Thanks, looks good.

Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>

Now, realistically, since overalyfs_mount() will create the workdir
as needed, I suppose the clone fn doesn't need it...  is that right?
(that would simplify some code)

> ---
>  src/lxc/bdev.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 89 insertions(+), 7 deletions(-)
> 
> diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
> index 8a819ab..ae5c77c 100644
> --- a/src/lxc/bdev.c
> +++ b/src/lxc/bdev.c
> @@ -2154,10 +2154,12 @@ 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, *lastslash;
> +	int lastslashidx;
> +	int len, len2;
>  	unsigned long mntflags;
>  	char *mntdata;
> -	int ret;
> +	int ret, ret2;
>  
>  	if (strcmp(bdev->type, "overlayfs"))
>  		return -22;
> @@ -2175,6 +2177,19 @@ static int overlayfs_mount(struct bdev *bdev)
>  	*upper = '\0';
>  	upper++;
>  
> +	// overlayfs.v22 or higher needs workdir option
> +	// if upper is /var/lib/lxc/c2/delta0,
> +	// then workdir is /var/lib/lxc/c2/olwork
> +	lastslash = strrchr(upper, '/');
> +	if (!lastslash)
> +		return -22;
> +	lastslash++;
> +	lastslashidx = lastslash - upper;
> +
> +	work = alloca(lastslashidx + 7);
> +	strncpy(work, upper, lastslashidx+7);
> +	strcpy(work+lastslashidx, "olwork");
> +
>  	if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
>  		free(mntdata);
>  		return -22;
> @@ -2187,21 +2202,44 @@ 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;
>  	}
>  
> +	// mount without workdir option for overlayfs before v21
>  	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) {
> +		INFO("overlayfs: error mounting %s onto %s options %s. retry with workdir",
>  			lower, bdev->dest, options);
> +
> +		// retry with workdir option for overlayfs v22 and higher
> +		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);
> @@ -2266,6 +2304,7 @@ static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char
>  
>  	if (strcmp(orig->type, "dir") == 0) {
>  		char *delta, *lastslash;
> +		char *work;
>  		int ret, len, lastslashidx;
>  
>  		// if we have /var/lib/lxc/c2/rootfs, then delta will be
> @@ -2291,6 +2330,25 @@ 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);
>  
> +		// make workdir for overlayfs.v22 or higher
> +		// workdir is /var/lib/lxc/c2/olwork
> +		// it is used to prepare files before atomically swithing with destination,
> +		// and needs to be on the same filesystem as upperdir,
> +		// so it's OK for it to be empty.
> +		work = malloc(lastslashidx + 7);
> +		if (!work)
> +			return -1;
> +		strncpy(work, new->dest, lastslashidx+1);
> +		strcpy(work+lastslashidx, "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);
> @@ -2307,8 +2365,9 @@ 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;
> -		int len, ret;
> +		char *osrc, *odelta, *nsrc, *ndelta, *work;
> +		char *lastslash;
> +		int len, ret, lastslashidx;
>  		if (!(osrc = strdup(orig->src)))
>  			return -22;
>  		nsrc = index(osrc, ':') + 1;
> @@ -2331,6 +2390,29 @@ 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);
> +
> +		// make workdir for overlayfs.v22 or higher
> +		// for details, see above.
> +		lastslash = strrchr(ndelta, '/');
> +		if (!lastslash)
> +			return -1;
> +		lastslash++;
> +		lastslashidx = lastslash - ndelta;
> +
> +		work = malloc(lastslashidx + 7);
> +		if (!work)
> +			return -1;
> +		strncpy(work, ndelta, lastslashidx+1);
> +		strcpy(work+lastslashidx, "olwork");
> +		if ((mkdir(work, 0755) < 0) && errno != EEXIST) {
> +			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 at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel


More information about the lxc-devel mailing list