[lxc-devel] [lxd/master] Storage: ensure volume block file
tomponline on Github
lxc-bot at linuxcontainers.org
Tue May 26 14:35:18 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 365 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200526/6cef134f/attachment-0001.bin>
-------------- next part --------------
From da07c97c13a5ea70f1b3bf29ba607dbf0dc2da97 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 18 May 2020 13:41:46 +0100
Subject: [PATCH 1/3] lxd/storage/drivers/utils: Updates ensureVolumeBlockFile
to reject unsafe volume shrinking
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/utils.go | 43 +++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 13 deletions(-)
diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index a2cf4dfa7f..af426c864d 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -324,34 +324,51 @@ func roundVolumeBlockFileSizeBytes(sizeBytes int64) (int64, error) {
return int64(sizeBytes/minBlockBoundary) * minBlockBoundary, nil
}
-// ensureVolumeBlockFile creates or resizes the raw block file for a volume to the specified size.
-func ensureVolumeBlockFile(path string, sizeBytes int64) error {
+// ensureVolumeBlockFile creates new block file or resizes the raw block file for a volume to the specified size.
+// Returns true if resize took place, false if not. Requested size is rounded to nearest block size using
+// roundVolumeBlockFileSizeBytes() before decision whether to resize is taken.
+func ensureVolumeBlockFile(path string, sizeBytes int64) (bool, error) {
if sizeBytes <= 0 {
- return fmt.Errorf("Size cannot be zero")
+ return false, fmt.Errorf("Size cannot be zero")
}
// Get rounded block size to avoid qemu boundary issues.
sizeBytes, err := roundVolumeBlockFileSizeBytes(sizeBytes)
if err != nil {
- return err
+ return false, err
}
if shared.PathExists(path) {
- _, err = shared.RunCommand("qemu-img", "resize", "-f", "raw", path, fmt.Sprintf("%d", sizeBytes))
+ fi, err := os.Stat(path)
if err != nil {
- return errors.Wrapf(err, "Failed resizing disk image %q to size %d", path, sizeBytes)
+ return false, err
}
- } else {
- // 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 = shared.RunCommand("qemu-img", "create", "-f", "raw", path, fmt.Sprintf("%d", sizeBytes))
+
+ oldSizeBytes := fi.Size()
+ if sizeBytes < oldSizeBytes {
+ return false, errors.Wrap(ErrCannotBeShrunk, "You cannot shrink block volumes")
+ }
+
+ if sizeBytes == oldSizeBytes {
+ return false, nil
+ }
+
+ _, err = shared.RunCommand("qemu-img", "resize", "-f", "raw", path, fmt.Sprintf("%d", sizeBytes))
if err != nil {
- return errors.Wrapf(err, "Failed creating disk image %q as size %d", path, sizeBytes)
+ return false, errors.Wrapf(err, "Failed resizing disk image %q to size %d", path, sizeBytes)
}
+
+ return true, nil
}
- return nil
+ // 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 = shared.RunCommand("qemu-img", "create", "-f", "raw", path, fmt.Sprintf("%d", sizeBytes))
+ if err != nil {
+ return false, errors.Wrapf(err, "Failed creating disk image %q as size %d", path, sizeBytes)
+ }
+
+ return false, nil
}
// mkfsOptions represents options for filesystem creation.
From db44b7f1132098c11f0a3f2004ef8303d52497ee Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 18 May 2020 13:40:51 +0100
Subject: [PATCH 2/3] lxd/storage/drivers/geneirc/vfs: Removes
genericVFSResizeBlockFile
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/generic_vfs.go | 38 ------------------------------
1 file changed, 38 deletions(-)
diff --git a/lxd/storage/drivers/generic_vfs.go b/lxd/storage/drivers/generic_vfs.go
index b08e691df7..bc583aa936 100644
--- a/lxd/storage/drivers/generic_vfs.go
+++ b/lxd/storage/drivers/generic_vfs.go
@@ -777,44 +777,6 @@ func genericVFSBackupUnpack(d Driver, vol Volume, snapshots []string, srcData io
return postHook, revertExternal.Fail, nil
}
-// genericVFSResizeBlockFile resizes an existing block file to the specified size. Returns true if resize took
-// place, false if not. Both requested size and existing file size are rounded to nearest block size using
-// roundVolumeBlockFileSizeBytes() before decision whether to resize is taken.
-func genericVFSResizeBlockFile(filePath string, sizeBytes int64) (bool, error) {
- if sizeBytes <= 0 {
- return false, fmt.Errorf("Size cannot be zero")
- }
-
- fi, err := os.Stat(filePath)
- if err != nil {
- return false, err
- }
-
- oldSizeBytes := fi.Size()
-
- // Round the supplied size the same way the block files created are so its accurate comparison.
- newSizeBytes, err := roundVolumeBlockFileSizeBytes(sizeBytes)
- if err != nil {
- return false, err
- }
-
- if newSizeBytes < oldSizeBytes {
- return false, errors.Wrap(ErrCannotBeShrunk, "You cannot shrink block volumes")
- }
-
- if newSizeBytes == oldSizeBytes {
- return false, nil
- }
-
- // Resize block file.
- err = ensureVolumeBlockFile(filePath, sizeBytes)
- if err != nil {
- return false, err
- }
-
- return true, nil
-}
-
// genericVFSCopyVolume copies a volume and its snapshots using a non-optimized method.
// initVolume is run against the main volume (not the snapshots) and is often used for quota initialization.
func genericVFSCopyVolume(d Driver, initVolume func(vol Volume) (func(), error), vol Volume, srcVol Volume, srcSnapshots []Volume, refresh bool, op *operations.Operation) error {
From 0c731f5982f541cd3e8deffa96e979cedbee1bbd Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 26 May 2020 15:34:02 +0100
Subject: [PATCH 3/3] lxd/storage/drivers: ensureVolumeBlockFile usage
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_btrfs_volumes.go | 4 ++--
lxd/storage/drivers/driver_dir_volumes.go | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lxd/storage/drivers/driver_btrfs_volumes.go b/lxd/storage/drivers/driver_btrfs_volumes.go
index 8367af8775..9251c586cc 100644
--- a/lxd/storage/drivers/driver_btrfs_volumes.go
+++ b/lxd/storage/drivers/driver_btrfs_volumes.go
@@ -71,7 +71,7 @@ func (d *btrfs) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Op
return err
}
- err = ensureVolumeBlockFile(rootBlockPath, sizeBytes)
+ _, err = ensureVolumeBlockFile(rootBlockPath, sizeBytes)
if err != nil {
return err
}
@@ -661,7 +661,7 @@ func (d *btrfs) SetVolumeQuota(vol Volume, size string, op *operations.Operation
return err
}
- resized, err := genericVFSResizeBlockFile(rootBlockPath, sizeBytes)
+ resized, err := ensureVolumeBlockFile(rootBlockPath, sizeBytes)
if err != nil {
return err
}
diff --git a/lxd/storage/drivers/driver_dir_volumes.go b/lxd/storage/drivers/driver_dir_volumes.go
index a980940e6e..1dc752e580 100644
--- a/lxd/storage/drivers/driver_dir_volumes.go
+++ b/lxd/storage/drivers/driver_dir_volumes.go
@@ -72,7 +72,7 @@ func (d *dir) CreateVolume(vol Volume, filler *VolumeFiller, op *operations.Oper
return err
}
- err = ensureVolumeBlockFile(rootBlockPath, sizeBytes)
+ _, err = ensureVolumeBlockFile(rootBlockPath, sizeBytes)
if err != nil {
return err
}
@@ -275,7 +275,7 @@ func (d *dir) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
return err
}
- resized, err := genericVFSResizeBlockFile(rootBlockPath, sizeBytes)
+ resized, err := ensureVolumeBlockFile(rootBlockPath, sizeBytes)
if err != nil {
return err
}
More information about the lxc-devel
mailing list