[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