[lxc-devel] [lxd/master] Storage tweaks

tomponline on Github lxc-bot at linuxcontainers.org
Tue Jan 7 16:01:57 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 380 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200107/85699a50/attachment.bin>
-------------- next part --------------
From 071fc4e56dcf9b2ad5d3a983467bcbe19f1d3f6f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 6 Jan 2020 16:20:26 +0000
Subject: [PATCH 1/6] lxd/storage/drivers/driver/dir/volumes: Use
 SetVolumeQuota from UpdateVolume

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

diff --git a/lxd/storage/drivers/driver_dir_volumes.go b/lxd/storage/drivers/driver_dir_volumes.go
index ffa3acf227..068dd60297 100644
--- a/lxd/storage/drivers/driver_dir_volumes.go
+++ b/lxd/storage/drivers/driver_dir_volumes.go
@@ -197,13 +197,7 @@ func (d *dir) UpdateVolume(vol Volume, changedConfig map[string]string) error {
 	}
 
 	if _, changed := changedConfig["size"]; changed {
-		volID, err := d.getVolID(vol.volType, vol.name)
-		if err != nil {
-			return err
-		}
-
-		// Set the quota if specified in volConfig or pool config.
-		err = d.setQuota(vol.MountPath(), volID, changedConfig["size"])
+		err := d.SetVolumeQuota(vol, changedConfig["size"], nil)
 		if err != nil {
 			return err
 		}

From be98f228c684475cfcbd40b92f650076d088c6d7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 7 Jan 2020 09:20:51 +0000
Subject: [PATCH 2/6] lxd/storage/backend/lxd: Makes specific lock name for
 volume EnsureImage action

Avoids deadlock with MountTask lock during same process.

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index e4219293da..82c102be5c 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1784,9 +1784,10 @@ func (b *lxdBackend) EnsureImage(fingerprint string, op *operations.Operation) e
 		return nil // Nothing to do for drivers that don't support optimized images volumes.
 	}
 
-	// We need to lock this operation to ensure that the image is not being
-	// created multiple times.
-	unlock := locking.Lock(b.name, string(drivers.VolumeTypeImage), fingerprint)
+	// We need to lock this operation to ensure that the image is not being created multiple times.
+	// Uses a lock name of "EnsureImage_<fingerprint>" to avoid deadlocking with CreateVolume below that also
+	// establishes a lock on the volume type & name if it needs to mount the volume before filling.
+	unlock := locking.Lock(b.name, string(drivers.VolumeTypeImage), fmt.Sprintf("EnsureImage_%v", fingerprint))
 	defer unlock()
 
 	// There's no need to pass the content type or config. Both are not needed

From 2f0be1f87fb867f9804045508dd3dffcb9c7b755 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 7 Jan 2020 09:21:41 +0000
Subject: [PATCH 3/6] lxd/storage/drivers/volume: Adds UnmountTask function

Allows a volume to be temporarily unmounted (if mounted) and a function be run before volume then being re-mounted (if previously mounted).

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

diff --git a/lxd/storage/drivers/volume.go b/lxd/storage/drivers/volume.go
index b7ec773dff..fcba388445 100644
--- a/lxd/storage/drivers/volume.go
+++ b/lxd/storage/drivers/volume.go
@@ -183,6 +183,54 @@ func (v Volume) MountTask(task func(mountPath string, op *operations.Operation)
 	return task(v.MountPath(), op)
 }
 
+// UnmountTask runs the supplied task after unmounting the volume if needed. If the volume was unmounted
+// for this then it is mounted when the task finishes.
+func (v Volume) UnmountTask(task func(op *operations.Operation) error, op *operations.Operation) error {
+	isSnap := v.IsSnapshot()
+
+	// If the volume is a snapshot then call the snapshot specific mount/unmount functions as
+	// these will mount the snapshot read only.
+	if isSnap {
+		unlock := locking.Lock(v.pool, string(v.volType), v.name)
+
+		ourUnmount, err := v.driver.UnmountVolumeSnapshot(v, op)
+		if err != nil {
+			unlock()
+			return err
+		}
+
+		unlock()
+
+		if ourUnmount {
+			defer func() {
+				unlock := locking.Lock(v.pool, string(v.volType), v.name)
+				v.driver.MountVolumeSnapshot(v, op)
+				unlock()
+			}()
+		}
+	} else {
+		unlock := locking.Lock(v.pool, string(v.volType), v.name)
+
+		ourUnmount, err := v.driver.UnmountVolume(v, op)
+		if err != nil {
+			unlock()
+			return err
+		}
+
+		unlock()
+
+		if ourUnmount {
+			defer func() {
+				unlock := locking.Lock(v.pool, string(v.volType), v.name)
+				v.driver.MountVolume(v, op)
+				unlock()
+			}()
+		}
+	}
+
+	return task(op)
+}
+
 // Snapshots returns a list of snapshots for the volume.
 func (v Volume) Snapshots(op *operations.Operation) ([]Volume, error) {
 	if v.IsSnapshot() {

From 5c187fdace34557857fd83f45ce822ca39e09263 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 7 Jan 2020 09:22:32 +0000
Subject: [PATCH 4/6] lxd/storage/drivers/utils: Adds volume filesystem shrink
 and grow functions

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

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index 768aab8b69..07a8b32268 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -10,6 +10,7 @@ import (
 
 	"golang.org/x/sys/unix"
 
+	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/units"
 )
@@ -401,3 +402,65 @@ func resolveMountOptions(options string) (uintptr, string) {
 
 	return mountFlags, strings.Join(tmp, ",")
 }
+
+// shrinkFileSystem shrinks a filesystem if it is supported. Ext4 volumes will be unmounted temporarily if needed.
+func shrinkFileSystem(fsType string, devPath string, vol Volume, byteSize int64) error {
+	strSize := fmt.Sprintf("%dK", byteSize/1024)
+
+	switch fsType {
+	case "": // if not specified, default to ext4.
+		fallthrough
+	case "xfs":
+		return fmt.Errorf(`Shrinking not supported for filesystem type "%s". A dump, mkfs, and restore are required`, fsType)
+	case "ext4":
+		return vol.UnmountTask(func(op *operations.Operation) error {
+			_, err := shared.TryRunCommand("e2fsck", "-f", "-y", devPath)
+			if err != nil {
+				return err
+			}
+
+			_, err = shared.TryRunCommand("resize2fs", devPath, strSize)
+			if err != nil {
+				return err
+			}
+
+			return nil
+		}, nil)
+	case "btrfs":
+		_, err := shared.TryRunCommand("btrfs", "filesystem", "resize", strSize, vol.MountPath())
+		if err != nil {
+			return err
+		}
+	default:
+		return fmt.Errorf(`Shrinking not supported for filesystem type "%s"`, fsType)
+	}
+
+	return nil
+}
+
+// growFileSystem grows a filesystem if it is supported. The volume will be mounted temporarily if needed.
+func growFileSystem(fsType string, devPath string, vol Volume) error {
+	return vol.MountTask(func(mountPath string, op *operations.Operation) error {
+		var msg string
+		var err error
+		switch fsType {
+		case "": // if not specified, default to ext4
+			fallthrough
+		case "ext4":
+			msg, err = shared.TryRunCommand("resize2fs", devPath)
+		case "xfs":
+			msg, err = shared.TryRunCommand("xfs_growfs", devPath)
+		case "btrfs":
+			msg, err = shared.TryRunCommand("btrfs", "filesystem", "resize", "max", mountPath)
+		default:
+			return fmt.Errorf(`Growing not supported for filesystem type "%s"`, fsType)
+		}
+
+		if err != nil {
+			errorMsg := fmt.Sprintf(`Could not extend underlying %s filesystem for "%s": %s`, fsType, devPath, msg)
+			return fmt.Errorf(errorMsg)
+		}
+
+		return nil
+	}, nil)
+}

From 7e5736f85b50381277dbb01d67f4ab50bdc8b069 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 7 Jan 2020 15:56:27 +0000
Subject: [PATCH 5/6] lxd/storage/drivers/errors: Adds "not supported" error
 type

Can be used when a driver doesn't support a specific feature.

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

diff --git a/lxd/storage/drivers/errors.go b/lxd/storage/drivers/errors.go
index 56d1bdab3c..e9fb157bc6 100644
--- a/lxd/storage/drivers/errors.go
+++ b/lxd/storage/drivers/errors.go
@@ -9,3 +9,6 @@ var ErrNotImplemented = fmt.Errorf("Not implemented")
 
 // ErrUnknownDriver is the "Unknown driver" error
 var ErrUnknownDriver = fmt.Errorf("Unknown driver")
+
+// ErrNotSupported is the "Not supported" error
+var ErrNotSupported = fmt.Errorf("Not supported")

From b2eca17175e3218e4c6d33889c15c4135618aaa2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 7 Jan 2020 15:55:52 +0000
Subject: [PATCH 6/6] lxd/container/lxc: Detects storage drivers that dont
 support volume usage stats

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_lxc.go | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 7eede32fcd..e1058c6595 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -5811,7 +5811,9 @@ func (c *containerLXC) diskState() map[string]api.InstanceStateDisk {
 
 			usage, err = pool.GetInstanceUsage(c)
 			if err != nil {
-				logger.Error("Error getting disk usage", log.Ctx{"project": c.Project(), "instance": c.Name(), "err": err})
+				if err != storageDrivers.ErrNotSupported {
+					logger.Error("Error getting disk usage", log.Ctx{"project": c.Project(), "instance": c.Name(), "err": err})
+				}
 				continue
 			}
 		} else {


More information about the lxc-devel mailing list