[lxc-devel] [lxc/stable-2.0] stable 2.0: revert a bunch of cherry picks

brauner on Github lxc-bot at linuxcontainers.org
Tue Aug 15 16:21:06 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170815/889b9f4e/attachment.bin>
-------------- next part --------------
From fd8b10a745d54f4dbe0db5293eed04865e6db33c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:05:42 +0200
Subject: [PATCH 01/24] Revert "rbd: rework rbd storage driver"

This reverts commit 93b8f59a889d72b863c9fd225ebe3694feb6a0d1.
---
 src/lxc/bdev/lxcrbd.c | 144 ++++++++++++++------------------------------------
 1 file changed, 40 insertions(+), 104 deletions(-)

diff --git a/src/lxc/bdev/lxcrbd.c b/src/lxc/bdev/lxcrbd.c
index 7f1c0f583..08436b75e 100644
--- a/src/lxc/bdev/lxcrbd.c
+++ b/src/lxc/bdev/lxcrbd.c
@@ -36,50 +36,6 @@
 
 lxc_log_define(lxcrbd, lxc);
 
-struct rbd_args {
-	const char *osd_pool_name;
-	const char *rbd_name;
-	const char *size;
-};
-
-int rbd_create_wrapper(void *data)
-{
-	struct rbd_args *args = data;
-
-	execlp("rbd", "rbd", "create", "--pool", args->osd_pool_name,
-	       args->rbd_name, "--size", args->size, (char *)NULL);
-
-	return -1;
-}
-
-int rbd_map_wrapper(void *data)
-{
-	struct rbd_args *args = data;
-
-	execlp("rbd", "rbd", "map", "--pool", args->osd_pool_name,
-	       args->rbd_name, (char *)NULL);
-
-	return -1;
-}
-
-int rbd_unmap_wrapper(void *data)
-{
-	struct rbd_args *args = data;
-
-	execlp("rbd", "rbd", "unmap", args->rbd_name, (char *)NULL);
-
-	return -1;
-}
-
-int rbd_delete_wrapper(void *data)
-{
-	struct rbd_args *args = data;
-
-	execlp("rbd", "rbd", "rm", args->rbd_name, (char *)NULL);
-
-	return -1;
-}
-
 int rbd_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		   const char *cname, const char *oldpath, const char *lxcpath,
 		   int snap, uint64_t newsize, struct lxc_conf *conf)
@@ -91,14 +47,13 @@ int rbd_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 int rbd_create(struct bdev *bdev, const char *dest, const char *n,
 	       struct bdev_specs *specs)
 {
-	const char *rbdpool, *fstype;
+	const char *rbdpool, *rbdname = n, *fstype;
 	uint64_t size;
 	int ret, len;
 	char sz[24];
+	pid_t pid;
 	const char *cmd_args[2];
 	char cmd_output[MAXPATHLEN];
-	const char *rbdname = n;
-	struct rbd_args args = {0};
 
 	if (!specs)
 		return -1;
@@ -113,16 +68,12 @@ int rbd_create(struct bdev *bdev, const char *dest, const char *n,
 	/* source device /dev/rbd/lxc/ctn */
 	len = strlen(rbdpool) + strlen(rbdname) + 4 + 11;
 	bdev->src = malloc(len);
-	if (!bdev->src) {
-		ERROR("Failed to allocate memory");
+	if (!bdev->src)
 		return -1;
-	}
 
 	ret = snprintf(bdev->src, len, "rbd:/dev/rbd/%s/%s", rbdpool, rbdname);
-	if (ret < 0 || ret >= len) {
-		ERROR("Failed to create string");
+	if (ret < 0 || ret >= len)
 		return -1;
-	}
 
 	/* fssize is in bytes */
 	size = specs->fssize;
@@ -131,92 +82,78 @@ int rbd_create(struct bdev *bdev, const char *dest, const char *n,
 
 	/* in megabytes for rbd tool */
 	ret = snprintf(sz, 24, "%" PRIu64, size / 1024 / 1024);
-	if (ret < 0 || ret >= 24) {
-		ERROR("Failed to create string");
-		return -1;
-	}
+	if (ret < 0 || ret >= 24)
+		exit(1);
 
-	args.osd_pool_name = rbdpool;
-	args.rbd_name = rbdname;
-	args.size = sz;
-	ret = run_command(cmd_output, sizeof(cmd_output), rbd_create_wrapper,
-			  (void *)&args);
-	if (ret < 0) {
-		ERROR("Failed to create rbd storage volume \"%s\": %s", rbdname,
-		      cmd_output);
+	if ((pid = fork()) < 0)
 		return -1;
+	if (!pid) {
+		execlp("rbd", "rbd", "create", "--pool", rbdpool, rbdname,
+		       "--size", sz, (char *)NULL);
+		exit(1);
 	}
+	if (wait_for_pid(pid) < 0)
+		return -1;
 
-	ret = run_command(cmd_output, sizeof(cmd_output), rbd_map_wrapper,
-			  (void *)&args);
-	if (ret < 0) {
-		ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
-		      cmd_output);
+	if ((pid = fork()) < 0)
 		return -1;
+	if (!pid) {
+		execlp("rbd", "rbd", "map", "--pool", rbdpool, rbdname,
+		       (char *)NULL);
+		exit(1);
 	}
+	if (wait_for_pid(pid) < 0)
+		return -1;
 
 	fstype = specs->fstype;
 	if (!fstype)
 		fstype = DEFAULT_FSTYPE;
 
 	cmd_args[0] = fstype;
-	cmd_args[1] = lxc_storage_get_path(bdev->src, bdev->type);
+	cmd_args[1] = bdev->src + 4;
 	ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
 			  (void *)cmd_args);
-	if (ret < 0) {
-		ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
-		      cmd_output);
+	if (ret < 0)
 		return -1;
-	}
 
-	bdev->dest = strdup(dest);
-	if (!bdev->dest) {
-		ERROR("Failed to duplicate string \"%s\"", dest);
+	if (!(bdev->dest = strdup(dest)))
 		return -1;
-	}
 
-	ret = mkdir_p(bdev->dest, 0755);
-	if (ret < 0 && errno != EEXIST) {
-		ERROR("Failed to create directory \"%s\"", bdev->dest);
+	if (mkdir_p(bdev->dest, 0755) < 0 && errno != EEXIST) {
+		ERROR("Error creating %s", bdev->dest);
 		return -1;
 	}
 
-	TRACE("Created rbd storage volume \"%s\"", bdev->dest);
 	return 0;
 }
 
 int rbd_destroy(struct bdev *orig)
 {
-	int ret;
 	char *src;
+	pid_t pid;
 	char *rbdfullname;
-	char cmd_output[MAXPATHLEN];
-	struct rbd_args args = {0};
 
 	src = lxc_storage_get_path(orig->src, orig->type);
 	if (file_exists(src)) {
-		args.rbd_name = src;
-		ret = run_command(cmd_output, sizeof(cmd_output),
-				  rbd_unmap_wrapper, (void *)&args);
-		if (ret < 0) {
-			ERROR("Failed to map rbd storage volume \"%s\": %s",
-			      src, cmd_output);
+		if ((pid = fork()) < 0)
 			return -1;
+		if (!pid) {
+			execlp("rbd", "rbd", "unmap", src, (char *)NULL);
+			exit(1);
 		}
+		if (wait_for_pid(pid) < 0)
+			return -1;
 	}
 
-	rbdfullname = alloca(strlen(src) - 8);
-	strcpy(rbdfullname, &src[9]);
-	args.rbd_name = rbdfullname;
-	ret = run_command(cmd_output, sizeof(cmd_output),
-			rbd_delete_wrapper, (void *)&args);
-	if (ret < 0) {
-		ERROR("Failed to delete rbd storage volume \"%s\": %s",
-		      rbdfullname, cmd_output);
+	if ((pid = fork()) < 0)
 		return -1;
+	if (!pid) {
+		rbdfullname = alloca(strlen(src) - 8);
+		strcpy(rbdfullname, &src[9]);
+		execlp("rbd", "rbd", "rm", rbdfullname, (char *)NULL);
+		exit(1);
 	}
-
-	return 0;
+	return wait_for_pid(pid);
 }
 
 int rbd_detect(const char *path)
@@ -229,7 +166,6 @@ int rbd_detect(const char *path)
 int rbd_mount(struct bdev *bdev)
 {
 	char *src;
-
 	if (strcmp(bdev->type, "rbd"))
 		return -22;
 
@@ -245,7 +181,7 @@ int rbd_mount(struct bdev *bdev)
 		return -1;
 	}
 
-	return mount_unknown_fs(src, bdev->dest, bdev->mntopts);
+	return mount_unknown_fs(bdev->src, bdev->dest, bdev->mntopts);
 }
 
 int rbd_umount(struct bdev *bdev)

From cf66f5f760afa62a0eb9c935b235373b77b4c855 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:06:07 +0200
Subject: [PATCH 02/24] Revert "rbd: rbd non-functional changes"

This reverts commit 162a857a5811ff343146401cf6dde482158ae665.
---
 src/lxc/bdev/lxcrbd.c | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/src/lxc/bdev/lxcrbd.c b/src/lxc/bdev/lxcrbd.c
index 08436b75e..c49b71d29 100644
--- a/src/lxc/bdev/lxcrbd.c
+++ b/src/lxc/bdev/lxcrbd.c
@@ -23,7 +23,7 @@
 
 #define _GNU_SOURCE
 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
-#include <inttypes.h>	/* Required for PRIu64 to work. */
+#include <inttypes.h> /* Required for PRIu64 to work. */
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,15 +37,15 @@
 lxc_log_define(lxcrbd, lxc);
 
 int rbd_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
-		   const char *cname, const char *oldpath, const char *lxcpath,
-		   int snap, uint64_t newsize, struct lxc_conf *conf)
+		const char *cname, const char *oldpath, const char *lxcpath,
+		int snap, uint64_t newsize, struct lxc_conf *conf)
 {
 	ERROR("rbd clonepaths not implemented");
 	return -1;
 }
 
 int rbd_create(struct bdev *bdev, const char *dest, const char *n,
-	       struct bdev_specs *specs)
+		struct bdev_specs *specs)
 {
 	const char *rbdpool, *rbdname = n, *fstype;
 	uint64_t size;
@@ -75,21 +75,20 @@ int rbd_create(struct bdev *bdev, const char *dest, const char *n,
 	if (ret < 0 || ret >= len)
 		return -1;
 
-	/* fssize is in bytes */
+	// fssize is in bytes.
 	size = specs->fssize;
 	if (!size)
 		size = DEFAULT_FS_SIZE;
 
-	/* in megabytes for rbd tool */
-	ret = snprintf(sz, 24, "%" PRIu64, size / 1024 / 1024);
+	// in megabytes for rbd tool
+	ret = snprintf(sz, 24, "%"PRIu64, size / 1024 / 1024 );
 	if (ret < 0 || ret >= 24)
 		exit(1);
 
 	if ((pid = fork()) < 0)
 		return -1;
 	if (!pid) {
-		execlp("rbd", "rbd", "create", "--pool", rbdpool, rbdname,
-		       "--size", sz, (char *)NULL);
+		execlp("rbd", "rbd", "create" , "--pool", rbdpool, rbdname, "--size", sz, (char *)NULL);
 		exit(1);
 	}
 	if (wait_for_pid(pid) < 0)
@@ -98,8 +97,7 @@ int rbd_create(struct bdev *bdev, const char *dest, const char *n,
 	if ((pid = fork()) < 0)
 		return -1;
 	if (!pid) {
-		execlp("rbd", "rbd", "map", "--pool", rbdpool, rbdname,
-		       (char *)NULL);
+		execlp("rbd", "rbd", "map", "--pool", rbdpool, rbdname, (char *)NULL);
 		exit(1);
 	}
 	if (wait_for_pid(pid) < 0)
@@ -138,7 +136,7 @@ int rbd_destroy(struct bdev *orig)
 		if ((pid = fork()) < 0)
 			return -1;
 		if (!pid) {
-			execlp("rbd", "rbd", "unmap", src, (char *)NULL);
+			execlp("rbd", "rbd", "unmap" , src, (char *)NULL);
 			exit(1);
 		}
 		if (wait_for_pid(pid) < 0)
@@ -149,11 +147,12 @@ int rbd_destroy(struct bdev *orig)
 		return -1;
 	if (!pid) {
 		rbdfullname = alloca(strlen(src) - 8);
-		strcpy(rbdfullname, &src[9]);
-		execlp("rbd", "rbd", "rm", rbdfullname, (char *)NULL);
+		strcpy( rbdfullname, &src[9] );
+		execlp("rbd", "rbd", "rm" , rbdfullname, (char *)NULL);
 		exit(1);
 	}
 	return wait_for_pid(pid);
+
 }
 
 int rbd_detect(const char *path)
@@ -174,9 +173,7 @@ int rbd_mount(struct bdev *bdev)
 
 	src = lxc_storage_get_path(bdev->src, bdev->type);
 	if (!file_exists(src)) {
-		/* If blkdev does not exist it should be mapped, because it is
-		 * not persistent on reboot.
-		 */
+		// if blkdev does not exist it should be mapped, because it is not persistent on reboot
 		ERROR("Block device %s is not mapped.", bdev->src);
 		return -1;
 	}

From c2b9617f04a7cf6656725669f19b7e7552dc8ff1 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:06:23 +0200
Subject: [PATCH 03/24] Revert "loop: rework loop storage driver"

This reverts commit 85914b6775afbf5598ea0cf8e342237f1da7c6d4.
---
 src/lxc/bdev/lxcloop.c | 190 +++++++++++++++----------------------------------
 1 file changed, 58 insertions(+), 132 deletions(-)

diff --git a/src/lxc/bdev/lxcloop.c b/src/lxc/bdev/lxcloop.c
index e5f14bb78..aa14925fb 100644
--- a/src/lxc/bdev/lxcloop.c
+++ b/src/lxc/bdev/lxcloop.c
@@ -22,15 +22,12 @@
  */
 
 #define _GNU_SOURCE
-#define __STDC_FORMAT_MACROS
 #include <dirent.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <linux/loop.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <linux/loop.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
@@ -49,16 +46,16 @@ static int do_loop_create(const char *path, uint64_t size, const char *fstype);
  * called $lxcpath/$lxcname/rootdev
  */
 int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
-		    const char *cname, const char *oldpath, const char *lxcpath,
-		    int snap, uint64_t newsize, struct lxc_conf *conf)
+		const char *cname, const char *oldpath, const char *lxcpath,
+		int snap, uint64_t newsize, struct lxc_conf *conf)
 {
+	char fstype[100];
 	uint64_t size = newsize;
 	int len, ret;
 	char *srcdev;
-	char fstype[100] = "ext4";
 
 	if (snap) {
-		ERROR("The loop storage driver does not support snapshots");
+		ERROR("loop devices cannot be snapshotted.");
 		return -1;
 	}
 
@@ -68,65 +65,43 @@ int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 	len = strlen(lxcpath) + strlen(cname) + strlen("rootdev") + 3;
 	srcdev = alloca(len);
 	ret = snprintf(srcdev, len, "%s/%s/rootdev", lxcpath, cname);
-	if (ret < 0 || ret >= len) {
-		ERROR("Failed to create string");
+	if (ret < 0 || ret >= len)
 		return -1;
-	}
 
 	new->src = malloc(len + 5);
-	if (!new->src) {
-		ERROR("Failed to allocate memory");
+	if (!new->src)
 		return -1;
-	}
-
-	ret = snprintf(new->src, (len + 5), "loop:%s", srcdev);
-	if (ret < 0 || ret >= (len + 5)) {
-		ERROR("Failed to create string");
+	ret = snprintf(new->src, len + 5, "loop:%s", srcdev);
+	if (ret < 0 || ret >= len + 5)
 		return -1;
-	}
 
 	new->dest = malloc(len);
-	if (!new->dest) {
-		ERROR("Failed to allocate memory");
+	if (!new->dest)
 		return -1;
-	}
-
 	ret = snprintf(new->dest, len, "%s/%s/rootfs", lxcpath, cname);
-	if (ret < 0 || ret >= len) {
-		ERROR("Failed to create string");
+	if (ret < 0 || ret >= len)
 		return -1;
-	}
 
-	/* It's tempting to say: if orig->src == loopback and !newsize, then
-	 * copy the loopback file. However, we'd have to make sure to correctly
-	 * keep holes! So punt for now.
-	 */
+	// it's tempting to say: if orig->src == loopback and !newsize, then
+	// copy the loopback file.  However, we'd have to make sure to
+	// correctly keep holes!  So punt for now.
+
 	if (is_blktype(orig)) {
-		/* detect size */
 		if (!newsize && blk_getsize(orig, &size) < 0) {
-			ERROR("Failed to detect size of loop file \"%s\"",
-			      orig->src);
+			ERROR("Error getting size of %s", orig->src);
 			return -1;
 		}
-
-		/* detect filesystem */
 		if (detect_fs(orig, fstype, 100) < 0) {
-			INFO("Failed to detect filesystem type for \"%s\"", orig->src);
+			INFO("could not find fstype for %s, using %s", orig->src,
+				DEFAULT_FSTYPE);
 			return -1;
 		}
-	} else if (!newsize) {
+	} else {
+		sprintf(fstype, "%s", DEFAULT_FSTYPE);
+		if (!newsize)
 			size = DEFAULT_FS_SIZE;
 	}
-
-	ret = do_loop_create(srcdev, size, fstype);
-	if (ret < 0) {
-		ERROR("Failed to create loop storage volume \"%s\" with "
-		      "filesystem \"%s\" and size \"%" PRIu64 "\"",
-		      srcdev, fstype, size);
-		return -1;
-	}
-
-	return 0;
+	return do_loop_create(srcdev, size, fstype);
 }
 
 int loop_create(struct bdev *bdev, const char *dest, const char *n,
@@ -140,35 +115,23 @@ int loop_create(struct bdev *bdev, const char *dest, const char *n,
 	if (!specs)
 		return -1;
 
-	/* <dest> is passed in as <lxcpath>/<lxcname>/rootfs, <srcdev> will
-	 * be <lxcpath>/<lxcname>/rootdev, and <src> will be "loop:<srcdev>".
-	 */
+	// dest is passed in as $lxcpath / $lxcname / rootfs
+	// srcdev will be:      $lxcpath / $lxcname / rootdev
+	// src will be 'loop:$srcdev'
 	len = strlen(dest) + 2;
 	srcdev = alloca(len);
 
 	ret = snprintf(srcdev, len, "%s", dest);
-	if (ret < 0 || ret >= len) {
-		ERROR("Failed to create string");
-		return -1;
-	}
-
-	ret = sprintf(srcdev + len - 4, "dev");
-	if (ret < 0) {
-		ERROR("Failed to create string");
+	if (ret < 0 || ret >= len)
 		return -1;
-	}
+	sprintf(srcdev + len - 4, "dev");
 
 	bdev->src = malloc(len + 5);
-	if (!bdev->src) {
-		ERROR("Failed to allocate memory");
+	if (!bdev->src)
 		return -1;
-	}
-
 	ret = snprintf(bdev->src, len + 5, "loop:%s", srcdev);
-	if (ret < 0 || ret >= len + 5) {
-		ERROR("Failed to create string");
+	if (ret < 0 || ret >= len + 5)
 		return -1;
-	}
 
 	sz = specs->fssize;
 	if (!sz)
@@ -178,31 +141,19 @@ int loop_create(struct bdev *bdev, const char *dest, const char *n,
 	if (!fstype)
 		fstype = DEFAULT_FSTYPE;
 
-	bdev->dest = strdup(dest);
-	if (!bdev->dest) {
-		ERROR("Failed to duplicate string \"%s\"", dest);
+	if (!(bdev->dest = strdup(dest)))
 		return -1;
-	}
 
-	ret = mkdir_p(bdev->dest, 0755);
-	if (ret < 0) {
-		ERROR("Failed creating directory \"%s\"", bdev->dest);
+	if (mkdir_p(bdev->dest, 0755) < 0) {
+		ERROR("Error creating %s", bdev->dest);
 		return -1;
 	}
 
-
-	ret = do_loop_create(srcdev, sz, fstype);
-	if (ret < 0) {
-		ERROR("Failed to create loop storage volume \"%s\" with "
-		      "filesystem \"%s\" and size \"%" PRIu64 "\"",
-		      srcdev, fstype, sz);
-		return -1;
-	}
-
-	return 0;
+	return do_loop_create(srcdev, sz, fstype);
 }
 
-int loop_destroy(struct bdev *orig) {
+int loop_destroy(struct bdev *orig)
+{
 	return unlink(orig->src + 5);
 }
 
@@ -228,7 +179,7 @@ int loop_mount(struct bdev *bdev)
 {
 	int ret, loopfd;
 	char loname[MAXPATHLEN];
-	char *src;
+	char *src = bdev->src;
 
 	if (strcmp(bdev->type, "loop"))
 		return -22;
@@ -237,98 +188,73 @@ int loop_mount(struct bdev *bdev)
 		return -22;
 
 	/* skip prefix */
-	src = lxc_storage_get_path(bdev->src, bdev->type);
+	if (!strncmp(bdev->src, "loop:", 5))
+		src += 5;
 
 	loopfd = lxc_prepare_loop_dev(src, loname, LO_FLAGS_AUTOCLEAR);
 	if (loopfd < 0) {
-		ERROR("Failed to prepare loop device for loop file \"%s\"", src);
+		ERROR("failed to prepare loop device for loop file \"%s\"", src);
 		return -1;
 	}
-	DEBUG("Prepared loop device \"%s\"", loname);
+	DEBUG("prepared loop device \"%s\"", loname);
 
 	ret = mount_unknown_fs(loname, bdev->dest, bdev->mntopts);
-	if (ret < 0) {
-		ERROR("Failed to mount rootfs \"%s\" on \"%s\" via loop device \"%s\"",
-		      bdev->src, bdev->dest, loname);
-		close(loopfd);
-		return -1;
-	}
-
-	bdev->lofd = loopfd;
-	DEBUG("Mounted rootfs \"%s\" on \"%s\" via loop device \"%s\"",
-	      bdev->src, bdev->dest, loname);
+	if (ret < 0)
+		ERROR("failed to mount rootfs \"%s\" onto \"%s\" via loop device \"%s\"", bdev->src, bdev->dest, loname);
+	else
+		bdev->lofd = loopfd;
+	DEBUG("mounted rootfs \"%s\" onto \"%s\" via loop device \"%s\"", bdev->src, bdev->dest, loname);
 
-	return 0;
+	return ret;
 }
 
 int loop_umount(struct bdev *bdev)
 {
-	int ret, saved_errno;
+	int ret;
 
 	if (strcmp(bdev->type, "loop"))
 		return -22;
-
 	if (!bdev->src || !bdev->dest)
 		return -22;
-
 	ret = umount(bdev->dest);
-	saved_errno = errno;
 	if (bdev->lofd >= 0) {
 		close(bdev->lofd);
 		bdev->lofd = -1;
 	}
-	errno = saved_errno;
-
-	if (ret < 0) {
-		SYSERROR("Failed to umount \"%s\"", bdev->dest);
-		return -1;
-	}
-
-	return 0;
+	return ret;
 }
 
 static int do_loop_create(const char *path, uint64_t size, const char *fstype)
 {
 	int fd, ret;
-	char cmd_output[MAXPATHLEN];
 	const char *cmd_args[2] = {fstype, path};
+	char cmd_output[MAXPATHLEN];
 
-	/* create the new loopback file */
-	fd = creat(path, S_IRUSR | S_IWUSR);
-	if (fd < 0) {
-		SYSERROR("Failed to create new loop file \"%s\"", path);
+	// create the new loopback file.
+	fd = creat(path, S_IRUSR|S_IWUSR);
+	if (fd < 0)
 		return -1;
-	}
-
-	ret = lseek(fd, size, SEEK_SET);
-	if (ret < 0) {
-		SYSERROR("Failed to seek to set new loop file size for loop "
-			 "file \"%s\"", path);
+	if (lseek(fd, size, SEEK_SET) < 0) {
+		SYSERROR("Error seeking to set new loop file size");
 		close(fd);
 		return -1;
 	}
-
-	ret = write(fd, "1", 1);
-	if (ret != 1) {
-		SYSERROR("Failed creating new loop file \"%s\"", path);
+	if (write(fd, "1", 1) != 1) {
+		SYSERROR("Error creating new loop file");
 		close(fd);
 		return -1;
 	}
-
 	ret = close(fd);
 	if (ret < 0) {
-		SYSERROR("Failed to create new loop file \"%s\"", path);
+		SYSERROR("Error closing new loop file");
 		return -1;
 	}
 
 	// create an fs in the loopback file
 	ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
 			  (void *)cmd_args);
-	if (ret < 0) {
-		ERROR("Failed to create new filesystem \"%s\" for loop file "
-		      "\"%s\": %s", fstype, path, cmd_output);
+	if (ret < 0)
 		return -1;
-	}
 
 	return 0;
 }

From 68174bb3d6401b52ca2713e15a9a3aac600cdb6a Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:06:42 +0200
Subject: [PATCH 04/24] Revert "btrfs: switch to new rsync helpers"

This reverts commit d8bb582ae3ffd1864f20bd0a9548b2a06ded66c0.
---
 src/lxc/bdev/lxcbtrfs.c | 61 +++++++++++++++++++++++--------------------------
 1 file changed, 28 insertions(+), 33 deletions(-)

diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c
index 746099630..2eaf27e86 100644
--- a/src/lxc/bdev/lxcbtrfs.c
+++ b/src/lxc/bdev/lxcbtrfs.c
@@ -242,8 +242,8 @@ static int btrfs_subvolume_create(const char *path)
 	*p = '\0';
 
 	fd = open(newfull, O_RDONLY);
+	free(newfull);
 	if (fd < 0) {
-		free(newfull);
 		return -errno;
 	}
 
@@ -255,7 +255,6 @@ static int btrfs_subvolume_create(const char *path)
 	saved_errno = errno;
 
 	close(fd);
-	free(newfull);
 	errno = saved_errno;
 	return ret;
 }
@@ -417,9 +416,8 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
 			struct bdev *new, uint64_t newsize)
 {
-	int ret;
-	struct rsync_data data = {0, 0};
-	char cmd_output[MAXPATHLEN] = {0};
+	int pid, ret;
+	struct rsync_data data;
 
 	ret = rmdir(new->dest);
 	if (ret < 0 && errno != ENOENT)
@@ -431,29 +429,37 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
 		return false;
 	}
 
-	/* rsync the contents from source to target */
-	data.orig = orig;
-	data.new = new;
-	if (am_unpriv()) {
-		ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &data,
-				    "lxc_rsync_exec_wrapper");
+	/* rsync contents */
+	pid = fork();
+	if (pid < 0) {
+		SYSERROR("fork");
+		return false;
+	}
+
+	if (pid > 0) {
+		int ret = wait_for_pid(pid);
+		bdev_put(orig);
 		if (ret < 0) {
-			ERROR("Failed to rsync from \"%s\" into \"%s\"",
-			      orig->dest, new->dest);
+			bdev_put(new);
 			return false;
 		}
-
 		return true;
 	}
 
-	ret = run_command(cmd_output, sizeof(cmd_output),
-			lxc_rsync_exec_wrapper, (void *)&data);
+	data.orig = orig;
+	data.new = new;
+
+	if (am_unpriv())
+		ret = userns_exec_1(conf, rsync_rootfs_wrapper, &data,
+				    "rsync_rootfs_wrapper");
+	else
+		ret = rsync_rootfs(&data);
 	if (ret < 0) {
-		ERROR("Failed to rsync from \"%s\" into \"%s\": %s", orig->dest,
-		      new->dest, cmd_output);
+		ERROR("Failed to rsync");
 		return false;
 	}
 
+	TRACE("Created btrfs subvolume \"%s\"", new->dest);
 	return true;
 }
 
@@ -839,27 +845,16 @@ int btrfs_create(struct bdev *bdev, const char *dest, const char *n,
 	/* strlen("btrfs:") */
 	len += 6;
 	bdev->src = malloc(len);
-	if (!bdev->src) {
-		ERROR("Failed to allocate memory");
+	if (!bdev->src)
 		return -1;
-	}
 
 	ret = snprintf(bdev->src, len, "btrfs:%s", dest);
-	if (ret < 0 || (size_t)ret >= len) {
-		ERROR("Failed to create string");
+	if (ret < 0 || (size_t)ret >= len)
 		return -1;
-	}
 
 	bdev->dest = strdup(dest);
-	if (!bdev->dest) {
-		ERROR("Failed to duplicate string \"%s\"", dest);
+	if (!bdev->dest)
 		return -1;
-	}
 
-	ret = btrfs_subvolume_create(bdev->dest);
-	if (ret < 0) {
-		SYSERROR("Failed to create btrfs subvolume \"%s\"", bdev->dest);
-	}
-
-	return ret;
+	return btrfs_subvolume_create(bdev->dest);
 }

From 1a1c9f90d9ddcf39c923d19d82fa400ddc245841 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:07:56 +0200
Subject: [PATCH 05/24] Revert "storage: switch to new rsync functions"

This reverts commit a493a694166e65edbf412433a605042cc0ac3d0e.
---
 src/lxc/bdev/bdev.c | 43 ++++++++++++++++++++++++-------------------
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index a52357262..15a275065 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -326,6 +326,7 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		       const char *bdevdata, uint64_t newsize, int *needs_rdep)
 {
 	struct bdev *orig, *new;
+	pid_t pid;
 	int ret;
 	char *src_no_prefix;
 	bool snap = flags & LXC_CLONE_SNAPSHOT;
@@ -335,7 +336,6 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	const char *oldname = c0->name;
 	const char *oldpath = c0->config_path;
 	struct rsync_data data;
-	char cmd_output[MAXPATHLEN];
 
 	/* 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.
@@ -475,28 +475,33 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		return new;
 
 	/* rsync the contents from source to target */
-	data.orig = orig;
-	data.new = new;
-	if (am_unpriv()) {
-		ret = userns_exec_1(c0->lxc_conf, lxc_rsync_exec_wrapper, &data,
-				    "lxc_rsync_exec_wrapper");
-		if (ret < 0) {
-			ERROR("Failed to rsync from \"%s\" into \"%s\"",
-			      orig->dest, new->dest);
-			goto err;
-		}
-	} else {
-		ret = run_command(cmd_output, sizeof(cmd_output),
-				  lxc_rsync_exec_wrapper, (void *)&data);
+	pid = fork();
+	if (pid < 0) {
+		SYSERROR("fork");
+		goto err;
+	}
+
+	if (pid > 0) {
+		int ret = wait_for_pid(pid);
+		bdev_put(orig);
 		if (ret < 0) {
-			ERROR("Failed to rsync from \"%s\" into \"%s\": %s",
-			      orig->dest, new->dest, cmd_output);
-			goto err;
+			bdev_put(new);
+			return NULL;
 		}
+		return new;
 	}
 
-	bdev_put(orig);
-	return new;
+	data.orig = orig;
+	data.new = new;
+	if (am_unpriv())
+		ret = userns_exec_1(c0->lxc_conf, rsync_rootfs_wrapper, &data,
+				    "rsync_rootfs_wrapper");
+	else
+		ret = rsync_rootfs(&data);
+	if (ret < 0)
+		ERROR("Failed to rsync from");
+
+	exit(ret == 0 ? 0 : 1);
 
 err:
 	bdev_put(orig);

From 10206db540bcfa19774f3f0460d800d35ee2ee9e Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:10:19 +0200
Subject: [PATCH 06/24] Revert "rsync: add new rsync functions"

This reverts commit 2ea2f3c8a6509cddbeebab92a0d3c56d4bf48be9.
---
 src/lxc/bdev/lxcrsync.c | 79 -------------------------------------------------
 src/lxc/bdev/lxcrsync.h |  5 ----
 2 files changed, 84 deletions(-)

diff --git a/src/lxc/bdev/lxcrsync.c b/src/lxc/bdev/lxcrsync.c
index ce2b5ae88..41eb881c4 100644
--- a/src/lxc/bdev/lxcrsync.c
+++ b/src/lxc/bdev/lxcrsync.c
@@ -139,82 +139,3 @@ int rsync_rootfs_wrapper(void *data)
 	struct rsync_data *arg = data;
 	return rsync_rootfs(arg);
 }
-
-/* new helpers */
-int lxc_rsync_exec_wrapper(void *data)
-{
-	struct rsync_data *arg = data;
-	return lxc_rsync(arg);
-}
-
-int lxc_rsync_exec(const char *src, const char *dest)
-{
-	int ret;
-	size_t l;
-	char *s;
-
-	l = strlen(src) + 2;
-	s = malloc(l);
-	if (!s)
-		return -1;
-
-	ret = snprintf(s, l, "%s", src);
-	if (ret < 0 || (size_t)ret >= l)
-		return -1;
-
-	s[l - 2] = '/';
-	s[l - 1] = '\0';
-
-	execlp("rsync", "rsync", "-aHXS", "--delete", s, dest, (char *)NULL);
-	return -1;
-}
-
-int lxc_rsync(struct rsync_data *data)
-{
-	int ret;
-	struct bdev *orig = data->orig, *new = data->new;
-	char *dest, *src;
-
-	ret = unshare(CLONE_NEWNS);
-	if (ret < 0) {
-		SYSERROR("Failed to unshare CLONE_NEWNS");
-		return -1;
-	}
-
-	ret = detect_shared_rootfs();
-	if (ret) {
-		ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL);
-		if (ret < 0)
-			SYSERROR("Failed to make \"/\" a slave mount");
-	}
-
-	ret = orig->ops->mount(orig);
-	if (ret < 0) {
-		ERROR("Failed mounting \"%s\" on \"%s\"", orig->src, orig->dest);
-		return -1;
-	}
-
-	ret = new->ops->mount(new);
-	if (ret < 0) {
-		ERROR("Failed mounting \"%s\" onto \"%s\"", new->src, new->dest);
-		return -1;
-	}
-
-	ret = lxc_switch_uid_gid(0, 0);
-	if (ret < 0)
-		return -1;
-	ret = lxc_setgroups(0, NULL);
-	if (ret < 0)
-		return -1;
-
-	src = lxc_storage_get_path(orig->dest, orig->type);
-	dest = lxc_storage_get_path(new->dest, new->type);
-
-	ret = lxc_rsync_exec(src, dest);
-	if (ret < 0) {
-		ERROR("Failed to rsync from \"%s\" into \"%s\"", src, dest);
-		return -1;
-	}
-
-	return 0;
-}
diff --git a/src/lxc/bdev/lxcrsync.h b/src/lxc/bdev/lxcrsync.h
index 81cac1bd0..802a88501 100644
--- a/src/lxc/bdev/lxcrsync.h
+++ b/src/lxc/bdev/lxcrsync.h
@@ -43,9 +43,4 @@ int rsync_delta(struct rsync_data_char *data);
 int rsync_rootfs(struct rsync_data *data);
 int rsync_rootfs_wrapper(void *data);
 
-/* new helpers */
-extern int lxc_rsync_exec_wrapper(void *data);
-extern int lxc_rsync_exec(const char *src, const char *dest);
-extern int lxc_rsync(struct rsync_data *data);
-
 #endif // __LXC_RSYNC_H

From 16a4b7127daabf39239b17e38b263b9e9b119209 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:10:36 +0200
Subject: [PATCH 07/24] Revert "bdev: non-functional changes"

This reverts commit 8608cb0bd3b4ecd8bdf57a397b43ee9f344b8870.
---
 src/lxc/bdev/bdev.c | 54 +++++++++++++++++++++++++----------------------------
 1 file changed, 25 insertions(+), 29 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 15a275065..2a33eebe2 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -337,12 +337,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	const char *oldpath = c0->config_path;
 	struct rsync_data data;
 
-	/* 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.
+	/* 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
 	 */
 	if (!strstr(src, oldname)) {
-		ERROR("Original rootfs path \"%s\" does not include container "
-		      "name \"%s\"", src, oldname);
+		ERROR("original rootfs path %s doesn't include container name %s",
+		      src, oldname);
 		return NULL;
 	}
 
@@ -371,13 +371,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 			bdev_put(orig);
 			return NULL;
 		}
-
 		ret = stat(orig->dest, &sb);
-		if (ret < 0 && errno == ENOENT) {
-			ret = mkdir_p(orig->dest, 0755);
-			if (ret < 0)
-				WARN("Failed to create directoy \"%s\"", orig->dest);
-		}
+
+		if (ret < 0 && errno == ENOENT)
+			if (mkdir_p(orig->dest, 0755) < 0)
+				WARN("Failed to create directoy \"%s\"",
+				     orig->dest);
 	}
 
 	/* Special case for snapshot. If the caller requested maybe_snapshot and
@@ -387,8 +386,11 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	if (maybe_snap && keepbdevtype && !bdevtype && !orig->ops->can_snapshot)
 		snap = false;
 
-	/* If newtype is NULL and snapshot is set, then use overlay. */
-	if (!bdevtype && !keepbdevtype && snap && strcmp(orig->type, "dir") == 0)
+	/*
+	 * If newtype is NULL and snapshot is set, then use overlayfs
+	 */
+	if (!bdevtype && !keepbdevtype && snap &&
+	    strcmp(orig->type, "dir") == 0)
 		bdevtype = "overlay";
 
 	if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
@@ -399,12 +401,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	}
 
 	*needs_rdep = 0;
-	if (bdevtype && !strcmp(orig->type, "dir") &&
+	if (bdevtype && strcmp(orig->type, "dir") == 0 &&
 	    (strcmp(bdevtype, "aufs") == 0 ||
 	     strcmp(bdevtype, "overlayfs") == 0 ||
 	     strcmp(bdevtype, "overlay") == 0)) {
 		*needs_rdep = 1;
-	} else if (snap && !strcmp(orig->type, "lvm") &&
+	} else if (snap && strcmp(orig->type, "lvm") == 0 &&
 		   !lvm_is_thin_volume(orig->src)) {
 		*needs_rdep = 1;
 	}
@@ -417,22 +419,20 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	/* get new bdev type */
 	new = bdev_get(bdevtype);
 	if (!new) {
-		ERROR("Failed to initialize \"%s\" storage driver",
+		ERROR("no such block device type: %s",
 		      bdevtype ? bdevtype : orig->type);
 		bdev_put(orig);
 		return NULL;
 	}
-	TRACE("Initialized \"%s\" storage driver", new->type);
+	TRACE("Detected \"%s\" storage driver", new->type);
 
 	/* create new paths */
-	ret = new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
-				    snap, newsize, c0->lxc_conf);
-	if (ret < 0) {
-		ERROR("Failed creating new paths for clone of \"%s\"", src);
+	if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
+				  snap, newsize, c0->lxc_conf) < 0) {
+		ERROR("Failed getting pathnames for clone of \"%s\"", src);
 		goto err;
 	}
 
-	/* btrfs */
 	if (!strcmp(orig->type, "btrfs") && !strcmp(new->type, "btrfs")) {
 		bool bret = false;
 		if (snap || btrfs_same_fs(orig->dest, new->dest) == 0)
@@ -444,7 +444,6 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		return new;
 	}
 
-	/* lvm */
 	if (!strcmp(orig->type, "lvm") && !strcmp(new->type, "lvm")) {
 		bool bret = false;
 		if (snap)
@@ -459,22 +458,19 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	}
 
 	if (strcmp(bdevtype, "btrfs")) {
-		if (!strcmp(new->type, "overlay") || !strcmp(new->type, "overlayfs"))
+		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()) {
-			ret = chown_mapped_root(src_no_prefix, c0->lxc_conf);
-			if (ret < 0)
-				WARN("Failed to chown \"%s\"", new->src);
-		}
+		if (am_unpriv() && chown_mapped_root(src_no_prefix, c0->lxc_conf) < 0)
+			WARN("Failed to chown \"%s\"", src_no_prefix);
 	}
 
 	if (snap)
 		return new;
 
-	/* rsync the contents from source to target */
 	pid = fork();
 	if (pid < 0) {
 		SYSERROR("fork");

From bdd2d3fe7889ca12dd3ead212dcef9dfebe75498 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:10:53 +0200
Subject: [PATCH 08/24] Revert "dir: improvements"

This reverts commit 23eb8575d414d8b448398e9ed45d83741296a1ca.
---
 src/lxc/bdev/lxcdir.c | 68 ++++++++++++++++++---------------------------------
 1 file changed, 24 insertions(+), 44 deletions(-)

diff --git a/src/lxc/bdev/lxcdir.c b/src/lxc/bdev/lxcdir.c
index ee1aea25a..bf2336539 100644
--- a/src/lxc/bdev/lxcdir.c
+++ b/src/lxc/bdev/lxcdir.c
@@ -39,12 +39,12 @@ int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		   const char *cname, const char *oldpath, const char *lxcpath,
 		   int snap, uint64_t newsize, struct lxc_conf *conf)
 {
-	char *src_no_prefix;
 	int ret;
 	size_t len;
 
 	if (snap) {
-		ERROR("Directories cannot be snapshotted");
+		ERROR("directories cannot be snapshotted.  Try aufs or "
+		      "overlayfs.");
 		return -1;
 	}
 
@@ -53,25 +53,17 @@ int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 
 	len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 4 + 3;
 	new->src = malloc(len);
-	if (!new->src) {
-		ERROR("Failed to allocate memory");
+	if (!new->src)
 		return -1;
-	}
 
 	ret = snprintf(new->src, len, "dir:%s/%s/rootfs", lxcpath, cname);
-	if (ret < 0 || (size_t)ret >= len) {
-		ERROR("Failed to create string");
+	if (ret < 0 || (size_t)ret >= len)
 		return -1;
-	}
 
-	src_no_prefix = lxc_storage_get_path(new->src, new->type);
-	new->dest = strdup(src_no_prefix);
-	if (!new->dest) {
-		ERROR("Failed to duplicate string \"%s\"", new->src);
+	new->dest = strdup(new->src + 4);
+	if (!new->dest)
 		return -1;
-	}
 
-	TRACE("Created new path \"%s\" for dir storage driver", new->dest);
 	return 0;
 }
 
@@ -91,45 +83,40 @@ int dir_create(struct bdev *bdev, const char *dest, const char *n,
 
 	len += strlen(src) + 1;
 	bdev->src = malloc(len);
-	if (!bdev->src) {
-		ERROR("Failed to allocate memory");
+	if (!bdev->src)
 		return -1;
-	}
 
 	ret = snprintf(bdev->src, len, "dir:%s", src);
-	if (ret < 0 || (size_t)ret >= len) {
-		ERROR("Failed to create string");
+	if (ret < 0 || (size_t)ret >= len)
 		return -1;
-	}
 
 	bdev->dest = strdup(dest);
-	if (!bdev->dest) {
-		ERROR("Failed to duplicate string \"%s\"", dest);
+	if (!bdev->dest)
+		return -1;
+
+	ret = mkdir_p(src, 0755);
+	if (ret < 0) {
+		ERROR("Failed to create %s", src);
 		return -1;
 	}
 
-	ret = mkdir_p(dest, 0755);
+	ret = mkdir_p(bdev->dest, 0755);
 	if (ret < 0) {
-		ERROR("Failed to create directory \"%s\"", dest);
+		ERROR("Failed to create %s", bdev->dest);
 		return -1;
 	}
-	TRACE("Created directory \"%s\"", dest);
 
 	return 0;
 }
 
 int dir_destroy(struct bdev *orig)
 {
-	int ret;
 	char *src;
 
 	src = lxc_storage_get_path(orig->src, orig->src);
 
-	ret = lxc_rmdir_onedev(src, NULL);
-	if (ret < 0) {
-		ERROR("Failed to delete \"%s\"", src);
+	if (lxc_rmdir_onedev(src, NULL) < 0)
 		return -1;
-	}
 
 	return 0;
 }
@@ -146,9 +133,10 @@ int dir_detect(const char *path)
 
 int dir_mount(struct bdev *bdev)
 {
-	int ret;
-	unsigned long mflags, mntflags;
+	unsigned long mntflags;
 	char *src, *mntdata;
+	int ret;
+	unsigned long mflags;
 
 	if (strcmp(bdev->type, "dir"))
 		return -22;
@@ -156,9 +144,7 @@ int dir_mount(struct bdev *bdev)
 	if (!bdev->src || !bdev->dest)
 		return -22;
 
-	ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
-	if (ret < 0) {
-		ERROR("Failed to parse mount options \"%s\"", bdev->mntopts);
+	if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
 		free(mntdata);
 		return -22;
 	}
@@ -168,19 +154,13 @@ int dir_mount(struct bdev *bdev)
 	ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags,
 		    mntdata);
 	if ((0 == ret) && (mntflags & MS_RDONLY)) {
-		DEBUG("Remounting \"%s\" on \"%s\" readonly",
+		DEBUG("remounting %s on %s with readonly options",
 		      src ? src : "(none)", bdev->dest ? bdev->dest : "(none)");
-		mflags = add_required_remount_flags(src, bdev->dest, MS_BIND | MS_REC | mntflags | MS_REMOUNT);
+		mflags = add_required_remount_flags(
+		    src, bdev->dest, MS_BIND | MS_REC | mntflags | MS_REMOUNT);
 		ret = mount(src, bdev->dest, "bind", mflags, mntdata);
 	}
 
-	if (ret < 0) {
-		SYSERROR("Failed to mount \"%s\" on \"%s\"", src, bdev->dest);
-		free(mntdata);
-		return -1;
-	}
-
-	TRACE("Mounted \"%s\" on \"%s\"", src, bdev->dest);
 	free(mntdata);
 	return ret;
 }

From a2a5c6faa021899fef6bb82fb6d15811fa7beb04 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:11:11 +0200
Subject: [PATCH 09/24] Revert "dir: non-functional changes"

This reverts commit 8f2896da31e7822eb7894a5ade9e11652fe75f7f.
---
 src/lxc/bdev/lxcdir.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/src/lxc/bdev/lxcdir.c b/src/lxc/bdev/lxcdir.c
index bf2336539..cd3d40ad6 100644
--- a/src/lxc/bdev/lxcdir.c
+++ b/src/lxc/bdev/lxcdir.c
@@ -36,15 +36,14 @@ lxc_log_define(lxcdir, lxc);
  * name and paths for the new
  */
 int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
-		   const char *cname, const char *oldpath, const char *lxcpath,
-		   int snap, uint64_t newsize, struct lxc_conf *conf)
+		const char *cname, const char *oldpath, const char *lxcpath,
+		int snap, uint64_t newsize, struct lxc_conf *conf)
 {
 	int ret;
 	size_t len;
 
 	if (snap) {
-		ERROR("directories cannot be snapshotted.  Try aufs or "
-		      "overlayfs.");
+		ERROR("directories cannot be snapshotted.  Try aufs or overlayfs.");
 		return -1;
 	}
 
@@ -151,13 +150,11 @@ int dir_mount(struct bdev *bdev)
 
 	src = lxc_storage_get_path(bdev->src, bdev->type);
 
-	ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags,
-		    mntdata);
+	ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
 	if ((0 == ret) && (mntflags & MS_RDONLY)) {
 		DEBUG("remounting %s on %s with readonly options",
-		      src ? src : "(none)", bdev->dest ? bdev->dest : "(none)");
-		mflags = add_required_remount_flags(
-		    src, bdev->dest, MS_BIND | MS_REC | mntflags | MS_REMOUNT);
+			src ? src : "(none)", bdev->dest ? bdev->dest : "(none)");
+		mflags = add_required_remount_flags(src, bdev->dest, MS_BIND | MS_REC | mntflags | MS_REMOUNT);
 		ret = mount(src, bdev->dest, "bind", mflags, mntdata);
 	}
 

From 46e50580ae84677b65f49ba06869ab7d2744c122 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:11:26 +0200
Subject: [PATCH 10/24] Revert "storage: rework lvm backend"

This reverts commit 9a534c222664cb3b2705fcf523d67de8522011d1.
---
 src/lxc/bdev/bdev.c   |  17 +-
 src/lxc/bdev/lxclvm.c | 512 ++++++++++++++++----------------------------------
 src/lxc/bdev/lxclvm.h |   5 -
 3 files changed, 167 insertions(+), 367 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 2a33eebe2..161d1750b 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -138,8 +138,8 @@ static const struct bdev_ops lvm_ops = {
     .clone_paths = &lvm_clonepaths,
     .destroy = &lvm_destroy,
     .create = &lvm_create,
-    .create_clone = &lvm_create_clone,
-    .create_snapshot = &lvm_create_snapshot,
+    .create_clone = NULL,
+    .create_snapshot = NULL,
     .can_snapshot = true,
     .can_backup = false,
 };
@@ -444,19 +444,6 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		return new;
 	}
 
-	if (!strcmp(orig->type, "lvm") && !strcmp(new->type, "lvm")) {
-		bool bret = false;
-		if (snap)
-			bret = new->ops->create_snapshot(c0->lxc_conf, orig,
-							 new, newsize);
-		else
-			bret = new->ops->create_clone(c0->lxc_conf, orig, new,
-						      newsize);
-		if (!bret)
-			return NULL;
-		return new;
-	}
-
 	if (strcmp(bdevtype, "btrfs")) {
 		if (!strcmp(new->type, "overlay") ||
 		    !strcmp(new->type, "overlayfs"))
diff --git a/src/lxc/bdev/lxclvm.c b/src/lxc/bdev/lxclvm.c
index 98a69c647..3a1a694e8 100644
--- a/src/lxc/bdev/lxclvm.c
+++ b/src/lxc/bdev/lxclvm.c
@@ -22,8 +22,8 @@
  */
 
 #define _GNU_SOURCE
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
+#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
+#include <inttypes.h> /* Required for PRIu64 to work. */
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -36,199 +36,118 @@
 #include "config.h"
 #include "log.h"
 #include "lxclvm.h"
-#include "lxcrsync.h"
 #include "storage_utils.h"
 #include "utils.h"
 
+/* major()/minor() */
 #ifdef MAJOR_IN_MKDEV
-#include <sys/mkdev.h>
+#    include <sys/mkdev.h>
 #endif
 
 lxc_log_define(lxclvm, lxc);
 
-struct lvcreate_args {
-	const char *size;
-	const char *vg;
-	const char *lv;
-	const char *thinpool;
+extern char *dir_new_path(char *src, const char *oldname, const char *name,
+			  const char *oldpath, const char *lxcpath);
 
-	/* snapshot specific arguments */
-	const char *source_lv;
-};
-
-static int lvm_destroy_exec_wrapper(void *data)
-{
-	struct lvcreate_args *args = data;
-
-	(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
-	execlp("lvremove", "lvremove", "-f", args->lv, (char *)NULL);
-
-	return -1;
-}
-
-static int lvm_create_exec_wrapper(void *data)
-{
-	struct lvcreate_args *args = data;
-
-	(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
-	if (args->thinpool)
-		execlp("lvcreate", "lvcreate", "--thinpool", args->thinpool,
-		       "-V", args->size, args->vg, "-n", args->lv,
-		       (char *)NULL);
-	else
-		execlp("lvcreate", "lvcreate", "-L", args->size, args->vg, "-n",
-		       args->lv, (char *)NULL);
-
-	return -1;
-}
-
-static int lvm_snapshot_exec_wrapper(void *data)
-{
-	struct lvcreate_args *args = data;
-
-	(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
-	if (args->thinpool)
-		execlp("lvcreate", "lvcreate", "-s", "-n", args->lv,
-		       args->source_lv, (char *)NULL);
-	else
-		execlp("lvcreate", "lvcreate", "-s", "-L", args->size, "-n",
-		       args->lv, args->source_lv, (char *)NULL);
-
-	return -1;
-}
-
-/* The path must be "/dev/<vg>/<lv>". The volume group <vg> must be an existing
- * volume group, and the logical volume <lv> must not yet exist.
- * This function will attempt to create "/dev/<vg>/<lv> of size <size>. If
+/* Path must be '/dev/$vg/$lv', $vg must be an existing VG, and $lv must not yet
+ * exist.  This function will attempt to create /dev/$vg/$lv of size $size. If
  * thinpool is specified, we'll check for it's existence and if it's a valid
- * thin pool, and if so, we'll create the requested logical volume from that
- * thin pool.
+ * thin pool, and if so, we'll create the requested lv from that thin pool.
  */
 static int do_lvm_create(const char *path, uint64_t size, const char *thinpool)
 {
-	int len, ret;
-	char *pathdup, *vg, *lv;
-	char cmd_output[MAXPATHLEN];
-	char sz[24];
-	char *tp = NULL;
-	struct lvcreate_args cmd_args = {0};
+	int ret, pid, len;
+	char sz[24], *pathdup, *vg, *lv, *tp = NULL;
 
-	ret = snprintf(sz, 24, "%" PRIu64 "b", size);
-	if (ret < 0 || ret >= 24) {
-		ERROR("Failed to create string: %d", ret);
+	if ((pid = fork()) < 0) {
+		SYSERROR("failed fork");
 		return -1;
 	}
+	if (pid > 0)
+		return wait_for_pid(pid);
+
+	// specify bytes to lvcreate
+	ret = snprintf(sz, 24, "%"PRIu64"b", size);
+	if (ret < 0 || ret >= 24)
+		exit(EXIT_FAILURE);
 
 	pathdup = strdup(path);
-	if (!pathdup) {
-		ERROR("Failed to duplicate string \"%s\"", path);
-		return -1;
-	}
+	if (!pathdup)
+		exit(EXIT_FAILURE);
 
 	lv = strrchr(pathdup, '/');
-	if (!lv) {
-		ERROR("Failed to detect \"/\" in string \"%s\"", pathdup);
-		free(pathdup);
-		return -1;
-	}
+	if (!lv)
+		exit(EXIT_FAILURE);
+
 	*lv = '\0';
 	lv++;
-	TRACE("Parsed logical volume \"%s\"", lv);
 
 	vg = strrchr(pathdup, '/');
-	if (!vg) {
-		ERROR("Failed to detect \"/\" in string \"%s\"", pathdup);
-		free(pathdup);
-		return -1;
-	}
+	if (!vg)
+		exit(EXIT_FAILURE);
 	vg++;
-	TRACE("Parsed volume group \"%s\"", vg);
 
 	if (thinpool) {
 		len = strlen(pathdup) + strlen(thinpool) + 2;
 		tp = alloca(len);
 
 		ret = snprintf(tp, len, "%s/%s", pathdup, thinpool);
-		if (ret < 0 || ret >= len) {
-			ERROR("Failed to create string: %d", ret);
-			free(pathdup);
-			return -1;
-		}
+		if (ret < 0 || ret >= len)
+			exit(EXIT_FAILURE);
 
 		ret = lvm_is_thin_pool(tp);
-		TRACE("got %d for thin pool at path: %s", ret, tp);
-		if (ret < 0) {
-			ERROR("Failed to detect whether \"%s\" is a thinpool", tp);
-			free(pathdup);
-			return -1;
-		} else if (!ret) {
-			TRACE("Detected that \"%s\" is not a thinpool", tp);
+		INFO("got %d for thin pool at path: %s", ret, tp);
+		if (ret < 0)
+			exit(EXIT_FAILURE);
+
+		if (!ret)
 			tp = NULL;
-		} else {
-			TRACE("Detected \"%s\" is a thinpool", tp);
-		}
 	}
 
-	cmd_args.thinpool = tp;
-	cmd_args.vg = vg;
-	cmd_args.lv = lv;
-	cmd_args.size = sz;
-	TRACE("Creating new lvm storage volume \"%s\" on volume group \"%s\" "
-	      "of size \"%s\"", lv, vg, sz);
-	ret = run_command(cmd_output, sizeof(cmd_output),
-			  lvm_create_exec_wrapper, (void *)&cmd_args);
-	if (ret < 0) {
-		ERROR("Failed to create logical volume \"%s\": %s", lv,
-		      cmd_output);
-		free(pathdup);
-		return -1;
-	}
-	TRACE("Created new lvm storage volume \"%s\" on volume group \"%s\" "
-	      "of size \"%s\"", lv, vg, sz);
+	(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
+	if (!tp)
+	    execlp("lvcreate", "lvcreate", "-L", sz, vg, "-n", lv, (char *)NULL);
+	else
+	    execlp("lvcreate", "lvcreate", "--thinpool", tp, "-V", sz, vg, "-n", lv, (char *)NULL);
 
-	free(pathdup);
-	return ret;
+	SYSERROR("execlp");
+	exit(EXIT_FAILURE);
 }
 
-/* Look at "/sys/dev/block/maj:min/dm/uuid". If it contains the hardcoded LVM
- * prefix "LVM-" then this is an lvm2 LV.
+
+/*
+ * Look at /sys/dev/block/maj:min/dm/uuid.  If it contains the hardcoded LVM
+ * prefix "LVM-", then this is an lvm2 LV
  */
 int lvm_detect(const char *path)
 {
-	int fd;
-	ssize_t ret;
-	struct stat statbuf;
 	char devp[MAXPATHLEN], buf[4];
+	FILE *fout;
+	int ret;
+	struct stat statbuf;
 
 	if (strncmp(path, "lvm:", 4) == 0)
 		return 1; // take their word for it
 
 	ret = stat(path, &statbuf);
-	if (ret < 0)
+	if (ret != 0)
 		return 0;
-
 	if (!S_ISBLK(statbuf.st_mode))
 		return 0;
 
 	ret = snprintf(devp, MAXPATHLEN, "/sys/dev/block/%d:%d/dm/uuid",
-		       major(statbuf.st_rdev), minor(statbuf.st_rdev));
+			major(statbuf.st_rdev), minor(statbuf.st_rdev));
 	if (ret < 0 || ret >= MAXPATHLEN) {
-		ERROR("Failed to create string");
+		ERROR("lvm uuid pathname too long");
 		return 0;
 	}
-
-	fd = open(devp, O_RDONLY);
-	if (fd < 0)
-		return 0;
-
-	ret = read(fd, buf, sizeof(buf));
-	close(fd);
-	if (ret != sizeof(buf))
+	fout = fopen(devp, "r");
+	if (!fout)
 		return 0;
-
-	if (strncmp(buf, "LVM-", 4))
+	ret = fread(buf, 1, 4, fout);
+	fclose(fout);
+	if (ret != 4 || strncmp(buf, "LVM-", 4) != 0)
 		return 0;
-
 	return 1;
 }
 
@@ -264,10 +183,8 @@ int lvm_umount(struct bdev *bdev)
 int lvm_compare_lv_attr(const char *path, int pos, const char expected)
 {
 	struct lxc_popen_FILE *f;
-	int ret, len, status;
-	char *cmd;
-	char output[12];
-	int start=0;
+	int ret, len, status, start=0;
+	char *cmd, output[12];
 	const char *lvscmd = "lvs --unbuffered --noheadings -o lv_attr %s 2>/dev/null";
 
 	len = strlen(lvscmd) + strlen(path) - 1;
@@ -278,22 +195,23 @@ int lvm_compare_lv_attr(const char *path, int pos, const char expected)
 		return -1;
 
 	f = lxc_popen(cmd);
-	if (!f) {
+
+	if (f == NULL) {
 		SYSERROR("popen failed");
 		return -1;
 	}
 
-	if (!fgets(output, 12, f->f))
-		ret = 1;
+	ret = fgets(output, 12, f->f) == NULL;
 
 	status = lxc_pclose(f);
-	/* Assume either vg or lvs do not exist, default comparison to false. */
+
 	if (ret || WEXITSTATUS(status))
+		// Assume either vg or lvs do not exist, default
+		// comparison to false.
 		return 0;
 
 	len = strlen(output);
-	while (start < len && output[start] == ' ')
-		start++;
+	while(start < len && output[start] == ' ') start++;
 
 	if (start + pos < len && output[start + pos] == expected)
 		return 1;
@@ -313,261 +231,175 @@ int lvm_is_thin_pool(const char *path)
 
 int lvm_snapshot(const char *orig, const char *path, uint64_t size)
 {
-	int ret;
-	char *pathdup, *lv;
-	char sz[24];
-	char cmd_output[MAXPATHLEN];
-	struct lvcreate_args cmd_args = {0};
+	int ret, pid;
+	char sz[24], *pathdup, *lv;
 
-	ret = snprintf(sz, 24, "%" PRIu64 "b", size);
-	if (ret < 0 || ret >= 24) {
-		ERROR("Failed to create string");
+	if ((pid = fork()) < 0) {
+		SYSERROR("failed fork");
 		return -1;
 	}
+	if (pid > 0)
+		return wait_for_pid(pid);
 
-	pathdup = strdup(path);
-	if (!pathdup) {
-		ERROR("Failed to duplicate string \"%s\"", path);
-		return -1;
-	}
+	// specify bytes to lvcreate
+	ret = snprintf(sz, 24, "%"PRIu64"b", size);
+	if (ret < 0 || ret >= 24)
+		exit(EXIT_FAILURE);
 
+	pathdup = strdup(path);
+	if (!pathdup)
+		exit(EXIT_FAILURE);
 	lv = strrchr(pathdup, '/');
 	if (!lv) {
-		ERROR("Failed to detect \"/\" in string \"%s\"", pathdup);
 		free(pathdup);
-		return -1;
+		exit(EXIT_FAILURE);
 	}
 	*lv = '\0';
 	lv++;
-	TRACE("Parsed logical volume \"%s\"", lv);
 
-	/* Check if the original logical volume is backed by a thinpool, in
-	 * which case we cannot specify a size that's different from the
-	 * original size.
-	 */
+	// check if the original lv is backed by a thin pool, in which case we
+	// cannot specify a size that's different from the original size.
 	ret = lvm_is_thin_volume(orig);
-	if (ret < 0) {
+	if (ret == -1) {
 		free(pathdup);
 		return -1;
-	} else if (ret) {
-		cmd_args.thinpool = orig;
 	}
 
-	cmd_args.lv = lv;
-	cmd_args.source_lv = orig;
-	cmd_args.size = sz;
-	TRACE("Creating new lvm snapshot \"%s\" of \"%s\" with size \"%s\"", lv,
-	      orig, sz);
-	ret = run_command(cmd_output, sizeof(cmd_output),
-			  lvm_snapshot_exec_wrapper, (void *)&cmd_args);
-	if (ret < 0) {
-		ERROR("Failed to create logical volume \"%s\": %s", orig,
-		      cmd_output);
-		free(pathdup);
-		return -1;
+	(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
+	if (!ret) {
+		ret = execlp("lvcreate", "lvcreate", "-s", "-L", sz, "-n", lv, orig, (char *)NULL);
+	} else {
+		ret = execlp("lvcreate", "lvcreate", "-s", "-n", lv, orig, (char *)NULL);
 	}
 
 	free(pathdup);
-	return 0;
+	exit(EXIT_FAILURE);
 }
 
 int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		const char *cname, const char *oldpath, const char *lxcpath, int snap,
 		uint64_t newsize, struct lxc_conf *conf)
 {
+	char fstype[100];
+	uint64_t size = newsize;
 	int len, ret;
-	const char *vg;
+	const char *cmd_args[2];
+	char cmd_output[MAXPATHLEN];
 
 	if (!orig->src || !orig->dest)
 		return -1;
 
-	if (strcmp(orig->type, "lvm") && snap) {
-		ERROR("LVM snapshot from \"%s\" storage driver is not supported",
-		      orig->type);
-		return -1;
-	}
-
 	if (strcmp(orig->type, "lvm")) {
-		vg = lxc_global_config_value("lxc.bdev.lvm.vg");
-		new->src = lxc_string_join(
-		    "/",
-		    (const char *[]){"lvm:", "dev", vg, cname, NULL},
-		    false);
-	} else {
-		char *dup, *slider, *src;
+		const char *vg;
 
-		src = lxc_storage_get_path(orig->src, orig->type);
-
-		dup = strdup(src);
-		if (!dup) {
-			ERROR("Failed to duplicate string \"%s\"", src);
+		if (snap) {
+			ERROR("LVM snapshot from %s backing store is not supported",
+				orig->type);
 			return -1;
 		}
-
-		slider = strrchr(dup, '/');
-		if (!slider) {
-			ERROR("Failed to detect \"/\" in string \"%s\"", dup);
-			free(dup);
+		vg = lxc_global_config_value("lxc.bdev.lvm.vg");
+		if (!vg) {
+			ERROR("The \"lxc.bdev.lvm.vg\" key is not set");
 			return -1;
 		}
-		*slider = '\0';
-		slider = dup;
-
-		new->src = lxc_string_join(
-		    "/",
-		    (const char *[]){"lvm:", *slider == '/' ? ++slider : slider,
-				     cname, NULL},
-		    false);
-		free(dup);
-	}
-	if (!new->src) {
-		ERROR("Failed to create string");
-		return -1;
+
+		len = strlen("/dev/") + strlen(vg) + strlen(cname) + 4 + 2;
+		new->src = malloc(len);
+		if (!new->src)
+			return -1;
+
+		ret = snprintf(new->src, len, "lvm:/dev/%s/%s", vg, cname);
+		if (ret < 0 || ret >= len)
+			return -1;
+	} else {
+		new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath);
+		if (!new->src)
+			return -1;
 	}
 
 	if (orig->mntopts) {
 		new->mntopts = strdup(orig->mntopts);
-		if (!new->mntopts) {
-			ERROR("Failed to duplicate string \"%s\"", orig->mntopts);
+		if (!new->mntopts)
 			return -1;
-		}
 	}
 
 	len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3;
 	new->dest = malloc(len);
-	if (!new->dest) {
-		ERROR("Failed to allocate memory");
+	if (!new->dest)
 		return -1;
-	}
-
 	ret = snprintf(new->dest, len, "%s/%s/rootfs", lxcpath, cname);
-	if (ret < 0 || ret >= len) {
-		ERROR("Failed to create string");
+	if (ret < 0 || ret >= len)
 		return -1;
-	}
-
-	ret = mkdir_p(new->dest, 0755);
-	if (ret < 0) {
-		SYSERROR("Failed to create directory \"%s\"", new->dest);
+	if (mkdir_p(new->dest, 0755) < 0)
 		return -1;
-	}
-
-	return 0;
-}
-
-bool lvm_create_clone(struct lxc_conf *conf, struct bdev *orig,
-		      struct bdev *new, uint64_t newsize)
-{
-	char *src;
-	const char *thinpool;
-	int ret;
-	struct rsync_data data;
-	char *cmd_args[2];
-	char cmd_output[MAXPATHLEN];
-	char fstype[100] = "ext4";
-	uint64_t size = newsize;
 
 	if (is_blktype(orig)) {
-		/* detect size */
 		if (!newsize && blk_getsize(orig, &size) < 0) {
-			ERROR("Failed to detect size of logical volume \"%s\"",
-			      orig->src);
+			ERROR("Error getting size of %s", orig->src);
 			return -1;
 		}
-
-		/* detect filesystem */
 		if (detect_fs(orig, fstype, 100) < 0) {
-			INFO("Failed to detect filesystem type for \"%s\"", orig->src);
+			INFO("could not find fstype for %s, using ext3", orig->src);
 			return -1;
 		}
-	} else if (!newsize) {
+	} else {
+		sprintf(fstype, "ext3");
+		if (!newsize)
 			size = DEFAULT_FS_SIZE;
 	}
 
-	src = lxc_storage_get_path(new->src, "lvm");
-	thinpool = lxc_global_config_value("lxc.bdev.lvm.thin_pool");
+	if (snap) {
+		char *newsrc, *origsrc;
 
-	ret = do_lvm_create(src, size, thinpool);
-	if (ret < 0) {
-		ERROR("Failed to create lvm storage volume \"%s\"", src);
-		return -1;
-	}
-
-	cmd_args[0] = fstype;
-	cmd_args[1] = src;
-	ret = run_command(cmd_output, sizeof(cmd_output),
-			do_mkfs_exec_wrapper, (void *)cmd_args);
-	if (ret < 0) {
-		ERROR("Failed to create new filesystem \"%s\" for lvm storage "
-		      "volume \"%s\": %s", fstype, src, cmd_output);
-		return -1;
-	}
-
-	data.orig = orig;
-	data.new = new;
-	ret = rsync_rootfs(&data);
-	if (ret < 0) {
-		ERROR("Failed to rsync from \"%s\" to \"%s\"", orig->dest,
-		      new->dest);
-		return false;
-	}
-
-	TRACE("Created lvm storage volume \"%s\"", new->dest);
-	return true;
-}
-
-bool lvm_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
-			 struct bdev *new, uint64_t newsize)
-{
-	int ret;
-	char *newsrc, *origsrc;
-	uint64_t size = newsize;
+		origsrc = lxc_storage_get_path(orig->src, "lvm");
+		newsrc = lxc_storage_get_path(new->src, "lvm");
 
-	if (is_blktype(orig)) {
-		if (!newsize && blk_getsize(orig, &size) < 0) {
-			ERROR("Failed to detect size of logical volume \"%s\"",
-			      orig->src);
+		if (lvm_snapshot(origsrc, newsrc, size) < 0) {
+			ERROR("could not create %s snapshot of %s", new->src, orig->src);
 			return -1;
 		}
-	} else if (!newsize) {
-			size = DEFAULT_FS_SIZE;
-	}
+	} else {
+		char *src;
 
-	origsrc = lxc_storage_get_path(orig->src, "lvm");
-	newsrc = lxc_storage_get_path(new->src, "lvm");
+		src = lxc_storage_get_path(new->src, "lvm");
+		if (do_lvm_create(src, size, lxc_global_config_value("lxc.bdev.lvm.thin_pool")) < 0) {
+			ERROR("Error creating new lvm blockdev");
+			return -1;
+		}
 
-	ret = lvm_snapshot(origsrc, newsrc, size);
-	if (ret < 0) {
-		ERROR("Failed to create lvm \"%s\" snapshot of \"%s\"",
-		      new->src, orig->src);
-		return false;
+		cmd_args[0] = fstype;
+		cmd_args[1] = src;
+		// create an fs in the loopback file
+		ret = run_command(cmd_output, sizeof(cmd_output),
+				  do_mkfs_exec_wrapper, (void *)cmd_args);
+		if (ret < 0)
+			return -1;
 	}
 
-	TRACE("Created lvm snapshot \"%s\" from \"%s\"", new->dest, orig->dest);
-	return true;
+	return 0;
 }
 
 int lvm_destroy(struct bdev *orig)
 {
-	int ret;
-	char cmd_output[MAXPATHLEN];
-	struct lvcreate_args cmd_args = {0};
-
-	cmd_args.lv = lxc_storage_get_path(orig->src, "lvm");
-	ret = run_command(cmd_output, sizeof(cmd_output),
-			  lvm_destroy_exec_wrapper, (void *)&cmd_args);
-	if (ret < 0) {
-		ERROR("Failed to destroy logical volume \"%s\": %s", orig->src,
-		      cmd_output);
+	char *src;
+
+	pid_t pid;
+
+	if ((pid = fork()) < 0)
 		return -1;
+
+	if (!pid) {
+		(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
+		src = lxc_storage_get_path(orig->src, "lvm");
+		execlp("lvremove", "lvremove", "-f", src, (char *)NULL);
+		exit(EXIT_FAILURE);
 	}
 
-	TRACE("Destroyed logical volume \"%s\"", orig->src);
-	return 0;
+	return wait_for_pid(pid);
 }
 
 int lvm_create(struct bdev *bdev, const char *dest, const char *n,
-	       struct bdev_specs *specs)
+		struct bdev_specs *specs)
 {
 	const char *vg, *thinpool, *fstype, *lv = n;
 	uint64_t sz;
@@ -592,26 +424,20 @@ int lvm_create(struct bdev *bdev, const char *dest, const char *n,
 
 	len = strlen(vg) + strlen(lv) + 4 + 7;
 	bdev->src = malloc(len);
-	if (!bdev->src) {
-		ERROR("Failed to allocate memory");
+	if (!bdev->src)
 		return -1;
-	}
 
 	ret = snprintf(bdev->src, len, "lvm:/dev/%s/%s", vg, lv);
-	if (ret < 0 || ret >= len) {
-		ERROR("Failed to create string");
+	if (ret < 0 || ret >= len)
 		return -1;
-	}
 
-	/* size is in bytes */
+	// fssize is in bytes.
 	sz = specs->fssize;
 	if (!sz)
 		sz = DEFAULT_FS_SIZE;
 
-	ret = do_lvm_create(bdev->src + 4, sz, thinpool);
-	if (ret < 0) {
-		ERROR("Error creating new logical volume \"%s\" of size "
-		      "\"%" PRIu64 " bytes\"", bdev->src, sz);
+	if (do_lvm_create(bdev->src + 4, sz, thinpool) < 0) {
+		ERROR("Error creating new lvm blockdev %s size %"PRIu64" bytes", bdev->src, sz);
 		return -1;
 	}
 
@@ -620,27 +446,19 @@ int lvm_create(struct bdev *bdev, const char *dest, const char *n,
 		fstype = DEFAULT_FSTYPE;
 
 	cmd_args[0] = fstype;
-	cmd_args[1] = lxc_storage_get_path(bdev->src, bdev->type);
+	cmd_args[1] = bdev->src + 4;
 	ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
 			  (void *)cmd_args);
-	if (ret < 0) {
-		ERROR("Failed to create new logical volume \"%s\": %s",
-		      bdev->src, cmd_output);
+	if (ret < 0)
 		return -1;
-	}
 
-	bdev->dest = strdup(dest);
-	if (!bdev->dest) {
-		ERROR("Failed to duplicate string \"%s\"", dest);
+	if (!(bdev->dest = strdup(dest)))
 		return -1;
-	}
 
-	ret = mkdir_p(bdev->dest, 0755);
-	if (ret < 0) {
-		SYSERROR("Failed to create directory \"%s\"", bdev->dest);
+	if (mkdir_p(bdev->dest, 0755) < 0) {
+		ERROR("Error creating %s", bdev->dest);
 		return -1;
 	}
 
-	TRACE("Created new logical volume \"%s\"", bdev->dest);
 	return 0;
 }
diff --git a/src/lxc/bdev/lxclvm.h b/src/lxc/bdev/lxclvm.h
index 07824fced..6f1a972be 100644
--- a/src/lxc/bdev/lxclvm.h
+++ b/src/lxc/bdev/lxclvm.h
@@ -25,7 +25,6 @@
 #define __LXC_LVM_H
 
 #define _GNU_SOURCE
-#include <stdbool.h>
 #include <stdint.h>
 
 /* defined in bdev.h */
@@ -53,9 +52,5 @@ int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 int lvm_destroy(struct bdev *orig);
 int lvm_create(struct bdev *bdev, const char *dest, const char *n,
 		struct bdev_specs *specs);
-bool lvm_create_clone(struct lxc_conf *conf, struct bdev *orig,
-		      struct bdev *new, uint64_t newsize);
-bool lvm_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
-			 struct bdev *new, uint64_t newsize);
 
 #endif /* __LXC_LVM_H */

From 626a25b128bf6cf3f2dd8e6b1b0c0e3fb607603b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:11:52 +0200
Subject: [PATCH 11/24] Revert "storage: add arg to create_snapshot()"

This reverts commit a3e85dae4e02ad9d3b8fcf6bf301907ef55a7c01.
---
 src/lxc/bdev/bdev.c     | 2 +-
 src/lxc/bdev/bdev.h     | 2 +-
 src/lxc/bdev/lxcbtrfs.c | 2 +-
 src/lxc/bdev/lxcbtrfs.h | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 161d1750b..b00366ea4 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -436,7 +436,7 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	if (!strcmp(orig->type, "btrfs") && !strcmp(new->type, "btrfs")) {
 		bool bret = false;
 		if (snap || btrfs_same_fs(orig->dest, new->dest) == 0)
-			bret = new->ops->create_snapshot(c0->lxc_conf, orig, new, 0);
+			bret = new->ops->create_snapshot(c0->lxc_conf, orig, new);
 		else
 			bret = new->ops->create_clone(c0->lxc_conf, orig, new, 0);
 		if (!bret)
diff --git a/src/lxc/bdev/bdev.h b/src/lxc/bdev/bdev.h
index 15d46502f..5a14e3376 100644
--- a/src/lxc/bdev/bdev.h
+++ b/src/lxc/bdev/bdev.h
@@ -76,7 +76,7 @@ struct bdev_ops {
 	bool (*create_clone)(struct lxc_conf *conf, struct bdev *orig,
 			     struct bdev *new, uint64_t newsize);
 	bool (*create_snapshot)(struct lxc_conf *conf, struct bdev *orig,
-				struct bdev *new, uint64_t newsize);
+				struct bdev *new);
 	bool can_snapshot;
 	bool can_backup;
 };
diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c
index 2eaf27e86..d4685621b 100644
--- a/src/lxc/bdev/lxcbtrfs.c
+++ b/src/lxc/bdev/lxcbtrfs.c
@@ -464,7 +464,7 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
 }
 
 bool btrfs_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
-			   struct bdev *new, uint64_t newsize)
+			   struct bdev *new)
 {
 	int ret;
 
diff --git a/src/lxc/bdev/lxcbtrfs.h b/src/lxc/bdev/lxcbtrfs.h
index 0069245e8..13b483994 100644
--- a/src/lxc/bdev/lxcbtrfs.h
+++ b/src/lxc/bdev/lxcbtrfs.h
@@ -416,6 +416,6 @@ int btrfs_snapshot_wrapper(void *data);
 bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
 			struct bdev *new, uint64_t newsize);
 bool btrfs_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
-			   struct bdev *new, uint64_t newsize);
+			   struct bdev *new);
 
 #endif // __LXC_BTRFS_H

From d3fa997ffe39ab24a8b5b1ee2fb6e066a63733f6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:12:05 +0200
Subject: [PATCH 12/24] Revert "btrfs: switch to
 btrfs_create_{clone,snapshot}()"

This reverts commit 618b655b4ed187b4853841813f9831b85987339a.
---
 src/lxc/bdev/bdev.c     |  23 +++-------
 src/lxc/bdev/lxcbtrfs.c | 111 ++++++++++++------------------------------------
 src/lxc/bdev/lxcbtrfs.h |   4 --
 3 files changed, 35 insertions(+), 103 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index b00366ea4..931885b3d 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -96,8 +96,8 @@ static const struct bdev_ops btrfs_ops = {
     .clone_paths = &btrfs_clonepaths,
     .destroy = &btrfs_destroy,
     .create = &btrfs_create,
-    .create_clone = &btrfs_create_clone,
-    .create_snapshot = &btrfs_create_snapshot,
+    .create_clone = NULL,
+    .create_snapshot = NULL,
     .can_snapshot = true,
     .can_backup = true,
 };
@@ -415,8 +415,6 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		bdevtype = "dir";
 	else if (!bdevtype)
 		bdevtype = orig->type;
-
-	/* get new bdev type */
 	new = bdev_get(bdevtype);
 	if (!new) {
 		ERROR("no such block device type: %s",
@@ -426,24 +424,17 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	}
 	TRACE("Detected \"%s\" storage driver", new->type);
 
-	/* create new paths */
+	if (bdevtype && !strcmp(orig->type, "btrfs") &&
+	    !strcmp(new->type, "btrfs"))
+		snap = 1;
+
 	if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
 				  snap, newsize, c0->lxc_conf) < 0) {
 		ERROR("Failed getting pathnames for clone of \"%s\"", src);
 		goto err;
 	}
 
-	if (!strcmp(orig->type, "btrfs") && !strcmp(new->type, "btrfs")) {
-		bool bret = false;
-		if (snap || btrfs_same_fs(orig->dest, new->dest) == 0)
-			bret = new->ops->create_snapshot(c0->lxc_conf, orig, new);
-		else
-			bret = new->ops->create_clone(c0->lxc_conf, orig, new, 0);
-		if (!bret)
-			return NULL;
-		return new;
-	}
-
+	/* If the storage driver is "btrfs" then the we will create snapshot. */
 	if (strcmp(bdevtype, "btrfs")) {
 		if (!strcmp(new->type, "overlay") ||
 		    !strcmp(new->type, "overlayfs"))
diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c
index d4685621b..0003b8b6a 100644
--- a/src/lxc/bdev/lxcbtrfs.c
+++ b/src/lxc/bdev/lxcbtrfs.c
@@ -372,6 +372,7 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		     const char *lxcpath, int snap, uint64_t newsize,
 		     struct lxc_conf *conf)
 {
+	int ret;
 	char *src;
 
 	if (!orig->dest || !orig->src)
@@ -392,7 +393,7 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		ERROR("Failed to create new rootfs path");
 		return -1;
 	}
-	TRACE("Constructed new rootfs path \"%s\"", new->src);
+	TRACE("Created new rootfs path \"%s\"", new->src);
 
 	src = lxc_storage_get_path(new->src, "btrfs");
 	new->dest = strdup(src);
@@ -410,95 +411,39 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		}
 	}
 
-	return 0;
-}
-
-bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
-			struct bdev *new, uint64_t newsize)
-{
-	int pid, ret;
-	struct rsync_data data;
-
-	ret = rmdir(new->dest);
-	if (ret < 0 && errno != ENOENT)
-		return false;
-
-	ret = btrfs_subvolume_create(new->dest);
-	if (ret < 0) {
-		SYSERROR("Failed to create btrfs subvolume \"%s\"", new->dest);
-		return false;
-	}
-
-	/* rsync contents */
-	pid = fork();
-	if (pid < 0) {
-		SYSERROR("fork");
-		return false;
-	}
-
-	if (pid > 0) {
-		int ret = wait_for_pid(pid);
-		bdev_put(orig);
-		if (ret < 0) {
-			bdev_put(new);
-			return false;
+	if (snap) {
+		struct rsync_data_char sdata;
+		if (!am_unpriv()) {
+			ret = btrfs_snapshot(orig->dest, new->dest);
+			if (ret < 0) {
+				SYSERROR("Failed to create btrfs snapshot "
+					 "\"%s\" from \"%s\"",
+					 new->dest, orig->dest);
+				return -1;
+			}
+			TRACE("Created btrfs snapshot \"%s\" from \"%s\"",
+			      new->dest, orig->dest);
+			return 0;
 		}
-		return true;
-	}
-
-	data.orig = orig;
-	data.new = new;
 
-	if (am_unpriv())
-		ret = userns_exec_1(conf, rsync_rootfs_wrapper, &data,
-				    "rsync_rootfs_wrapper");
-	else
-		ret = rsync_rootfs(&data);
-	if (ret < 0) {
-		ERROR("Failed to rsync");
-		return false;
+		sdata.dest = new->dest;
+		sdata.src = orig->dest;
+		return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata,
+				     "btrfs_snapshot_wrapper");
 	}
 
-	TRACE("Created btrfs subvolume \"%s\"", new->dest);
-	return true;
-}
-
-bool btrfs_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
-			   struct bdev *new)
-{
-	int ret;
-
 	ret = rmdir(new->dest);
-	if (ret < 0 && errno != ENOENT)
-		return false;
-
-	if (am_unpriv()) {
-		struct rsync_data_char args;
-
-		args.src = orig->dest;
-		args.dest = new->dest;
-
-		ret = userns_exec_1(conf, btrfs_snapshot_wrapper, &args,
-				"btrfs_snapshot_wrapper");
-		if (ret < 0) {
-			ERROR("Failed to run \"btrfs_snapshot_wrapper\"");
-			return false;
-		}
-
-		TRACE("Created btrfs snapshot \"%s\" from \"%s\"", new->dest,
-		      orig->dest);
-		return true;
-	}
-
-	ret = btrfs_snapshot(orig->dest, new->dest);
-	if (ret < 0) {
-		SYSERROR("Failed to create btrfs snapshot \"%s\" from \"%s\"",
-			 new->dest, orig->dest);
-		return false;
+	if (ret < 0 && errno != ENOENT) {
+		SYSERROR("Failed to remove directory \"%s\"", new->dest);
+		return -1;
 	}
 
-	TRACE("Created btrfs snapshot \"%s\" from \"%s\"", new->dest, orig->dest);
-	return true;
+	ret = btrfs_subvolume_create(new->dest);
+	if (ret < 0)
+		SYSERROR("Failed to create btrfs subvolume \"%s\"", new->dest);
+	else
+		TRACE("Created btrfs subvolume \"%s\"", new->dest);
+	return ret;
 }
 
 static int btrfs_do_destroy_subvol(const char *path)
diff --git a/src/lxc/bdev/lxcbtrfs.h b/src/lxc/bdev/lxcbtrfs.h
index 13b483994..b2ebb3739 100644
--- a/src/lxc/bdev/lxcbtrfs.h
+++ b/src/lxc/bdev/lxcbtrfs.h
@@ -413,9 +413,5 @@ bool btrfs_try_remove_subvol(const char *path);
 int btrfs_same_fs(const char *orig, const char *new);
 int btrfs_snapshot(const char *orig, const char *new);
 int btrfs_snapshot_wrapper(void *data);
-bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
-			struct bdev *new, uint64_t newsize);
-bool btrfs_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
-			   struct bdev *new);
 
 #endif // __LXC_BTRFS_H

From bdc1796403a118895c481be4a0fb66b5c6b397b3 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:12:18 +0200
Subject: [PATCH 13/24] Revert "storage: add create_{clone,snapshot}()"

This reverts commit 667fa8cef1afc88bbe20c04523521556cb2946ac.
---
 src/lxc/bdev/bdev.c | 18 ------------------
 src/lxc/bdev/bdev.h |  4 ----
 2 files changed, 22 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 931885b3d..a99a05177 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -82,8 +82,6 @@ static const struct bdev_ops aufs_ops = {
     .clone_paths = &aufs_clonepaths,
     .destroy = &aufs_destroy,
     .create = &aufs_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = true,
     .can_backup = true,
 };
@@ -96,8 +94,6 @@ static const struct bdev_ops btrfs_ops = {
     .clone_paths = &btrfs_clonepaths,
     .destroy = &btrfs_destroy,
     .create = &btrfs_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = true,
     .can_backup = true,
 };
@@ -110,8 +106,6 @@ static const struct bdev_ops dir_ops = {
     .clone_paths = &dir_clonepaths,
     .destroy = &dir_destroy,
     .create = &dir_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = false,
     .can_backup = true,
 };
@@ -124,8 +118,6 @@ static const struct bdev_ops loop_ops = {
     .clone_paths = &loop_clonepaths,
     .destroy = &loop_destroy,
     .create = &loop_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = false,
     .can_backup = true,
 };
@@ -138,8 +130,6 @@ static const struct bdev_ops lvm_ops = {
     .clone_paths = &lvm_clonepaths,
     .destroy = &lvm_destroy,
     .create = &lvm_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = true,
     .can_backup = false,
 };
@@ -152,8 +142,6 @@ const struct bdev_ops nbd_ops = {
     .clone_paths = &nbd_clonepaths,
     .destroy = &nbd_destroy,
     .create = &nbd_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = true,
     .can_backup = false,
 };
@@ -166,8 +154,6 @@ static const struct bdev_ops ovl_ops = {
     .clone_paths = &ovl_clonepaths,
     .destroy = &ovl_destroy,
     .create = &ovl_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = true,
     .can_backup = true,
 };
@@ -180,8 +166,6 @@ static const struct bdev_ops rbd_ops = {
     .clone_paths = &rbd_clonepaths,
     .destroy = &rbd_destroy,
     .create = &rbd_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = false,
     .can_backup = false,
 };
@@ -194,8 +178,6 @@ static const struct bdev_ops zfs_ops = {
     .clone_paths = &zfs_clonepaths,
     .destroy = &zfs_destroy,
     .create = &zfs_create,
-    .create_clone = NULL,
-    .create_snapshot = NULL,
     .can_snapshot = true,
     .can_backup = true,
 };
diff --git a/src/lxc/bdev/bdev.h b/src/lxc/bdev/bdev.h
index 5a14e3376..22133173a 100644
--- a/src/lxc/bdev/bdev.h
+++ b/src/lxc/bdev/bdev.h
@@ -73,10 +73,6 @@ struct bdev_ops {
 			   const char *oldname, const char *cname,
 			   const char *oldpath, const char *lxcpath, int snap,
 			   uint64_t newsize, struct lxc_conf *conf);
-	bool (*create_clone)(struct lxc_conf *conf, struct bdev *orig,
-			     struct bdev *new, uint64_t newsize);
-	bool (*create_snapshot)(struct lxc_conf *conf, struct bdev *orig,
-				struct bdev *new);
 	bool can_snapshot;
 	bool can_backup;
 };

From 69d3f2de3c3a35630fdacccfd9a842308e876907 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:12:31 +0200
Subject: [PATCH 14/24] Revert "btrfs: simplify"

This reverts commit 36c55bf31c67d5048b6dd7f85ac425f3b2e22fd3.
---
 src/lxc/bdev/bdev.c | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index a99a05177..34d8e78d2 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -406,10 +406,6 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	}
 	TRACE("Detected \"%s\" storage driver", new->type);
 
-	if (bdevtype && !strcmp(orig->type, "btrfs") &&
-	    !strcmp(new->type, "btrfs"))
-		snap = 1;
-
 	if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
 				  snap, newsize, c0->lxc_conf) < 0) {
 		ERROR("Failed getting pathnames for clone of \"%s\"", src);
@@ -431,6 +427,36 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	if (snap)
 		return new;
 
+	/* https://github.com/lxc/lxc/issues/131
+	 * Use btrfs snapshot feature instead of rsync to restore if both orig
+	 * and new are btrfs.
+	 */
+	if (bdevtype && strcmp(orig->type, "btrfs") == 0 &&
+	    strcmp(new->type, "btrfs") == 0 &&
+	    btrfs_same_fs(orig->dest, new->dest) == 0) {
+		struct rsync_data_char arg;
+
+		if (btrfs_destroy(new) < 0) {
+			ERROR("Failed to destroy \"%s\" btrfs subvolume", new->dest);
+			goto err;
+		}
+
+		arg.src = orig->dest;
+		arg.dest = new->dest;
+		if (am_unpriv())
+			ret = userns_exec_1(c0->lxc_conf, btrfs_snapshot_wrapper,
+					  &arg, "btrfs_snapshot_wrapper");
+		else
+			ret = btrfs_snapshot(orig->dest, new->dest);
+		if (ret < 0) {
+			SYSERROR("Failed to create btrfs snapshot \"%s\" of \"%s\"",
+			         new->dest, orig->dest);
+			goto err;
+		}
+		bdev_put(orig);
+		return new;
+	}
+
 	pid = fork();
 	if (pid < 0) {
 		SYSERROR("fork");

From 0f0cd5b03c638f1840221b5ce7b6cb3619411f80 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:12:45 +0200
Subject: [PATCH 15/24] Revert "btrfs: simplify"

This reverts commit 1aa0201f1446f1387c649467d86e923c9e9ecccf.
---
 src/lxc/bdev/bdev.c     |  5 +++++
 src/lxc/bdev/lxcbtrfs.c | 17 ++---------------
 2 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 34d8e78d2..303821cb4 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -441,6 +441,11 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 			goto err;
 		}
 
+		if (mkdir_p(new->dest, 0755) < 0) {
+			ERROR("Failed to create directory \"%s\"", new->dest);
+			goto err;
+		}
+
 		arg.src = orig->dest;
 		arg.dest = new->dest;
 		if (am_unpriv())
diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c
index 0003b8b6a..8ab16beab 100644
--- a/src/lxc/bdev/lxcbtrfs.c
+++ b/src/lxc/bdev/lxcbtrfs.c
@@ -413,19 +413,8 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 
 	if (snap) {
 		struct rsync_data_char sdata;
-		if (!am_unpriv()) {
-			ret = btrfs_snapshot(orig->dest, new->dest);
-			if (ret < 0) {
-				SYSERROR("Failed to create btrfs snapshot "
-					 "\"%s\" from \"%s\"",
-					 new->dest, orig->dest);
-				return -1;
-			}
-			TRACE("Created btrfs snapshot \"%s\" from \"%s\"",
-			      new->dest, orig->dest);
-			return 0;
-		}
-
+		if (!am_unpriv())
+			return btrfs_snapshot(orig->dest, new->dest);
 		sdata.dest = new->dest;
 		sdata.src = orig->dest;
 		return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata,
@@ -441,8 +430,6 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 	ret = btrfs_subvolume_create(new->dest);
 	if (ret < 0)
 		SYSERROR("Failed to create btrfs subvolume \"%s\"", new->dest);
-	else
-		TRACE("Created btrfs subvolume \"%s\"", new->dest);
 	return ret;
 }
 

From 72a51ea709cf04c3783ba18cec445e8883fe3ba9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:12:58 +0200
Subject: [PATCH 16/24] Revert "btrfs: only chown_mapped_root() if not btrfs"

This reverts commit d848b631492434985ffc5de9bbd7c631101077cb.
---
 src/lxc/bdev/bdev.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 303821cb4..3a67997a8 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -412,17 +412,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		goto err;
 	}
 
-	/* If the storage driver is "btrfs" then the we will create snapshot. */
-	if (strcmp(bdevtype, "btrfs")) {
-		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 chown \"%s\"", src_no_prefix);
-	}
+	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 (snap)
 		return new;

From 6fe6f45db3945e7b27248c3dd4badec11c2b1279 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:13:11 +0200
Subject: [PATCH 17/24] Revert "btrfs: non-functional changes"

This reverts commit 8e295bc1a95441ddcf5290153322b8ca78971d8f.
---
 src/lxc/bdev/bdev.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 3a67997a8..c94abff1c 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -322,15 +322,16 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	/* 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
 	 */
-	if (!strstr(src, oldname)) {
-		ERROR("original rootfs path %s doesn't include container name %s",
-		      src, oldname);
+	if (strstr(src, oldname) == NULL) {
+		ERROR(
+		    "original rootfs path %s doesn't include container name %s",
+		    src, oldname);
 		return NULL;
 	}
 
 	orig = bdev_init(c0->lxc_conf, src, NULL, NULL);
 	if (!orig) {
-		ERROR("Failed to detect storage driver for \"%s\"", src);
+		ERROR("failed to detect blockdev type for %s", src);
 		return NULL;
 	}
 
@@ -342,14 +343,14 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		len = strlen(oldpath) + strlen(oldname) + strlen("/rootfs") + 2;
 		orig->dest = malloc(len);
 		if (!orig->dest) {
-			ERROR("Failed to allocate memory");
+			ERROR("out of memory");
 			bdev_put(orig);
 			return NULL;
 		}
 
 		ret = snprintf(orig->dest, len, "%s/%s/rootfs", oldpath, oldname);
 		if (ret < 0 || (size_t)ret >= len) {
-			ERROR("Failed to create string");
+			ERROR("rootfs path too long");
 			bdev_put(orig);
 			return NULL;
 		}
@@ -357,13 +358,14 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 
 		if (ret < 0 && errno == ENOENT)
 			if (mkdir_p(orig->dest, 0755) < 0)
-				WARN("Failed to create directoy \"%s\"",
+				WARN("Error creating '%s', continuing.",
 				     orig->dest);
 	}
 
-	/* Special case for snapshot. If the caller requested maybe_snapshot and
-	 * keepbdevtype and the backing store is directory, then proceed with a
-	 * a copy clone rather than returning error.
+	/*
+	 * 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;
@@ -408,7 +410,7 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 
 	if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
 				  snap, newsize, c0->lxc_conf) < 0) {
-		ERROR("Failed getting pathnames for clone of \"%s\"", src);
+		ERROR("failed getting pathnames for cloned storage: %s", src);
 		goto err;
 	}
 
@@ -422,9 +424,10 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	if (snap)
 		return new;
 
-	/* https://github.com/lxc/lxc/issues/131
+	/*
+	 * https://github.com/lxc/lxc/issues/131
 	 * Use btrfs snapshot feature instead of rsync to restore if both orig
-	 * and new are btrfs.
+	 * and new are btrfs
 	 */
 	if (bdevtype && strcmp(orig->type, "btrfs") == 0 &&
 	    strcmp(new->type, "btrfs") == 0 &&
@@ -432,12 +435,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		struct rsync_data_char arg;
 
 		if (btrfs_destroy(new) < 0) {
-			ERROR("Failed to destroy \"%s\" btrfs subvolume", new->dest);
+			ERROR("Error destroying %s subvolume", new->dest);
 			goto err;
 		}
 
 		if (mkdir_p(new->dest, 0755) < 0) {
-			ERROR("Failed to create directory \"%s\"", new->dest);
+			ERROR("Error creating %s directory", new->dest);
 			goto err;
 		}
 
@@ -481,7 +484,7 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	else
 		ret = rsync_rootfs(&data);
 	if (ret < 0)
-		ERROR("Failed to rsync from");
+		ERROR("Failed to rsync");
 
 	exit(ret == 0 ? 0 : 1);
 

From 2a2700700a274ca9d61742f7c89546244873e423 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:13:34 +0200
Subject: [PATCH 18/24] Revert "btrfs: enable unprivileged snapshots"

This reverts commit 2d66f57109b542b7a7a4882db74658374d2b5745.
---
 src/lxc/bdev/bdev.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index c94abff1c..829c28040 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -432,28 +432,17 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	if (bdevtype && strcmp(orig->type, "btrfs") == 0 &&
 	    strcmp(new->type, "btrfs") == 0 &&
 	    btrfs_same_fs(orig->dest, new->dest) == 0) {
-		struct rsync_data_char arg;
-
 		if (btrfs_destroy(new) < 0) {
 			ERROR("Error destroying %s subvolume", new->dest);
 			goto err;
 		}
-
 		if (mkdir_p(new->dest, 0755) < 0) {
 			ERROR("Error creating %s directory", new->dest);
 			goto err;
 		}
-
-		arg.src = orig->dest;
-		arg.dest = new->dest;
-		if (am_unpriv())
-			ret = userns_exec_1(c0->lxc_conf, btrfs_snapshot_wrapper,
-					  &arg, "btrfs_snapshot_wrapper");
-		else
-			ret = btrfs_snapshot(orig->dest, new->dest);
-		if (ret < 0) {
-			SYSERROR("Failed to create btrfs snapshot \"%s\" of \"%s\"",
-			         new->dest, orig->dest);
+		if (btrfs_snapshot(orig->dest, new->dest) < 0) {
+			ERROR("Error restoring %s to %s", orig->dest,
+			      new->dest);
 			goto err;
 		}
 		bdev_put(orig);

From af229cc57ce5db12218effa7fb2bee9364bd456f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:13:48 +0200
Subject: [PATCH 19/24] Revert "btrfs: export btrfs_snapshot_wrapper()"

This reverts commit 707f3fff59abe5db1033b4676e0063b35cfedd7b.
---
 src/lxc/bdev/lxcbtrfs.c | 2 +-
 src/lxc/bdev/lxcbtrfs.h | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c
index 8ab16beab..9a4051283 100644
--- a/src/lxc/bdev/lxcbtrfs.c
+++ b/src/lxc/bdev/lxcbtrfs.c
@@ -346,7 +346,7 @@ int btrfs_snapshot(const char *orig, const char *new)
 	return ret;
 }
 
-int btrfs_snapshot_wrapper(void *data)
+static int btrfs_snapshot_wrapper(void *data)
 {
 	char *src;
 	struct rsync_data_char *arg = data;
diff --git a/src/lxc/bdev/lxcbtrfs.h b/src/lxc/bdev/lxcbtrfs.h
index b2ebb3739..ebd8421e1 100644
--- a/src/lxc/bdev/lxcbtrfs.h
+++ b/src/lxc/bdev/lxcbtrfs.h
@@ -412,6 +412,5 @@ int is_btrfs_subvol(const char *path);
 bool btrfs_try_remove_subvol(const char *path);
 int btrfs_same_fs(const char *orig, const char *new);
 int btrfs_snapshot(const char *orig, const char *new);
-int btrfs_snapshot_wrapper(void *data);
 
 #endif // __LXC_BTRFS_H

From ea7aed2c22f6431462177474ac5b56ad06233e9f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:14:01 +0200
Subject: [PATCH 20/24] Revert "btrfs: non-functional changes"

This reverts commit fb49a3cbebd4cf6433517f8550528ecf2a8aceb9.
---
 src/lxc/bdev/lxcbtrfs.c | 99 ++++++++++++++++++++-----------------------------
 1 file changed, 40 insertions(+), 59 deletions(-)

diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c
index 9a4051283..2e2b603a8 100644
--- a/src/lxc/bdev/lxcbtrfs.c
+++ b/src/lxc/bdev/lxcbtrfs.c
@@ -222,40 +222,38 @@ int btrfs_umount(struct bdev *bdev)
 
 static int btrfs_subvolume_create(const char *path)
 {
-	int ret, saved_errno;
-	struct btrfs_ioctl_vol_args args;
-	char *p, *newfull;
-	int fd = -1;
+	int ret, fd = -1;
+	struct btrfs_ioctl_vol_args  args;
+	char *p, *newfull = strdup(path);
 
-	newfull = strdup(path);
 	if (!newfull) {
-		errno = ENOMEM;
-		return -ENOMEM;
+		ERROR("Error: out of memory");
+		return -1;
 	}
 
 	p = strrchr(newfull, '/');
 	if (!p) {
+		ERROR("bad path: %s", path);
 		free(newfull);
-		errno = EINVAL;
-		return -EINVAL;
+		return -1;
 	}
 	*p = '\0';
 
 	fd = open(newfull, O_RDONLY);
-	free(newfull);
 	if (fd < 0) {
-		return -errno;
+		ERROR("Error opening %s", newfull);
+		free(newfull);
+		return -1;
 	}
 
 	memset(&args, 0, sizeof(args));
-	strncpy(args.name, p + 1, BTRFS_SUBVOL_NAME_MAX);
-	args.name[BTRFS_SUBVOL_NAME_MAX - 1] = 0;
-
+	strncpy(args.name, p+1, BTRFS_SUBVOL_NAME_MAX);
+	args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
 	ret = ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args);
-	saved_errno = errno;
+	INFO("btrfs: snapshot create ioctl returned %d", ret);
 
+	free(newfull);
 	close(fd);
-	errno = saved_errno;
 	return ret;
 }
 
@@ -302,37 +300,39 @@ int btrfs_same_fs(const char *orig, const char *new)
 
 int btrfs_snapshot(const char *orig, const char *new)
 {
-	struct btrfs_ioctl_vol_args_v2 args;
-	char *newdir, *newname;
-	char *newfull = NULL;
-	int saved_errno = -1;
 	int fd = -1, fddst = -1, ret = -1;
+	struct btrfs_ioctl_vol_args_v2  args;
+	char *newdir, *newname, *newfull = NULL;
 
 	newfull = strdup(new);
-	if (!newfull)
+	if (!newfull) {
+		ERROR("Error: out of memory");
 		goto out;
-
-	ret = rmdir(newfull);
-	if (ret < 0 && errno != ENOENT)
+	}
+	// make sure the directory doesn't already exist
+	if (rmdir(newfull) < 0 && errno != ENOENT) {
+		SYSERROR("Error removing empty new rootfs");
 		goto out;
-
+	}
 	newname = basename(newfull);
+	newdir = dirname(newfull);
 	fd = open(orig, O_RDONLY);
-	if (fd < 0)
+	if (fd < 0) {
+		SYSERROR("Error opening original rootfs %s", orig);
 		goto out;
-
-	newdir = dirname(newfull);
+	}
 	fddst = open(newdir, O_RDONLY);
-	if (fddst < 0)
+	if (fddst < 0) {
+		SYSERROR("Error opening new container dir %s", newdir);
 		goto out;
+	}
 
 	memset(&args, 0, sizeof(args));
 	args.fd = fd;
 	strncpy(args.name, newname, BTRFS_SUBVOL_NAME_MAX);
-	args.name[BTRFS_SUBVOL_NAME_MAX - 1] = 0;
-
+	args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
 	ret = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
-	saved_errno = errno;
+	INFO("btrfs: snapshot create ioctl returned %d", ret);
 
 out:
 	if (fddst != -1)
@@ -340,9 +340,6 @@ int btrfs_snapshot(const char *orig, const char *new)
 	if (fd != -1)
 		close(fd);
 	free(newfull);
-
-	if (saved_errno >= 0)
-		errno = saved_errno;
 	return ret;
 }
 
@@ -357,13 +354,13 @@ static int btrfs_snapshot_wrapper(void *data)
 	}
 	if (setgroups(0, NULL) < 0)
 		WARN("Failed to clear groups");
-
 	if (setuid(0) < 0) {
 		ERROR("Failed to setuid to 0");
 		return -1;
 	}
 
 	src = lxc_storage_get_path(arg->src, "btrfs");
+
 	return btrfs_snapshot(src, arg->dest);
 }
 
@@ -372,7 +369,6 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		     const char *lxcpath, int snap, uint64_t newsize,
 		     struct lxc_conf *conf)
 {
-	int ret;
 	char *src;
 
 	if (!orig->dest || !orig->src)
@@ -389,27 +385,16 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 	    (const char *[]){"btrfs:", *lxcpath != '/' ? lxcpath : ++lxcpath,
 			     cname, "rootfs", NULL},
 	    false);
-	if (!new->src) {
-		ERROR("Failed to create new rootfs path");
+	if (!new->src)
 		return -1;
-	}
-	TRACE("Created new rootfs path \"%s\"", new->src);
 
 	src = lxc_storage_get_path(new->src, "btrfs");
 	new->dest = strdup(src);
-	if (!new->dest) {
-		ERROR("Failed to duplicate string \"%s\"", src);
+	if (!new->dest)
 		return -1;
-	}
 
-	if (orig->mntopts) {
-		new->mntopts = strdup(orig->mntopts);
-		if (!new->mntopts) {
-			ERROR("Failed to duplicate string \"%s\"",
-			      orig->mntopts);
-			return -1;
-		}
-	}
+	if (orig->mntopts && (new->mntopts = strdup(orig->mntopts)) == NULL)
+		return -1;
 
 	if (snap) {
 		struct rsync_data_char sdata;
@@ -421,16 +406,12 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 				     "btrfs_snapshot_wrapper");
 	}
 
-	ret = rmdir(new->dest);
-	if (ret < 0 && errno != ENOENT) {
-		SYSERROR("Failed to remove directory \"%s\"", new->dest);
+	if (rmdir(new->dest) < 0 && errno != ENOENT) {
+		SYSERROR("removing %s", new->dest);
 		return -1;
 	}
 
-	ret = btrfs_subvolume_create(new->dest);
-	if (ret < 0)
-		SYSERROR("Failed to create btrfs subvolume \"%s\"", new->dest);
-	return ret;
+	return btrfs_subvolume_create(new->dest);
 }
 
 static int btrfs_do_destroy_subvol(const char *path)

From bc006bbf53e24b6186de8c0c31c7cbcec2bc7ec2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:14:19 +0200
Subject: [PATCH 21/24] Revert "tools: remove empty snap directory"

This reverts commit d51915386e22a19da131a578330ab1115905c326.
---
 src/lxc/tools/lxc_destroy.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lxc/tools/lxc_destroy.c b/src/lxc/tools/lxc_destroy.c
index 8b932dd17..fee4d8049 100644
--- a/src/lxc/tools/lxc_destroy.c
+++ b/src/lxc/tools/lxc_destroy.c
@@ -171,7 +171,7 @@ static bool do_destroy(struct lxc_container *c)
 	if (ret < 0 || ret >= MAXPATHLEN)
 		return false;
 
-	if (rmdir(path) < 0 && errno != ENOENT) {
+	if (dir_exists(path)) {
 		if (!quiet)
 			fprintf(stdout, "Destroying %s failed: %s has snapshots.\n", c->name, c->name);
 		return false;
@@ -271,7 +271,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
 	if (ret < 0 || ret >= MAXPATHLEN)
 		return false;
 
-	if (rmdir(path) < 0 && errno != ENOENT)
+	if (dir_exists(path))
 		bret = c->destroy_with_snapshots(c);
 	else
 		bret = do_destroy(c);

From 40269b877a44e7054c9ef211f91d16f05bf6fe16 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:14:33 +0200
Subject: [PATCH 22/24] Revert "overlay: simplify and adapt to "overlay""

This reverts commit 7f79cc4c3457459dc20c4e40398395c5150618a9.
---
 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, 72 insertions(+), 105 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 829c28040..e41c6e808 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -194,7 +194,6 @@ static const struct bdev_type bdevs[] = {
 	{ .name = "btrfs",     .ops = &btrfs_ops, },
 	{ .name = "dir",       .ops = &dir_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,   },
@@ -375,11 +374,10 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 	 */
 	if (!bdevtype && !keepbdevtype && snap &&
 	    strcmp(orig->type, "dir") == 0)
-		bdevtype = "overlay";
+		bdevtype = "overlayfs";
 
 	if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
-		ERROR("Unsupported snapshot type \"%s\" for unprivileged users",
-		      bdevtype ? bdevtype : "(null)");
+		ERROR("Unsupported snapshot type for unprivileged users");
 		bdev_put(orig);
 		return NULL;
 	}
@@ -387,8 +385,7 @@ 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, "overlay") == 0)) {
+	     strcmp(bdevtype, "overlayfs") == 0)) {
 		*needs_rdep = 1;
 	} else if (snap && strcmp(orig->type, "lvm") == 0 &&
 		   !lvm_is_thin_volume(orig->src)) {
@@ -414,10 +411,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		goto err;
 	}
 
-	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);
+	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 92cbb8adf..18fb2754f 100644
--- a/src/lxc/bdev/lxcoverlay.c
+++ b/src/lxc/bdev/lxcoverlay.c
@@ -34,7 +34,6 @@
 #include "lxccontainer.h"
 #include "lxcoverlay.h"
 #include "lxcrsync.h"
-#include "storage_utils.h"
 #include "utils.h"
 
 lxc_log_define(lxcoverlay, lxc);
@@ -42,6 +41,10 @@ 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);
@@ -58,18 +61,16 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
         char *src;
 
 	if (!snap) {
-		ERROR("overlay is only for snapshot clones");
+		ERROR("overlayfs is only for snapshot clones");
 		return -22;
 	}
 
 	if (!orig->src || !orig->dest)
 		return -1;
 
-	new->dest = lxc_string_join(
-	    "/", (const char *[]){lxcpath, cname, "rootfs", NULL}, false);
+	new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath);
 	if (!new->dest)
 		return -1;
-
 	if (mkdir_p(new->dest, 0755) < 0)
 		return -1;
 
@@ -142,11 +143,11 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 			free(delta);
 			return -ENOMEM;
 		}
-		ret = snprintf(new->src, len, "overlay:%s:%s", src, delta);
+		ret = snprintf(new->src, len, "overlayfs:%s:%s", src, delta);
 		free(delta);
 		if (ret < 0 || ret >= len)
-			return -1;
-	} else if (!strcmp(orig->type, "overlayfs") || !strcmp(orig->type, "overlay")) {
+			return -ENOMEM;
+	} else if (strcmp(orig->type, "overlayfs") == 0) {
 		/*
 		 * What exactly do we want to do here?  I think we want to use
 		 * the original lowerdir, with a private delta which is
@@ -155,44 +156,26 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		char *osrc, *odelta, *nsrc, *ndelta, *work;
 		char *lastslash;
 		int len, ret, lastslashidx;
-
-		osrc = strdup(orig->src);
-		if (!osrc) {
-                        SYSERROR("Failed to duplicate \"%s\"", orig->src);
+		if (!(osrc = strdup(orig->src)))
 			return -22;
-                }
-
 		nsrc = strchr(osrc, ':') + 1;
-		if ((nsrc != osrc + 8) && (nsrc != osrc + 10)) {
-			free(osrc);
-                        ERROR("Detected \":\" in \"%s\" at wrong position", osrc);
-			return -22;
-                }
-
-		odelta = strchr(nsrc, ':');
-		if (!odelta) {
+		if (nsrc != osrc + 10 || (odelta = strchr(nsrc, ':')) == NULL) {
 			free(osrc);
-                        ERROR("Failed to find \":\" in \"%s\"", nsrc);
 			return -22;
 		}
-
 		*odelta = '\0';
 		odelta++;
-                ndelta = lxc_string_join("/", (const char *[]){lxcpath, cname, "rootfs", NULL}, false);
-                if (!ndelta) {
+		ndelta = dir_new_path(odelta, oldname, cname, oldpath, lxcpath);
+		if (!ndelta) {
 			free(osrc);
-                        ERROR("Failed to create new path");
 			return -ENOMEM;
-                }
-
-		ret = mkdir(ndelta, 0755);
-		if (ret < 0 && errno != EEXIST) {
+		}
+		if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) {
+			SYSERROR("error: mkdir %s", ndelta);
 			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);
 
@@ -204,7 +187,6 @@ 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++;
@@ -214,43 +196,37 @@ 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");
-		ret = mkdir(work, 0755);
-		if (ret < 0 && errno != EEXIST) {
+		if ((mkdir(work, 0755) < 0) && errno != EEXIST) {
+			SYSERROR("error: mkdir %s", work);
 			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) + 10;
+		len = strlen(nsrc) + strlen(ndelta) + 12;
 		new->src = malloc(len);
 		if (!new->src) {
 			free(osrc);
 			free(ndelta);
-			ERROR("Failed to allocate memory");
 			return -ENOMEM;
 		}
-		ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
+		ret = snprintf(new->src, len, "overlayfs:%s:%s", nsrc, ndelta);
 		free(osrc);
 		free(ndelta);
-		if (ret < 0 || ret >= len) {
-			ERROR("Failed to create string");
-			return -1;
-                }
+		if (ret < 0 || ret >= len)
+			return -ENOMEM;
 
 		return ovl_do_rsync(orig, new, conf);
 	} else {
-		ERROR("overlay clone of %s container is not yet supported",
+		ERROR("overlayfs clone of %s container is not yet supported",
 		      orig->type);
 		/*
 		 * Note, supporting this will require ovl_mount supporting
@@ -263,7 +239,7 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 }
 
 /*
- * to say 'lxc-create -t ubuntu -n o1 -B overlay' means you want
+ * to say 'lxc-create -t ubuntu -n o1 -B overlayfs' means you want
  * $lxcpath/$lxcname/rootfs to have the created container, while all
  * changes after starting the container are written to
  * $lxcpath/$lxcname/delta0
@@ -291,14 +267,14 @@ int ovl_create(struct bdev *bdev, const char *dest, const char *n,
 		return -1;
 	}
 
-	// overlay:lower:upper
-	newlen = (2 * len) + strlen("overlay:") + 2;
+	// overlayfs:lower:upper
+	newlen = (2 * len) + strlen("overlayfs:") + 2;
 	bdev->src = malloc(newlen);
 	if (!bdev->src) {
 		ERROR("Out of memory");
 		return -1;
 	}
-	ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta);
+	ret = snprintf(bdev->src, newlen, "overlayfs:%s:%s", dest, delta);
 	if (ret < 0 || ret >= newlen)
 		return -1;
 
@@ -312,23 +288,14 @@ int ovl_create(struct bdev *bdev, const char *dest, const char *n,
 
 int ovl_destroy(struct bdev *orig)
 {
-        bool ovl;
-	char *upper = orig->src;
+	char *upper;
 
-        ovl = !strncmp(upper, "overlay:", 8);
-	if (!ovl && strncmp(upper, "overlayfs:", 10))
+	if (strncmp(orig->src, "overlayfs:", 10) != 0)
 		return -22;
-
-        if (ovl)
-                upper += 8;
-        else
-                upper += 10;
-
-	upper = strchr(upper, ':');
+	upper = strchr(orig->src + 10, ':');
 	if (!upper)
 		return -22;
 	upper++;
-
 	return lxc_rmdir_onedev(upper, NULL);
 }
 
@@ -339,6 +306,14 @@ 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;
@@ -349,9 +324,8 @@ int ovl_mount(struct bdev *bdev)
 	char *mntdata;
 	int ret, ret2;
 
-	if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
+	if (strcmp(bdev->type, "overlayfs"))
 		return -22;
-
 	if (!bdev->src || !bdev->dest)
 		return -22;
 
@@ -445,7 +419,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("Overlay: Error mounting %s onto %s with options %s. "
+		INFO("Overlayfs: Error mounting %s onto %s with options %s. "
 		     "Retrying without workdir: %s.",
 		     lower, bdev->dest, options_work, strerror(errno));
 
@@ -453,15 +427,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("Overlay: Error mounting %s onto %s with "
+			SYSERROR("Overlayfs: Error mounting %s onto %s with "
 				 "options %s: %s.",
 				 lower, bdev->dest, options,
 				 strerror(errno));
 		else
-			INFO("Overlay: Mounted %s onto %s with options %s.",
+			INFO("Overlayfs: Mounted %s onto %s with options %s.",
 			     lower, bdev->dest, options);
 	} else {
-		INFO("Overlay: Mounted %s onto %s with options %s.", lower,
+		INFO("Overlayfs: Mounted %s onto %s with options %s.", lower,
 		     bdev->dest, options_work);
 	}
 	return ret;
@@ -469,31 +443,13 @@ int ovl_mount(struct bdev *bdev)
 
 int ovl_umount(struct bdev *bdev)
 {
-	if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
+	if (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;
@@ -802,7 +758,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 overlay delta");
+		ERROR("copying overlayfs delta");
 
 	return ret;
 }
diff --git a/src/lxc/bdev/lxcoverlay.h b/src/lxc/bdev/lxcoverlay.h
index fe70d3dbc..8ef277b83 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_get_lower(const char *rootfs_path);
+char *ovl_getlower(char *p);
 
 /*
  * 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 5e3f1fc3b..0cf9710fb 100644
--- a/src/lxc/bdev/storage_utils.c
+++ b/src/lxc/bdev/storage_utils.c
@@ -415,7 +415,6 @@ 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)
@@ -428,7 +427,6 @@ 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 f4701fbdb..c2018305d 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3623,6 +3623,7 @@ 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];
@@ -3658,6 +3659,23 @@ 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 fbf76164e..657f703ef 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -3225,8 +3225,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 overlay]
--s -B overlay
+-s [ implies overlayfs]
+-s -B overlayfs
 -s -B aufs
 
 only rootfs gets converted (copied/snapshotted) on clone.
@@ -3600,7 +3600,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 overlay clone first, snapshot that");
+		ERROR("please create an aufs or overlayfs clone first, snapshot that");
 		ERROR("and keep the original container pristine.");
 		flags &= ~LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT;
 	}

From b25790c1fcc4bcafa1a31fa3c53d4686536f8533 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:14:46 +0200
Subject: [PATCH 23/24] Revert "lvm: non-functional changes"

This reverts commit 7a8d7de2476b61005d80503ab8c816809bbc2d89.
---
 src/lxc/bdev/lxclvm.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/src/lxc/bdev/lxclvm.c b/src/lxc/bdev/lxclvm.c
index 3a1a694e8..4f7750b25 100644
--- a/src/lxc/bdev/lxclvm.c
+++ b/src/lxc/bdev/lxclvm.c
@@ -47,14 +47,23 @@
 lxc_log_define(lxclvm, lxc);
 
 extern char *dir_new_path(char *src, const char *oldname, const char *name,
-			  const char *oldpath, const char *lxcpath);
-
-/* Path must be '/dev/$vg/$lv', $vg must be an existing VG, and $lv must not yet
- * exist.  This function will attempt to create /dev/$vg/$lv of size $size. If
- * thinpool is specified, we'll check for it's existence and if it's a valid
- * thin pool, and if so, we'll create the requested lv from that thin pool.
- */
-static int do_lvm_create(const char *path, uint64_t size, const char *thinpool)
+		const char *oldpath, const char *lxcpath);
+
+    /*
+     * LVM ops
+     */
+
+    /*
+     * path must be '/dev/$vg/$lv', $vg must be an existing VG, and $lv must not
+     * yet exist.  This function will attempt to create /dev/$vg/$lv of size
+     * $size. If thinpool is specified, we'll check for it's existence and if
+     * it's
+     * a valid thin pool, and if so, we'll create the requested lv from that
+     * thin
+     * pool.
+     */
+    static int do_lvm_create(const char *path, uint64_t size,
+			     const char *thinpool)
 {
 	int ret, pid, len;
 	char sz[24], *pathdup, *vg, *lv, *tp = NULL;

From c42c677aa170cbc025705fb157f76594831cf7a5 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 Aug 2017 18:14:59 +0200
Subject: [PATCH 24/24] Revert "btrfs: simplify + bugfix"

This reverts commit 874a329ca6fd92057a3d243bfa6200906051393a.
---
 src/lxc/bdev/bdev.c     |  3 +--
 src/lxc/bdev/lxcbtrfs.c | 41 +++++++++++++++++++++++++++--------------
 2 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index e41c6e808..65491f016 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -392,7 +392,7 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		*needs_rdep = 1;
 	}
 
-	if (strcmp(oldpath, lxcpath) && !bdevtype && !snap)
+	if (strcmp(oldpath, lxcpath) && !bdevtype)
 		bdevtype = "dir";
 	else if (!bdevtype)
 		bdevtype = orig->type;
@@ -403,7 +403,6 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
 		bdev_put(orig);
 		return NULL;
 	}
-	TRACE("Detected \"%s\" storage driver", new->type);
 
 	if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
 				  snap, newsize, c0->lxc_conf) < 0) {
diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c
index 2e2b603a8..add3c2047 100644
--- a/src/lxc/bdev/lxcbtrfs.c
+++ b/src/lxc/bdev/lxcbtrfs.c
@@ -32,7 +32,6 @@
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
-#include <sys/wait.h>
 #include <sys/types.h>
 #include <sys/vfs.h>
 
@@ -40,10 +39,14 @@
 #include "log.h"
 #include "lxcbtrfs.h"
 #include "lxcrsync.h"
-#include "../utils.h"
+#include "utils.h"
 
 lxc_log_define(lxcbtrfs, lxc);
 
+/* 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);
+
 /*
  * Return the full path of objid under dirid.  Let's say dirid is
  * /lxc/c1/rootfs, and objid is /lxc/c1/rootfs/a/b/c.  Then we will
@@ -374,19 +377,29 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 	if (!orig->dest || !orig->src)
 		return -1;
 
-	if (strcmp(orig->type, "btrfs") && snap) {
-		ERROR("btrfs snapshot from %s backing store is not supported",
-		      orig->type);
-		return -1;
-	}
+	if (strcmp(orig->type, "btrfs")) {
+		int len, ret;
+		if (snap) {
+			ERROR("btrfs snapshot from %s backing store is not supported",
+				orig->type);
+			return -1;
+		}
 
-	new->src = lxc_string_join(
-	    "/",
-	    (const char *[]){"btrfs:", *lxcpath != '/' ? lxcpath : ++lxcpath,
-			     cname, "rootfs", NULL},
-	    false);
-	if (!new->src)
-		return -1;
+		len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 6 + 3;
+		new->src = malloc(len);
+		if (!new->src)
+			return -1;
+
+		ret = snprintf(new->src, len, "btrfs:%s/%s/rootfs", lxcpath, cname);
+		if (ret < 0 || ret >= len)
+			return -1;
+	} else {
+		/* In case rootfs is in custom path, reuse it. */
+		new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath);
+		if (!new->src)
+			return -1;
+
+	}
 
 	src = lxc_storage_get_path(new->src, "btrfs");
 	new->dest = strdup(src);


More information about the lxc-devel mailing list