[lxc-devel] [lxd/master] Storage: ZFS rounding up

tomponline on Github lxc-bot at linuxcontainers.org
Tue Dec 8 13:06:04 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 629 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201208/66df1a73/attachment.bin>
-------------- next part --------------
From 23835ab8cc0a8b7334fff5a185b97e67a5920f86 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 8 Dec 2020 12:56:13 +0000
Subject: [PATCH 1/8] lxd/storage/drivers/utils: Modifies
 roundVolumeBlockFileSizeBytes to round up

Ensures that the returned bytes is always greater than or equal to the input bytes.

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

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index a64635bbc2..3a216852c7 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -310,16 +310,24 @@ func ensureSparseFile(filePath string, sizeBytes int64) error {
 	return nil
 }
 
-// roundVolumeBlockFileSizeBytes parses the supplied size string and then rounds it to the nearest 8k bytes.
-func roundVolumeBlockFileSizeBytes(sizeBytes int64) (int64, error) {
+// roundVolumeBlockFileSizeBytes parses the supplied size string and then rounds it to the nearest multiple of
+// MinBlockBoundary bytes that is equal to or larger than sizeBytes.
+func roundVolumeBlockFileSizeBytes(sizeBytes int64) int64 {
 	// 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
 	}
 
+	roundedSizeBytes := int64(sizeBytes/MinBlockBoundary) * MinBlockBoundary
+
+	// Ensure the rounded size is at least the size specified in sizeBytes.
+	if roundedSizeBytes < sizeBytes {
+		roundedSizeBytes += MinBlockBoundary
+	}
+
 	// Round the size to closest MinBlockBoundary bytes to avoid qemu boundary issues.
-	return int64(sizeBytes/MinBlockBoundary) * MinBlockBoundary, nil
+	return roundedSizeBytes
 }
 
 // ensureVolumeBlockFile creates new block file or enlarges the raw block file for a volume to the specified size.

From f1a1b13c5acbd16969c5f3186d1c7cc74e2d3636 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 8 Dec 2020 12:56:55 +0000
Subject: [PATCH 2/8] lxd/storage/drivers/utils: roundVolumeBlockFileSizeBytes
 usage

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

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index 3a216852c7..b922e12160 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -339,10 +339,7 @@ func ensureVolumeBlockFile(vol Volume, path string, sizeBytes int64) (bool, erro
 	}
 
 	// Get rounded block size to avoid qemu boundary issues.
-	sizeBytes, err := roundVolumeBlockFileSizeBytes(sizeBytes)
-	if err != nil {
-		return false, err
-	}
+	sizeBytes = roundVolumeBlockFileSizeBytes(sizeBytes)
 
 	if shared.PathExists(path) {
 		fi, err := os.Stat(path)
@@ -384,7 +381,7 @@ func ensureVolumeBlockFile(vol Volume, path string, sizeBytes int64) (bool, erro
 
 	// If path doesn't exist, then there has been no filler function supplied to create it from another source.
 	// So instead create an empty volume (use for PXE booting a VM).
-	err = ensureSparseFile(path, sizeBytes)
+	err := ensureSparseFile(path, sizeBytes)
 	if err != nil {
 		return false, errors.Wrapf(err, "Failed creating disk image %q as size %d", path, sizeBytes)
 	}

From 8e7d36e48fa423424b37e5b08fb31f0025ac47f3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 8 Dec 2020 12:57:16 +0000
Subject: [PATCH 3/8] lxd/storage/drivers/driver/zfs/utils: Use
 roundVolumeBlockFileSizeBytes in createVolume

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

diff --git a/lxd/storage/drivers/driver_zfs_utils.go b/lxd/storage/drivers/driver_zfs_utils.go
index 13e59cb80f..555a71b7ab 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 = roundVolumeBlockFileSizeBytes(size)
 
 	args := []string{"create", "-s", "-V", fmt.Sprintf("%d", size)}
 	for _, option := range options {

From 6f74c97fa2c0ed9def4ae8ff7b10849eb564f099 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 8 Dec 2020 12:57:38 +0000
Subject: [PATCH 4/8] lxd/storage/drivers/driver/zfs/volumes: Use
 roundVolumeBlockFileSizeBytes in CreateVolume

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

diff --git a/lxd/storage/drivers/driver_zfs_volumes.go b/lxd/storage/drivers/driver_zfs_volumes.go
index 78152519e9..8053a8a5f6 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -73,7 +73,7 @@ func (d *zfs) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Oper
 			}
 
 			// Round to block boundary.
-			poolVolSizeBytes = (poolVolSizeBytes / MinBlockBoundary) * MinBlockBoundary
+			poolVolSizeBytes = roundVolumeBlockFileSizeBytes(poolVolSizeBytes)
 
 			// If the cached volume size is different 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

From 9ac20b24b9151559d7eae3efa0112fb774863cfb Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 8 Dec 2020 12:57:56 +0000
Subject: [PATCH 5/8] lxd/storage/drivers/driver/zfs/volumes: Use
 roundVolumeBlockFileSizeBytes in SetVolumeQuota

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

diff --git a/lxd/storage/drivers/driver_zfs_volumes.go b/lxd/storage/drivers/driver_zfs_volumes.go
index 8053a8a5f6..29e38998d8 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -921,7 +921,7 @@ func (d *zfs) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
 			return nil
 		}
 
-		sizeBytes = (sizeBytes / MinBlockBoundary) * MinBlockBoundary
+		sizeBytes = roundVolumeBlockFileSizeBytes(sizeBytes)
 
 		oldSizeBytesStr, err := d.getDatasetProperty(d.dataset(vol, false), "volsize")
 		if err != nil {

From d5e2a01d02e55871905ebdba7858fda3f3f42025 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 8 Dec 2020 12:58:23 +0000
Subject: [PATCH 6/8] lxd/storage/backend/lxd: Use revert in
 CreateInstanceFromCopy

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/backend_lxd.go | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 344de2b4d4..36854abcb7 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -744,13 +744,8 @@ func (b *lxdBackend) CreateInstanceFromCopy(inst instance.Instance, src instance
 	// We don't need to use the source instance's root disk config, so set to nil.
 	srcVol := b.newVolume(volType, contentType, srcVolStorageName, nil)
 
-	revert := true
-	defer func() {
-		if !revert {
-			return
-		}
-		b.DeleteInstance(inst, op)
-	}()
+	revert := revert.New()
+	defer revert.Fail()
 
 	srcPool, err := GetPoolByInstance(b.state, src)
 	if err != nil {
@@ -767,6 +762,8 @@ func (b *lxdBackend) CreateInstanceFromCopy(inst instance.Instance, src instance
 		defer src.Unfreeze()
 	}
 
+	revert.Add(func() { b.DeleteInstance(inst, op) })
+
 	if b.Name() == srcPool.Name() {
 		logger.Debug("CreateInstanceFromCopy same-pool mode detected")
 		err = b.driver.CreateVolumeFromCopy(vol, srcVol, snapshots, op)
@@ -876,7 +873,7 @@ func (b *lxdBackend) CreateInstanceFromCopy(inst instance.Instance, src instance
 		return err
 	}
 
-	revert = false
+	revert.Success()
 	return nil
 }
 

From a281aaa8ac06314338d7b6b8fdbba0d8bd89b969 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 8 Dec 2020 12:58:39 +0000
Subject: [PATCH 7/8] lxd/storage/backend/lxd: Don't fail in DeleteInstance if
 DB record already removed

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 36854abcb7..245f6c8015 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1471,7 +1471,7 @@ func (b *lxdBackend) DeleteInstance(inst instance.Instance, op *operations.Opera
 
 	// Remove the volume record from the database.
 	err = b.state.Cluster.RemoveStoragePoolVolume(inst.Project(), inst.Name(), volDBType, b.ID())
-	if err != nil {
+	if err != nil && errors.Cause(err) != db.ErrNoSuchObject {
 		return errors.Wrapf(err, "Error deleting storage volume from database")
 	}
 

From 4335cb1a745ab97bfad29fbc3b7793cc978057c1 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 8 Dec 2020 12:59:04 +0000
Subject: [PATCH 8/8] lxd/instance: Use revert in instanceCreateAsCopy

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

diff --git a/lxd/instance.go b/lxd/instance.go
index 11325fcaef..7d14be5be8 100644
--- a/lxd/instance.go
+++ b/lxd/instance.go
@@ -181,16 +181,11 @@ func instanceCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op *o
 }
 
 func instanceCreateAsCopy(s *state.State, args db.InstanceArgs, sourceInst instance.Instance, instanceOnly bool, refresh bool, op *operations.Operation) (instance.Instance, error) {
-	var inst, revertInst instance.Instance
+	var inst instance.Instance
 	var err error
 
-	defer func() {
-		if revertInst == nil {
-			return
-		}
-
-		revertInst.Delete(true)
-	}()
+	revert := revert.New()
+	defer revert.Fail()
 
 	if refresh {
 		// Load the target instance.
@@ -211,7 +206,8 @@ func instanceCreateAsCopy(s *state.State, args db.InstanceArgs, sourceInst insta
 		if err != nil {
 			return nil, errors.Wrap(err, "Failed creating instance record")
 		}
-		revertInst = inst
+
+		revert.Add(func() { inst.Delete(true) })
 	}
 
 	// At this point we have already figured out the parent container's root disk device so we
@@ -326,7 +322,7 @@ func instanceCreateAsCopy(s *state.State, args db.InstanceArgs, sourceInst insta
 		return nil, err
 	}
 
-	revertInst = nil
+	revert.Success()
 	return inst, nil
 }
 


More information about the lxc-devel mailing list