The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/8225
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Fixes issue when copying from ceph to zfs pools, the zfs volumes were being rounded to the nearest 8192 bytes, which sometimes meant the volume size created was just too small to accommodate the source ceph volume (which doesn't round to nearest 8192 bytes). This modifies the ZFS volumes to round up to nearest 8192 bytes.
From 23835ab8cc0a8b7334fff5a185b97e67a5920f86 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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 }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel