[lxc-devel] [lxd/master] VM: Use qemu-img dd mode instead of convert

tomponline on Github lxc-bot at linuxcontainers.org
Thu May 28 11:26:57 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 410 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200528/4c946f4b/attachment.bin>
-------------- next part --------------
From deef1786e9d93037c366bf24de5ffc82f467bd20 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 28 May 2020 12:20:59 +0100
Subject: [PATCH 1/4] lxd/storage/utils: Removes duplicated qemu-img call in
 ImageUnpack

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/utils.go | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go
index e4b0d2f146..8e0c2b3107 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -576,12 +576,6 @@ func ImageUnpack(imageFile string, vol drivers.Volume, destBlockFile string, blo
 		if err != nil {
 			return -1, err
 		}
-
-		// Convert the qcow2 format to a raw block device.
-		_, err = shared.RunCommand("qemu-img", "convert", "-O", "raw", imageRootfsFile, destBlockFile)
-		if err != nil {
-			return -1, fmt.Errorf("Failed converting image to raw at %s: %v", destBlockFile, err)
-		}
 	} else {
 		// Dealing with unified tarballs require an initial unpack to a temporary directory.
 		tempDir, err := ioutil.TempDir(shared.VarPath("images"), "lxd_image_unpack_")

From b29fb09d3aa123374d4f1dd4a68263d090294609 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 28 May 2020 12:20:26 +0100
Subject: [PATCH 2/4] lxd/storage/utils: Switch to qemu-img dd mode in
 ImageUnpack

To avoid issues with storage pools on loopback devices.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/utils.go | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go
index 8e0c2b3107..66b1aed6ec 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -553,8 +553,10 @@ func ImageUnpack(imageFile string, vol drivers.Volume, destBlockFile string, blo
 			}
 		}
 
-		// Convert the qcow2 format to a raw block device.
-		_, err = shared.RunCommand("qemu-img", "convert", "-f", "qcow2", "-O", "raw", imgPath, dstPath)
+		// Convert the qcow2 format to a raw block device using qemu's dd mode to avoid issues with
+		// loop backed storage pools. Use the MinBlockBoundary block size to speed up conversion.
+		logger.Debugf("Converting qcow2 image %q to raw disk %q", imgPath, dstPath)
+		_, err = shared.RunCommand("qemu-img", "dd", "-f", "qcow2", "-O", "raw", fmt.Sprintf("bs=%d", drivers.MinBlockBoundary), fmt.Sprintf("if=%s", imgPath), fmt.Sprintf("of=%s", dstPath))
 		if err != nil {
 			return -1, errors.Wrapf(err, "Failed converting image to raw at %q", dstPath)
 		}

From ba6635a6980738f5ba1415ea19121f4519418611 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 28 May 2020 12:21:30 +0100
Subject: [PATCH 3/4] lxd/storage/drivers/utils: Exports MinBlockBoundary

For use with ImageUnpack

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/drivers/utils.go | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index 85ae62d885..381ce190ad 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -18,7 +18,8 @@ import (
 	"github.com/lxc/lxd/shared/idmap"
 )
 
-const minBlockBoundary = 8192
+// MinBlockBoundary minimum block boundary size to use.
+const MinBlockBoundary = 8192
 
 // wipeDirectory empties the contents of a directory, but leaves it in place.
 func wipeDirectory(path string) error {

From 23ef563b75a2d8dbe61ff2d460d8ae4ce72da820 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 28 May 2020 12:21:50 +0100
Subject: [PATCH 4/4] lxd/storage/drivers: MinBlockBoundary usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/drivers/driver_zfs_utils.go   | 2 +-
 lxd/storage/drivers/driver_zfs_volumes.go | 4 ++--
 lxd/storage/drivers/utils.go              | 8 ++++----
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/lxd/storage/drivers/driver_zfs_utils.go b/lxd/storage/drivers/driver_zfs_utils.go
index 9cdd6c127e..62619abf6d 100644
--- a/lxd/storage/drivers/driver_zfs_utils.go
+++ b/lxd/storage/drivers/driver_zfs_utils.go
@@ -55,7 +55,7 @@ func (d *zfs) createDataset(dataset string, options ...string) error {
 }
 
 func (d *zfs) createVolume(dataset string, size int64, options ...string) error {
-	size = (size / minBlockBoundary) * minBlockBoundary
+	size = (size / MinBlockBoundary) * MinBlockBoundary
 
 	args := []string{"create", "-s", "-V", fmt.Sprintf("%d", size)}
 	for _, option := range options {
diff --git a/lxd/storage/drivers/driver_zfs_volumes.go b/lxd/storage/drivers/driver_zfs_volumes.go
index 316dfc1780..43caa00a55 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -72,7 +72,7 @@ func (d *zfs) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Oper
 			}
 
 			// Round to block boundary.
-			poolVolSizeBytes = (poolVolSizeBytes / minBlockBoundary) * minBlockBoundary
+			poolVolSizeBytes = (poolVolSizeBytes / MinBlockBoundary) * MinBlockBoundary
 
 			// If the cached volume is larger than the pool volume size, then we can't use the
 			// deleted cached image volume and instead we will rename it to a random UUID so it can't
@@ -886,7 +886,7 @@ func (d *zfs) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
 			return nil
 		}
 
-		sizeBytes = (sizeBytes / minBlockBoundary) * minBlockBoundary
+		sizeBytes = (sizeBytes / MinBlockBoundary) * MinBlockBoundary
 
 		oldSizeBytesStr, err := d.getDatasetProperty(d.dataset(vol, false), "volsize")
 		if err != nil {
diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index 381ce190ad..5a974baf5f 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -317,12 +317,12 @@ func createSparseFile(filePath string, sizeBytes int64) error {
 func roundVolumeBlockFileSizeBytes(sizeBytes int64) (int64, error) {
 	// Qemu requires image files to be in traditional storage block boundaries.
 	// We use 8k here to ensure our images are compatible with all of our backend drivers.
-	if sizeBytes < minBlockBoundary {
-		sizeBytes = minBlockBoundary
+	if sizeBytes < MinBlockBoundary {
+		sizeBytes = MinBlockBoundary
 	}
 
-	// Round the size to closest minBlockBoundary bytes to avoid qemu boundary issues.
-	return int64(sizeBytes/minBlockBoundary) * minBlockBoundary, nil
+	// Round the size to closest MinBlockBoundary bytes to avoid qemu boundary issues.
+	return int64(sizeBytes/MinBlockBoundary) * MinBlockBoundary, nil
 }
 
 // ensureVolumeBlockFile creates new block file or enlarges the raw block file for a volume to the specified size.


More information about the lxc-devel mailing list