[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