[lxc-devel] [lxd/master] Storage: LVM volume activation
tomponline on Github
lxc-bot at linuxcontainers.org
Tue May 5 13:35:40 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1164 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200505/bc0d1155/attachment-0001.bin>
-------------- next part --------------
From 0c80e5d572eca9d6f149422e0649d885aa87a01e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:16:12 +0100
Subject: [PATCH 01/13] lxd/storage/drivers/driver/lvm/utils: Adds
activateVolume and deactivateVolume functions
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_utils.go | 28 +++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/lxd/storage/drivers/driver_lvm_utils.go b/lxd/storage/drivers/driver_lvm_utils.go
index 4c6f543528..1b5191eeb8 100644
--- a/lxd/storage/drivers/driver_lvm_utils.go
+++ b/lxd/storage/drivers/driver_lvm_utils.go
@@ -737,3 +737,31 @@ func (d *lvm) thinPoolVolumeUsage(volDevPath string) (uint64, uint64, error) {
return totalSize, usedSize, nil
}
+
+// activateVolume activates an LVM logical volume if not already present. Returns true if activated, false if not.
+func (d *lvm) activateVolume(volDevPath string) (bool, error) {
+ if !shared.PathExists(volDevPath) {
+ _, err := shared.RunCommand("lvchange", "--activate", "y", "--ignoreactivationskip", volDevPath)
+ if err != nil {
+ return false, errors.Wrapf(err, "Failed to activate LVM logical volume %q", volDevPath)
+ }
+ d.logger.Debug("Activated logical volume", log.Ctx{"dev": volDevPath})
+ return true, nil
+ }
+
+ return false, nil
+}
+
+// deactivateVolume deactivates an LVM logical volume if present. Returns true if deactivated, false if not.
+func (d *lvm) deactivateVolume(volDevPath string) (bool, error) {
+ if shared.PathExists(volDevPath) {
+ _, err := shared.RunCommand("lvchange", "--activate", "n", "--ignoreactivationskip", volDevPath)
+ if err != nil {
+ return false, errors.Wrapf(err, "Failed to deactivate LVM logical volume %q", volDevPath)
+ }
+ d.logger.Debug("Deactivated logical volume", log.Ctx{"dev": volDevPath})
+ return true, nil
+ }
+
+ return false, nil
+}
From 1e59e3b34ef4156624ce3c8a8c343721db5154ba Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:17:06 +0100
Subject: [PATCH 02/13] lxd/storage/drivers/driver/lvm/utils: Set
--setactivationskip on in createLogicalVolume
So that volume devices are not automatically activated when the storage pool is started.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_utils.go | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/lxd/storage/drivers/driver_lvm_utils.go b/lxd/storage/drivers/driver_lvm_utils.go
index 1b5191eeb8..cbc68b2fe5 100644
--- a/lxd/storage/drivers/driver_lvm_utils.go
+++ b/lxd/storage/drivers/driver_lvm_utils.go
@@ -390,6 +390,20 @@ func (d *lvm) createLogicalVolume(vgName, thinPoolName string, vol Volume, makeT
}
}
+ isRecent, err := d.lvmVersionIsAtLeast(lvmVersion, "2.02.99")
+ if err != nil {
+ return errors.Wrapf(err, "Error checking LVM version")
+ }
+
+ if isRecent {
+ // Disable auto activation of volume on LVM versions that support it.
+ // Must be done after volume create so that zeroing and signature wiping can take place.
+ _, err := shared.RunCommand("lvchange", "--setactivationskip", "y", volDevPath)
+ if err != nil {
+ return errors.Wrapf(err, "Failed to set activation skip on LVM logical volume %q", volDevPath)
+ }
+ }
+
d.logger.Debug("Logical volume created", log.Ctx{"vg_name": vgName, "lv_name": lvFullName, "size": fmt.Sprintf("%db", lvSizeBytes), "fs": d.volumeFilesystem(vol)})
return nil
}
From f4292aa87e2e164c0f4ad089c4a673135187821b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:21:01 +0100
Subject: [PATCH 03/13] lxd/storage/drivers/driver/lvm/utils: Set
--setactivationskip on in createLogicalVolumeSnapshot
So that snapshot volumes are not automatically activated.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_utils.go | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/lxd/storage/drivers/driver_lvm_utils.go b/lxd/storage/drivers/driver_lvm_utils.go
index cbc68b2fe5..cb18f4bbcb 100644
--- a/lxd/storage/drivers/driver_lvm_utils.go
+++ b/lxd/storage/drivers/driver_lvm_utils.go
@@ -421,7 +421,7 @@ func (d *lvm) createLogicalVolumeSnapshot(vgName string, srcVol, snapVol Volume,
args := []string{"-n", snapLvName, "-s", srcVolDevPath}
if isRecent {
- args = append(args, "-kn")
+ args = append(args, "--setactivationskip", "y")
}
// If the source is not a thin volume the size needs to be specified.
@@ -457,15 +457,6 @@ func (d *lvm) createLogicalVolumeSnapshot(vgName string, srcVol, snapVol Volume,
})
targetVolDevPath := d.lvmDevPath(vgName, snapVol.volType, snapVol.contentType, snapVol.name)
- if makeThinLv {
- // Snapshots of thin logical volumes can be directly activated.
- // Normal snapshots will complain about changing the origin (Which they never do.),
- // so skip the activation since the logical volume will be automatically activated anyway.
- _, err := shared.TryRunCommand("lvchange", "-ay", targetVolDevPath)
- if err != nil {
- return "", err
- }
- }
revert.Success()
return targetVolDevPath, nil
From a84a4a4ec9ab9c5a9c30d8a922552bea06057f2e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:21:50 +0100
Subject: [PATCH 04/13] lxd/storage/drivers/driver/lvm/utils: Activate volume
in copyThinpoolVolume when regeneration FS UUID
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_utils.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lxd/storage/drivers/driver_lvm_utils.go b/lxd/storage/drivers/driver_lvm_utils.go
index cb18f4bbcb..9a6092ce45 100644
--- a/lxd/storage/drivers/driver_lvm_utils.go
+++ b/lxd/storage/drivers/driver_lvm_utils.go
@@ -639,6 +639,11 @@ func (d *lvm) copyThinpoolVolume(vol, srcVol Volume, srcSnapshots []Volume, refr
// volumes with the same UUID to be mounted at the same time). This should be done before volume
// resize as some filesystems will need to mount the filesystem to resize.
if renegerateFilesystemUUIDNeeded(d.volumeFilesystem(vol)) {
+ _, err = d.activateVolume(volDevPath)
+ if err != nil {
+ return err
+ }
+
d.logger.Debug("Regenerating filesystem UUID", log.Ctx{"dev": volDevPath, "fs": d.volumeFilesystem(vol)})
err = regenerateFilesystemUUID(d.volumeFilesystem(vol), volDevPath)
if err != nil {
From a79aed91a06a71db92d29839f3ef3a4f4711b628 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:22:37 +0100
Subject: [PATCH 05/13] lxd/storage/drivers/driver/lvm: Dont activate all
volumes on pool mount
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm.go | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/lxd/storage/drivers/driver_lvm.go b/lxd/storage/drivers/driver_lvm.go
index 1061c25e04..dbf3c6b5f4 100644
--- a/lxd/storage/drivers/driver_lvm.go
+++ b/lxd/storage/drivers/driver_lvm.go
@@ -501,12 +501,7 @@ func (d *lvm) Mount() (bool, error) {
return false, err
}
defer loopFile.Close()
- }
-
- // Activate volume group so that it's device is added to /dev.
- _, err := shared.TryRunCommand("vgchange", "-ay", d.config["lvm.vg_name"])
- if err != nil {
- return false, err
+ return true, nil
}
return false, nil
From b63bd23241c26d092371e9cba60b28b0687c7715 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:23:30 +0100
Subject: [PATCH 06/13] lxd/storage/drivers/driver/lvm/volumes: Activate volume
before generic copy in CreateVolumeFromCopy
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index a001ba1561..fffbda8320 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -137,6 +137,18 @@ func (d *lvm) CreateVolumeFromCopy(vol, srcVol Volume, copySnapshots bool, op *o
return nil
}
+ // Before doing a generic volume copy, we need to ensure volume (or snap volume parent) is activated to
+ // avoid failing with warnings about changing the origin of the snapshot when trying to activate it.
+ parent, _, _ := shared.InstanceGetParentAndSnapshotName(srcVol.Name())
+ volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], srcVol.volType, srcVol.contentType, parent)
+ activated, err := d.activateVolume(volDevPath)
+ if err != nil {
+ return err
+ }
+ if activated {
+ defer d.deactivateVolume(volDevPath)
+ }
+
// Otherwise run the generic copy.
return genericVFSCopyVolume(d, nil, vol, srcVol, srcSnapshots, false, op)
}
From 211f88993457b17c69b64d3983669b5c9090dc85 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:23:57 +0100
Subject: [PATCH 07/13] lxd/storage/drivers/driver/lvm/volumes: Activate volume
in SetVolumeQuota
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index fffbda8320..0ce1a37da2 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -366,6 +366,15 @@ func (d *lvm) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
logCtx := log.Ctx{"dev": volDevPath, "size": fmt.Sprintf("%db", sizeBytes)}
+ // Activate volume if needed.
+ activated, err := d.activateVolume(volDevPath)
+ if err != nil {
+ return err
+ }
+ if activated {
+ defer d.deactivateVolume(volDevPath)
+ }
+
// Resize filesystem if needed.
if vol.contentType == ContentTypeFS {
if sizeBytes < oldSizeBytes {
From f09f9bf6c64798bd3139d18e31fd69bf8f678351 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:26:05 +0100
Subject: [PATCH 08/13] lxd/storage/drivers/driver/lvm/volumes: Activate volume
in MountVolume
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index 0ce1a37da2..66399090fe 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -436,19 +436,26 @@ func (d *lvm) GetVolumeDiskPath(vol Volume) (string, error) {
return "", ErrNotSupported
}
-// MountVolume simulates mounting a volume. As dir driver doesn't have volumes to mount it returns
-// false indicating that there is no need to issue an unmount.
+// MountVolume mounts a volume. Returns true if this volume was our mount.
func (d *lvm) MountVolume(vol Volume, op *operations.Operation) (bool, error) {
- mountPath := vol.MountPath()
+ var err error
+ activated := false
+
+ // Activate LVM volume if needed.
+ volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], vol.volType, vol.contentType, vol.name)
+ activated, err = d.activateVolume(volDevPath)
+ if err != nil {
+ return false, err
+ }
// Check if already mounted.
+ mountPath := vol.MountPath()
if vol.contentType == ContentTypeFS && !shared.IsMountPoint(mountPath) {
- err := vol.EnsureMountPath()
+ err = vol.EnsureMountPath()
if err != nil {
return false, err
}
- volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], vol.volType, vol.contentType, vol.name)
mountFlags, mountOptions := resolveMountOptions(d.volumeMountOptions(vol))
err = TryMount(volDevPath, mountPath, d.volumeFilesystem(vol), mountFlags, mountOptions)
if err != nil {
@@ -465,7 +472,7 @@ func (d *lvm) MountVolume(vol Volume, op *operations.Operation) (bool, error) {
return d.MountVolume(fsVol, op)
}
- return false, nil
+ return activated, nil
}
// UnmountVolume simulates unmounting a volume. As dir driver doesn't have volumes to unmount it
From 57c982d60c3305240189206cc62a4586e039e8fc Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:27:19 +0100
Subject: [PATCH 09/13] lxd/storage/drivers/driver/lvm/volumes: Deactivate
volume in UnmountVolume
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 32 +++++++++++++++++++----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index 66399090fe..8449e9e1dd 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -475,23 +475,45 @@ func (d *lvm) MountVolume(vol Volume, op *operations.Operation) (bool, error) {
return activated, nil
}
-// UnmountVolume simulates unmounting a volume. As dir driver doesn't have volumes to unmount it
-// returns false indicating the volume was already unmounted.
+// UnmountVolume unmounts a volume. Returns true if we unmounted.
func (d *lvm) UnmountVolume(vol Volume, op *operations.Operation) (bool, error) {
+ var err error
+ volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], vol.volType, vol.contentType, vol.name)
mountPath := vol.MountPath()
// Check if already mounted.
- if shared.IsMountPoint(mountPath) {
- err := TryUnmount(mountPath, 0)
+ if vol.contentType == ContentTypeFS && shared.IsMountPoint(mountPath) {
+ err = TryUnmount(mountPath, 0)
if err != nil {
return false, errors.Wrapf(err, "Failed to unmount LVM logical volume")
}
d.logger.Debug("Unmounted logical volume", log.Ctx{"path": mountPath})
+ // We only deactivate filesystem volumes if an unmount was needed to better align with our
+ // unmount return value indicator.
+ _, err = d.deactivateVolume(volDevPath)
+ if err != nil {
+ return false, err
+ }
+
return true, nil
}
- return false, nil
+ deactivated := false
+ if vol.contentType == ContentTypeBlock {
+ deactivated, err = d.deactivateVolume(volDevPath)
+ if err != nil {
+ return false, err
+ }
+ }
+
+ // For VMs, unmount the filesystem volume.
+ if vol.IsVMBlock() {
+ fsVol := vol.NewVMBlockFilesystemVolume()
+ return d.UnmountVolume(fsVol, op)
+ }
+
+ return deactivated, nil
}
// RenameVolume renames a volume and its snapshots.
From 3472d062b2031e0bdef1173c7ab98a837180de1d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:27:47 +0100
Subject: [PATCH 10/13] lxd/storage/drivers/driver/lvm/volumes: Acticate volume
before generic migrate in MigrateVolume
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index 8449e9e1dd..570f6e666a 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -590,6 +590,18 @@ func (d *lvm) RenameVolume(vol Volume, newVolName string, op *operations.Operati
// MigrateVolume sends a volume for migration.
func (d *lvm) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs *migration.VolumeSourceArgs, op *operations.Operation) error {
+ // Before doing a generic volume migration, we need to ensure volume (or snap volume parent) is activated
+ // to avoid failing with warnings about changing the origin of the snapshot when trying to activate it.
+ parent, _, _ := shared.InstanceGetParentAndSnapshotName(vol.Name())
+ volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], vol.volType, vol.contentType, parent)
+ activated, err := d.activateVolume(volDevPath)
+ if err != nil {
+ return err
+ }
+ if activated {
+ defer d.deactivateVolume(volDevPath)
+ }
+
return genericVFSMigrateVolume(d, d.state, vol, conn, volSrcArgs, op)
}
From fd374e5bdbf7615c7b36ea3a58a3eb8b7fa8b508 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:28:41 +0100
Subject: [PATCH 11/13] lxd/storage/drivers/driver/lvm/volumes: Activate volume
in MountVolumeSnapshot
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 45 +++++++++++++++++------
1 file changed, 33 insertions(+), 12 deletions(-)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index 570f6e666a..ad44269a54 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -708,6 +708,7 @@ func (d *lvm) DeleteVolumeSnapshot(snapVol Volume, op *operations.Operation) err
// MountVolumeSnapshot sets up a read-only mount on top of the snapshot to avoid accidental modifications.
func (d *lvm) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (bool, error) {
+ var err error
mountPath := snapVol.MountPath()
// Check if already mounted.
@@ -715,7 +716,7 @@ func (d *lvm) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (boo
revert := revert.New()
defer revert.Fail()
- err := snapVol.EnsureMountPath()
+ err = snapVol.EnsureMountPath()
if err != nil {
return false, err
}
@@ -733,13 +734,14 @@ func (d *lvm) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (boo
// we do not want to modify a snapshot in case it is corrupted for some reason, so at mount time
// we take another snapshot of the snapshot, regenerate the temporary snapshot's UUID and then
// mount that.
- if renegerateFilesystemUUIDNeeded(d.volumeFilesystem(snapVol)) {
+ regenerateFSUUID := renegerateFilesystemUUIDNeeded(d.volumeFilesystem(snapVol))
+ if regenerateFSUUID {
// Instantiate a new volume to be the temporary writable snapshot.
tmpVolName := fmt.Sprintf("%s%s", snapVol.name, tmpVolSuffix)
tmpVol := NewVolume(d, d.name, snapVol.volType, snapVol.contentType, tmpVolName, snapVol.config, snapVol.poolConfig)
// Create writable snapshot from source snapshot named with a tmpVolSuffix suffix.
- _, err := d.createLogicalVolumeSnapshot(d.config["lvm.vg_name"], snapVol, tmpVol, false, d.usesThinpool())
+ _, err = d.createLogicalVolumeSnapshot(d.config["lvm.vg_name"], snapVol, tmpVol, false, d.usesThinpool())
if err != nil {
return false, errors.Wrapf(err, "Error creating temporary LVM logical volume snapshot")
}
@@ -748,8 +750,20 @@ func (d *lvm) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (boo
d.removeLogicalVolume(d.lvmDevPath(d.config["lvm.vg_name"], tmpVol.volType, tmpVol.contentType, tmpVol.name))
})
- tmpVolDevPath := d.lvmDevPath(d.config["lvm.vg_name"], tmpVol.volType, tmpVol.contentType, tmpVol.name)
- tmpVolFsType := d.volumeFilesystem(tmpVol)
+ // We are going to mount the temporary volume instead.
+ mountVol = tmpVol
+ }
+
+ volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], mountVol.volType, mountVol.contentType, mountVol.name)
+
+ // Activate volume if needed.
+ _, err = d.activateVolume(volDevPath)
+ if err != nil {
+ return false, err
+ }
+
+ if regenerateFSUUID {
+ tmpVolFsType := d.volumeFilesystem(mountVol)
// When mounting XFS filesystems temporarily we can use the nouuid option rather than fully
// regenerating the filesystem UUID.
@@ -759,19 +773,15 @@ func (d *lvm) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (boo
mountOptions += ",nouuid"
}
} else {
- d.logger.Debug("Regenerating filesystem UUID", log.Ctx{"dev": tmpVolDevPath, "fs": d.volumeFilesystem(tmpVol)})
- err = regenerateFilesystemUUID(d.volumeFilesystem(tmpVol), tmpVolDevPath)
+ d.logger.Debug("Regenerating filesystem UUID", log.Ctx{"dev": volDevPath, "fs": tmpVolFsType})
+ err = regenerateFilesystemUUID(d.volumeFilesystem(mountVol), volDevPath)
if err != nil {
return false, err
}
}
-
- // We are going to mount the temporary volume instead.
- mountVol = tmpVol
}
// Finally attempt to mount the volume that needs mounting.
- volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], mountVol.volType, mountVol.contentType, mountVol.name)
err = TryMount(volDevPath, mountPath, d.volumeFilesystem(mountVol), mountFlags|unix.MS_RDONLY, mountOptions)
if err != nil {
return false, errors.Wrapf(err, "Failed to mount LVM snapshot volume")
@@ -782,13 +792,24 @@ func (d *lvm) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (boo
return true, nil
}
+ activated := false
+ if snapVol.contentType == ContentTypeBlock {
+ volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], snapVol.volType, snapVol.contentType, snapVol.name)
+
+ // Activate volume if needed.
+ activated, err = d.activateVolume(volDevPath)
+ if err != nil {
+ return false, err
+ }
+ }
+
// For VMs, mount the filesystem volume.
if snapVol.IsVMBlock() {
fsVol := snapVol.NewVMBlockFilesystemVolume()
return d.MountVolumeSnapshot(fsVol, op)
}
- return false, nil
+ return activated, nil
}
// UnmountVolumeSnapshot removes the read-only mount placed on top of a snapshot.
From 9fd213561bdb32ced9746350c247b8265005e7d3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:30:02 +0100
Subject: [PATCH 12/13] lxd/storage/drivers/driver/lvm/volumes: Deactivate
volume in UnmountVolumeSnapshot
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index ad44269a54..a2dc7ff8e1 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -815,11 +815,13 @@ func (d *lvm) MountVolumeSnapshot(snapVol Volume, op *operations.Operation) (boo
// UnmountVolumeSnapshot removes the read-only mount placed on top of a snapshot.
// If a temporary snapshot volume exists then it will attempt to remove it.
func (d *lvm) UnmountVolumeSnapshot(snapVol Volume, op *operations.Operation) (bool, error) {
+ var err error
+ volDevPath := d.lvmDevPath(d.config["lvm.vg_name"], snapVol.volType, snapVol.contentType, snapVol.name)
mountPath := snapVol.MountPath()
// Check if already mounted.
if snapVol.contentType == ContentTypeFS && shared.IsMountPoint(mountPath) {
- err := TryUnmount(mountPath, 0)
+ err = TryUnmount(mountPath, 0)
if err != nil {
return false, errors.Wrapf(err, "Failed to unmount LVM snapshot volume")
}
@@ -840,16 +842,31 @@ func (d *lvm) UnmountVolumeSnapshot(snapVol Volume, op *operations.Operation) (b
}
}
+ // We only deactivate filesystem volumes if an unmount was needed to better align with our
+ // unmount return value indicator.
+ _, err = d.deactivateVolume(volDevPath)
+ if err != nil {
+ return false, err
+ }
+
return true, nil
}
+ deactivated := false
+ if snapVol.contentType == ContentTypeBlock {
+ deactivated, err = d.deactivateVolume(volDevPath)
+ if err != nil {
+ return false, err
+ }
+ }
+
// For VMs, unmount the filesystem volume.
if snapVol.IsVMBlock() {
fsVol := snapVol.NewVMBlockFilesystemVolume()
return d.UnmountVolumeSnapshot(fsVol, op)
}
- return false, nil
+ return deactivated, nil
}
// VolumeSnapshots returns a list of snapshots for the volume.
From 527048b8359a37d0cafa5c57cc65c7330e0d105d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 5 May 2020 14:30:25 +0100
Subject: [PATCH 13/13] lxd/storage/drivers/driver/lvm/volumes: Activate volume
before FS UUID regen in RestoreVolume
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_lvm_volumes.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lxd/storage/drivers/driver_lvm_volumes.go b/lxd/storage/drivers/driver_lvm_volumes.go
index a2dc7ff8e1..ed280d4f96 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -984,6 +984,11 @@ func (d *lvm) RestoreVolume(vol Volume, snapshotName string, op *operations.Oper
// If the volume's filesystem needs to have its UUID regenerated to allow mount then do so now.
if vol.contentType == ContentTypeFS && renegerateFilesystemUUIDNeeded(d.volumeFilesystem(vol)) {
+ _, err = d.activateVolume(volDevPath)
+ if err != nil {
+ return err
+ }
+
d.logger.Debug("Regenerating filesystem UUID", log.Ctx{"dev": volDevPath, "fs": d.volumeFilesystem(vol)})
err = regenerateFilesystemUUID(d.volumeFilesystem(vol), volDevPath)
if err != nil {
More information about the lxc-devel
mailing list