[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