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

tomponline on Github lxc-bot at linuxcontainers.org
Wed Dec 18 15:08:10 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 851 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191218/5f8558d3/attachment-0001.bin>
-------------- next part --------------
From b452867a0e10ff165487f4de0325c10caedf876d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 14:51:45 +0000
Subject: [PATCH 01/10] lxd/storage/utils: Removes mount helper functions

These will be moved into storage/drivers pkg

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

diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go
index bcd370f3f0..22f24f7bae 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -5,9 +5,6 @@ import (
 	"os"
 	"path/filepath"
 	"strings"
-	"time"
-
-	"golang.org/x/sys/unix"
 
 	"github.com/lxc/lxd/lxd/db"
 	"github.com/lxc/lxd/lxd/instance"
@@ -26,83 +23,6 @@ import (
 // VolumeUsedByInstancesWithProfiles returns a slice containing the names of instances using a volume.
 var VolumeUsedByInstancesWithProfiles func(s *state.State, poolName string, volumeName string, volumeTypeName string, runningOnly bool) ([]string, error)
 
-// Export the mount options map since we might find it useful in other parts of
-// LXD.
-type mountOptions struct {
-	capture bool
-	flag    uintptr
-}
-
-// MountOptions represents a list of possible mount options.
-var MountOptions = map[string]mountOptions{
-	"async":         {false, unix.MS_SYNCHRONOUS},
-	"atime":         {false, unix.MS_NOATIME},
-	"bind":          {true, unix.MS_BIND},
-	"defaults":      {true, 0},
-	"dev":           {false, unix.MS_NODEV},
-	"diratime":      {false, unix.MS_NODIRATIME},
-	"dirsync":       {true, unix.MS_DIRSYNC},
-	"exec":          {false, unix.MS_NOEXEC},
-	"lazytime":      {true, unix.MS_LAZYTIME},
-	"mand":          {true, unix.MS_MANDLOCK},
-	"noatime":       {true, unix.MS_NOATIME},
-	"nodev":         {true, unix.MS_NODEV},
-	"nodiratime":    {true, unix.MS_NODIRATIME},
-	"noexec":        {true, unix.MS_NOEXEC},
-	"nomand":        {false, unix.MS_MANDLOCK},
-	"norelatime":    {false, unix.MS_RELATIME},
-	"nostrictatime": {false, unix.MS_STRICTATIME},
-	"nosuid":        {true, unix.MS_NOSUID},
-	"rbind":         {true, unix.MS_BIND | unix.MS_REC},
-	"relatime":      {true, unix.MS_RELATIME},
-	"remount":       {true, unix.MS_REMOUNT},
-	"ro":            {true, unix.MS_RDONLY},
-	"rw":            {false, unix.MS_RDONLY},
-	"strictatime":   {true, unix.MS_STRICTATIME},
-	"suid":          {false, unix.MS_NOSUID},
-	"sync":          {true, unix.MS_SYNCHRONOUS},
-}
-
-// TryMount tries mounting a filesystem multiple times. This is useful for unreliable backends.
-func TryMount(src string, dst string, fs string, flags uintptr, options string) error {
-	var err error
-
-	for i := 0; i < 20; i++ {
-		err = unix.Mount(src, dst, fs, flags, options)
-		if err == nil {
-			break
-		}
-
-		time.Sleep(500 * time.Millisecond)
-	}
-
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// TryUnmount tries unmounting a filesystem multiple times. This is useful for unreliable backends.
-func TryUnmount(path string, flags int) error {
-	var err error
-
-	for i := 0; i < 20; i++ {
-		err = unix.Unmount(path, flags)
-		if err == nil {
-			break
-		}
-
-		time.Sleep(500 * time.Millisecond)
-	}
-
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
 // ValidName validates the provided name, and returns an error if it's not a valid storage name.
 func ValidName(value string) error {
 	if strings.Contains(value, "/") {

From 54583a35b229b7b8e093daa10e56aeccce39cb1f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 14:53:12 +0000
Subject: [PATCH 02/10] lx/storage/utils: Adds legacy mount functions to main
 pkg

Allowing for new mount helper functions to not be exported in storage/drivers pkg.

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

diff --git a/lxd/storage_utils.go b/lxd/storage_utils.go
index 468a1982ff..5a37a6b9e1 100644
--- a/lxd/storage_utils.go
+++ b/lxd/storage_utils.go
@@ -2,9 +2,13 @@ package main
 
 import (
 	"fmt"
+	"strings"
+
+	"golang.org/x/sys/unix"
 
 	"github.com/lxc/lxd/lxd/instance"
 	driver "github.com/lxc/lxd/lxd/storage"
+	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/logger"
 )
 
@@ -48,3 +52,97 @@ func shrinkVolumeFilesystem(s storage, volumeType int, fsType string, devPath st
 	err := driver.ShrinkFileSystem(fsType, devPath, mntpoint, byteSize)
 	return cleanupFunc, err
 }
+
+// MkfsOptions represents options for filesystem creation.
+type mkfsOptions struct {
+	Label string
+}
+
+// MakeFSType creates the provided filesystem.
+func makeFSType(path string, fsType string, options *mkfsOptions) (string, error) {
+	var err error
+	var msg string
+
+	fsOptions := options
+	if fsOptions == nil {
+		fsOptions = &mkfsOptions{}
+	}
+
+	cmd := []string{fmt.Sprintf("mkfs.%s", fsType), path}
+	if fsOptions.Label != "" {
+		cmd = append(cmd, "-L", fsOptions.Label)
+	}
+
+	if fsType == "ext4" {
+		cmd = append(cmd, "-E", "nodiscard,lazy_itable_init=0,lazy_journal_init=0")
+	}
+
+	msg, err = shared.TryRunCommand(cmd[0], cmd[1:]...)
+	if err != nil {
+		return msg, err
+	}
+
+	return "", nil
+}
+
+// mountOption represents an individual mount option.
+type mountOption struct {
+	capture bool
+	flag    uintptr
+}
+
+// mountOptions represents a list of possible mount options.
+var mountOptions = map[string]mountOption{
+	"async":         {false, unix.MS_SYNCHRONOUS},
+	"atime":         {false, unix.MS_NOATIME},
+	"bind":          {true, unix.MS_BIND},
+	"defaults":      {true, 0},
+	"dev":           {false, unix.MS_NODEV},
+	"diratime":      {false, unix.MS_NODIRATIME},
+	"dirsync":       {true, unix.MS_DIRSYNC},
+	"exec":          {false, unix.MS_NOEXEC},
+	"lazytime":      {true, unix.MS_LAZYTIME},
+	"mand":          {true, unix.MS_MANDLOCK},
+	"noatime":       {true, unix.MS_NOATIME},
+	"nodev":         {true, unix.MS_NODEV},
+	"nodiratime":    {true, unix.MS_NODIRATIME},
+	"noexec":        {true, unix.MS_NOEXEC},
+	"nomand":        {false, unix.MS_MANDLOCK},
+	"norelatime":    {false, unix.MS_RELATIME},
+	"nostrictatime": {false, unix.MS_STRICTATIME},
+	"nosuid":        {true, unix.MS_NOSUID},
+	"rbind":         {true, unix.MS_BIND | unix.MS_REC},
+	"relatime":      {true, unix.MS_RELATIME},
+	"remount":       {true, unix.MS_REMOUNT},
+	"ro":            {true, unix.MS_RDONLY},
+	"rw":            {false, unix.MS_RDONLY},
+	"strictatime":   {true, unix.MS_STRICTATIME},
+	"suid":          {false, unix.MS_NOSUID},
+	"sync":          {true, unix.MS_SYNCHRONOUS},
+}
+
+// resolveMountOptions resolves the provided mount options.
+func resolveMountOptions(options string) (uintptr, string) {
+	mountFlags := uintptr(0)
+	tmp := strings.SplitN(options, ",", -1)
+	for i := 0; i < len(tmp); i++ {
+		opt := tmp[i]
+		do, ok := mountOptions[opt]
+		if !ok {
+			continue
+		}
+
+		if do.capture {
+			mountFlags |= do.flag
+		} else {
+			mountFlags &= ^do.flag
+		}
+
+		copy(tmp[i:], tmp[i+1:])
+		tmp[len(tmp)-1] = ""
+		tmp = tmp[:len(tmp)-1]
+		i--
+	}
+
+	return mountFlags, strings.Join(tmp, ",")
+}

From ff089066516e4cd587e97dbc85ab51412d196bb7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 14:54:17 +0000
Subject: [PATCH 03/10] lxd/storage/drivers/utils: Unexports mount helper funcs
 except TryMount/TryUnmount

TryMount/TryUnmount are used from patches.go and so must be exported even after legacy storage code is removed.

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

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index f4df80eac8..c95b7a6799 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -64,13 +64,13 @@ func mountReadOnly(srcPath string, dstPath string) (bool, error) {
 	}
 
 	// Create a mount entry.
-	err := tryMount(srcPath, dstPath, "none", unix.MS_BIND, "")
+	err := TryMount(srcPath, dstPath, "none", unix.MS_BIND, "")
 	if err != nil {
 		return false, err
 	}
 
 	// Make it read-only.
-	err = tryMount("", dstPath, "none", unix.MS_BIND|unix.MS_RDONLY|unix.MS_REMOUNT, "")
+	err = TryMount("", dstPath, "none", unix.MS_BIND|unix.MS_RDONLY|unix.MS_REMOUNT, "")
 	if err != nil {
 		forceUnmount(dstPath)
 		return false, err
@@ -121,7 +121,8 @@ func sameMount(srcPath string, dstPath string) bool {
 	return true
 }
 
-func tryMount(src string, dst string, fs string, flags uintptr, options string) error {
+// TryMount tries mounting a filesystem multiple times. This is useful for unreliable backends.
+func TryMount(src string, dst string, fs string, flags uintptr, options string) error {
 	var err error
 
 	// Attempt 20 mounts over 10s
@@ -141,6 +142,26 @@ func tryMount(src string, dst string, fs string, flags uintptr, options string)
 	return nil
 }
 
+// TryUnmount tries unmounting a filesystem multiple times. This is useful for unreliable backends.
+func TryUnmount(path string, flags int) error {
+	var err error
+
+	for i := 0; i < 20; i++ {
+		err = unix.Unmount(path, flags)
+		if err == nil {
+			break
+		}
+
+		time.Sleep(500 * time.Millisecond)
+	}
+
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
 // GetPoolMountPath returns the mountpoint of the given pool.
 // {LXD_DIR}/storage-pools/<pool>
 func GetPoolMountPath(poolName string) string {
@@ -224,19 +245,19 @@ func createSparseFile(filePath string, sizeBytes int64) error {
 	return nil
 }
 
-// MkfsOptions represents options for filesystem creation.
-type MkfsOptions struct {
+// mkfsOptions represents options for filesystem creation.
+type mkfsOptions struct {
 	Label string
 }
 
-// MakeFSType creates the provided filesystem.
-func MakeFSType(path string, fsType string, options *MkfsOptions) (string, error) {
+// makeFSType creates the provided filesystem.
+func makeFSType(path string, fsType string, options *mkfsOptions) (string, error) {
 	var err error
 	var msg string
 
 	fsOptions := options
 	if fsOptions == nil {
-		fsOptions = &MkfsOptions{}
+		fsOptions = &mkfsOptions{}
 	}
 
 	cmd := []string{fmt.Sprintf("mkfs.%s", fsType), path}
@@ -292,8 +313,8 @@ var mountOptions = map[string]mountOption{
 	"sync":          {true, unix.MS_SYNCHRONOUS},
 }
 
-// ResolveMountOptions resolves the provided mount options.
-func ResolveMountOptions(options string) (uintptr, string) {
+// resolveMountOptions resolves the provided mount options.
+func resolveMountOptions(options string) (uintptr, string) {
 	mountFlags := uintptr(0)
 	tmp := strings.SplitN(options, ",", -1)
 	for i := 0; i < len(tmp); i++ {

From 4992af08cea86c2068aaefd0dfe728d5ed136216 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 14:55:06 +0000
Subject: [PATCH 04/10] lxd/patches: Updates to use TryMount/TryUnmount from
 storage/drivers pkg

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

diff --git a/lxd/patches.go b/lxd/patches.go
index 3049b08896..276d1f87f7 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -20,6 +20,7 @@ import (
 	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/rsync"
 	driver "github.com/lxc/lxd/lxd/storage"
+	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/shared"
 	log "github.com/lxc/lxd/shared/log15"
 	"github.com/lxc/lxd/shared/logger"
@@ -1095,7 +1096,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 		// Unmount the logical volume.
 		oldContainerMntPoint := shared.VarPath("containers", ct)
 		if shared.IsMountPoint(oldContainerMntPoint) {
-			err := driver.TryUnmount(oldContainerMntPoint, unix.MNT_DETACH)
+			err := storageDrivers.TryUnmount(oldContainerMntPoint, unix.MNT_DETACH)
 			if err != nil {
 				logger.Errorf("Failed to unmount LVM logical volume \"%s\": %s", oldContainerMntPoint, err)
 				return err
@@ -1270,7 +1271,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 				if shared.PathExists(oldLvDevPath) {
 					// Unmount the logical volume.
 					if shared.IsMountPoint(oldSnapshotMntPoint) {
-						err := driver.TryUnmount(oldSnapshotMntPoint, unix.MNT_DETACH)
+						err := storageDrivers.TryUnmount(oldSnapshotMntPoint, unix.MNT_DETACH)
 						if err != nil {
 							logger.Errorf("Failed to unmount LVM logical volume \"%s\": %s", oldSnapshotMntPoint, err)
 							return err
@@ -1373,7 +1374,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 		}
 
 		if !shared.IsMountPoint(newContainerMntPoint) {
-			err := driver.TryMount(containerLvDevPath, newContainerMntPoint, lvFsType, 0, mountOptions)
+			err := storageDrivers.TryMount(containerLvDevPath, newContainerMntPoint, lvFsType, 0, mountOptions)
 			if err != nil {
 				logger.Errorf("Failed to mount LVM logical \"%s\" onto \"%s\" : %s", containerLvDevPath, newContainerMntPoint, err)
 				return err
@@ -1421,7 +1422,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 		// Unmount the logical volume.
 		oldImageMntPoint := shared.VarPath("images", img+".lv")
 		if shared.IsMountPoint(oldImageMntPoint) {
-			err := driver.TryUnmount(oldImageMntPoint, unix.MNT_DETACH)
+			err := storageDrivers.TryUnmount(oldImageMntPoint, unix.MNT_DETACH)
 			if err != nil {
 				return err
 			}
@@ -1621,7 +1622,7 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
 			_, err := shared.TryRunCommand("zfs", "unmount", "-f", ctDataset)
 			if err != nil {
 				logger.Warnf("Failed to unmount ZFS filesystem via zfs unmount, trying lazy umount (MNT_DETACH)...")
-				err := driver.TryUnmount(oldContainerMntPoint, unix.MNT_DETACH)
+				err := storageDrivers.TryUnmount(oldContainerMntPoint, unix.MNT_DETACH)
 				if err != nil {
 					failedUpgradeEntities = append(failedUpgradeEntities, fmt.Sprintf("containers/%s: Failed to umount zfs filesystem.", ct))
 					continue
@@ -1769,7 +1770,7 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
 			_, err := shared.TryRunCommand("zfs", "unmount", "-f", imageDataset)
 			if err != nil {
 				logger.Warnf("Failed to unmount ZFS filesystem via zfs unmount, trying lazy umount (MNT_DETACH)...")
-				err := driver.TryUnmount(oldImageMntPoint, unix.MNT_DETACH)
+				err := storageDrivers.TryUnmount(oldImageMntPoint, unix.MNT_DETACH)
 				if err != nil {
 					logger.Warnf("Failed to unmount ZFS filesystem: %s", err)
 				}

From 0fd48e853a06e9d24746dc52fc35aa08f5d7bc7a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 14:55:44 +0000
Subject: [PATCH 05/10] lxd/storage/drivers/driver/cephfs: TryMount usage

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

diff --git a/lxd/storage/drivers/driver_cephfs.go b/lxd/storage/drivers/driver_cephfs.go
index e6e89bd881..6af9b1ee3c 100644
--- a/lxd/storage/drivers/driver_cephfs.go
+++ b/lxd/storage/drivers/driver_cephfs.go
@@ -127,7 +127,7 @@ func (d *cephfs) Create() error {
 
 	// Mount the pool.
 	uri := fmt.Sprintf("%s:6789:/", strings.Join(monAddresses, ","))
-	err = tryMount(uri, mountPoint, "ceph", 0, fmt.Sprintf("name=%v,secret=%v,mds_namespace=%v", d.config["cephfs.user.name"], userSecret, fsName))
+	err = TryMount(uri, mountPoint, "ceph", 0, fmt.Sprintf("name=%v,secret=%v,mds_namespace=%v", d.config["cephfs.user.name"], userSecret, fsName))
 	if err != nil {
 		return err
 	}
@@ -184,7 +184,7 @@ func (d *cephfs) Delete(op *operations.Operation) error {
 
 	// Mount the pool.
 	uri := fmt.Sprintf("%s:6789:/", strings.Join(monAddresses, ","))
-	err = tryMount(uri, mountPoint, "ceph", 0, fmt.Sprintf("name=%v,secret=%v,mds_namespace=%v", d.config["cephfs.user.name"], userSecret, fsName))
+	err = TryMount(uri, mountPoint, "ceph", 0, fmt.Sprintf("name=%v,secret=%v,mds_namespace=%v", d.config["cephfs.user.name"], userSecret, fsName))
 	if err != nil {
 		return err
 	}
@@ -249,7 +249,7 @@ func (d *cephfs) Mount() (bool, error) {
 
 	// Mount the pool.
 	uri := fmt.Sprintf("%s:6789:/%s", strings.Join(monAddresses, ","), fsPath)
-	err = tryMount(uri, GetPoolMountPath(d.name), "ceph", 0, fmt.Sprintf("name=%v,secret=%v,mds_namespace=%v", d.config["cephfs.user.name"], userSecret, fsName))
+	err = TryMount(uri, GetPoolMountPath(d.name), "ceph", 0, fmt.Sprintf("name=%v,secret=%v,mds_namespace=%v", d.config["cephfs.user.name"], userSecret, fsName))
 	if err != nil {
 		return false, err
 	}

From 2650b3954fab68995d78aef8aeb6c0df4e5013f7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 14:56:05 +0000
Subject: [PATCH 06/10] lxd/storage/drivers/driver/dir: TryMount usage

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

diff --git a/lxd/storage/drivers/driver_dir.go b/lxd/storage/drivers/driver_dir.go
index ee4c69e523..3e0d6f56a1 100644
--- a/lxd/storage/drivers/driver_dir.go
+++ b/lxd/storage/drivers/driver_dir.go
@@ -104,7 +104,7 @@ func (d *dir) Mount() (bool, error) {
 	}
 
 	// Setup the bind-mount.
-	err := tryMount(d.config["source"], path, "none", unix.MS_BIND, "")
+	err := TryMount(d.config["source"], path, "none", unix.MS_BIND, "")
 	if err != nil {
 		return false, err
 	}

From 6a68a3697382286984086ccc387fee0030f669a4 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 14:56:42 +0000
Subject: [PATCH 07/10] lxd/storage/btrfs: Updates to use unexported legacy
 mount functions

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

diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index 57b6584574..86f9c09b3d 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -163,7 +163,7 @@ func (s *storageBtrfs) StoragePoolCreate() error {
 			return fmt.Errorf("Failed to create sparse file %s: %s", source, err)
 		}
 
-		output, err := drivers.MakeFSType(source, "btrfs", &drivers.MkfsOptions{Label: s.pool.Name})
+		output, err := makeFSType(source, "btrfs", &mkfsOptions{Label: s.pool.Name})
 		if err != nil {
 			return fmt.Errorf("Failed to create the BTRFS pool: %v (%s)", err, output)
 		}
@@ -174,7 +174,7 @@ func (s *storageBtrfs) StoragePoolCreate() error {
 		if filepath.IsAbs(source) {
 			isBlockDev = shared.IsBlockdevPath(source)
 			if isBlockDev {
-				output, err := drivers.MakeFSType(source, "btrfs", &drivers.MkfsOptions{Label: s.pool.Name})
+				output, err := makeFSType(source, "btrfs", &mkfsOptions{Label: s.pool.Name})
 				if err != nil {
 					return fmt.Errorf("Failed to create the BTRFS pool: %v (%s)", err, output)
 				}
@@ -222,7 +222,7 @@ func (s *storageBtrfs) StoragePoolCreate() error {
 
 	var err1 error
 	var devUUID string
-	mountFlags, mountOptions := drivers.ResolveMountOptions(s.getBtrfsMountOptions())
+	mountFlags, mountOptions := resolveMountOptions(s.getBtrfsMountOptions())
 	mountFlags |= s.remount
 	if isBlockDev && filepath.IsAbs(source) {
 		devUUID, _ = shared.LookupUUIDByBlockDevPath(source)
@@ -415,7 +415,7 @@ func (s *storageBtrfs) StoragePoolMount() (bool, error) {
 		return false, nil
 	}
 
-	mountFlags, mountOptions := drivers.ResolveMountOptions(s.getBtrfsMountOptions())
+	mountFlags, mountOptions := resolveMountOptions(s.getBtrfsMountOptions())
 	mountSource := source
 	isBlockDev := shared.IsBlockdevPath(source)
 	if filepath.IsAbs(source) {

From 0dcf90364f25ba2120f967e9d0499f9b8e7fd607 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 14:57:19 +0000
Subject: [PATCH 08/10] lxd/storage/ceph: Updates to use legacy unexported
 mount functions, except TryMount/TryUnmount

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage_ceph.go       | 26 +++++++++++++-------------
 lxd/storage_ceph_utils.go | 14 +++++++-------
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/lxd/storage_ceph.go b/lxd/storage_ceph.go
index 1b5729e8e7..bddb5dd6bf 100644
--- a/lxd/storage_ceph.go
+++ b/lxd/storage_ceph.go
@@ -373,7 +373,7 @@ func (s *storageCeph) StoragePoolVolumeCreate() error {
 	RBDFilesystem := s.getRBDFilesystem()
 	logger.Debugf(`Retrieved filesystem type "%s" of RBD storage volume "%s" on storage pool "%s"`, RBDFilesystem, s.volume.Name, s.pool.Name)
 
-	output, err := storageDrivers.MakeFSType(RBDDevPath, RBDFilesystem, nil)
+	output, err := makeFSType(RBDDevPath, RBDFilesystem, nil)
 	if err != nil {
 		logger.Errorf(`Failed to create filesystem type "%s" on device path "%s" for RBD storage volume "%s" on storage pool "%s": %v (%s)`, RBDFilesystem, RBDDevPath, s.volume.Name, s.pool.Name, err, output)
 		return err
@@ -439,7 +439,7 @@ func (s *storageCeph) StoragePoolVolumeDelete() error {
 
 	volumeMntPoint := driver.GetStoragePoolVolumeMountPoint(s.pool.Name, s.volume.Name)
 	if shared.IsMountPoint(volumeMntPoint) {
-		err := driver.TryUnmount(volumeMntPoint, unix.MNT_DETACH)
+		err := storageDrivers.TryUnmount(volumeMntPoint, unix.MNT_DETACH)
 		if err != nil {
 			logger.Errorf(`Failed to unmount RBD storage volume "%s" on storage pool "%s": %s`, s.volume.Name, s.pool.Name, err)
 		}
@@ -523,8 +523,8 @@ func (s *storageCeph) StoragePoolVolumeMount() (bool, error) {
 		RBDDevPath, ret = getRBDMappedDevPath(s.ClusterName, s.OSDPoolName,
 			storagePoolVolumeTypeNameCustom, s.volume.Name, true,
 			s.UserName)
-		mountFlags, mountOptions := storageDrivers.ResolveMountOptions(s.getRBDMountOptions())
-		customerr = driver.TryMount(
+		mountFlags, mountOptions := resolveMountOptions(s.getRBDMountOptions())
+		customerr = storageDrivers.TryMount(
 			RBDDevPath,
 			volumeMntPoint,
 			RBDFilesystem,
@@ -575,7 +575,7 @@ func (s *storageCeph) StoragePoolVolumeUmount() (bool, error) {
 	var customerr error
 	ourUmount := false
 	if shared.IsMountPoint(volumeMntPoint) {
-		customerr = driver.TryUnmount(volumeMntPoint, unix.MNT_DETACH)
+		customerr = storageDrivers.TryUnmount(volumeMntPoint, unix.MNT_DETACH)
 		ourUmount = true
 	}
 
@@ -1396,7 +1396,7 @@ func (s *storageCeph) ContainerUmount(c instance.Instance, path string) (bool, e
 	var mounterr error
 	ourUmount := false
 	if shared.IsMountPoint(containerMntPoint) {
-		mounterr = driver.TryUnmount(containerMntPoint, 0)
+		mounterr = storageDrivers.TryUnmount(containerMntPoint, 0)
 		ourUmount = true
 	}
 
@@ -1834,7 +1834,7 @@ func (s *storageCeph) ContainerSnapshotStart(c instance.Instance) (bool, error)
 
 	containerMntPoint := driver.GetSnapshotMountPoint(c.Project(), s.pool.Name, containerName)
 	RBDFilesystem := s.getRBDFilesystem()
-	mountFlags, mountOptions := storageDrivers.ResolveMountOptions(s.getRBDMountOptions())
+	mountFlags, mountOptions := resolveMountOptions(s.getRBDMountOptions())
 	if RBDFilesystem == "xfs" {
 		idx := strings.Index(mountOptions, "nouuid")
 		if idx < 0 {
@@ -1842,7 +1842,7 @@ func (s *storageCeph) ContainerSnapshotStart(c instance.Instance) (bool, error)
 		}
 	}
 
-	err = driver.TryMount(
+	err = storageDrivers.TryMount(
 		RBDDevPath,
 		containerMntPoint,
 		RBDFilesystem,
@@ -1875,7 +1875,7 @@ func (s *storageCeph) ContainerSnapshotStop(c instance.Instance) (bool, error) {
 	}
 
 	// Unmount
-	err := driver.TryUnmount(containerMntPoint, unix.MNT_DETACH)
+	err := storageDrivers.TryUnmount(containerMntPoint, unix.MNT_DETACH)
 	if err != nil {
 		logger.Errorf("Failed to unmount %s: %s", containerMntPoint, err)
 		return false, err
@@ -2106,7 +2106,7 @@ func (s *storageCeph) ImageCreate(fingerprint string, tracker *ioprogress.Progre
 
 		// get filesystem
 		RBDFilesystem := s.getRBDFilesystem()
-		output, err := storageDrivers.MakeFSType(RBDDevPath, RBDFilesystem, nil)
+		output, err := makeFSType(RBDDevPath, RBDFilesystem, nil)
 		if err != nil {
 			logger.Errorf(`Failed to create filesystem "%s" for RBD storage volume for image "%s" on storage pool "%s": %v (%s)`, RBDFilesystem, fingerprint, s.pool.Name, err, output)
 			return err
@@ -2341,7 +2341,7 @@ func (s *storageCeph) ImageMount(fingerprint string) (bool, error) {
 
 	RBDFilesystem := s.getRBDFilesystem()
 	RBDMountOptions := s.getRBDMountOptions()
-	mountFlags, mountOptions := storageDrivers.ResolveMountOptions(RBDMountOptions)
+	mountFlags, mountOptions := resolveMountOptions(RBDMountOptions)
 	RBDDevPath, ret := getRBDMappedDevPath(s.ClusterName, s.OSDPoolName,
 		storagePoolVolumeTypeNameImage, fingerprint, true, s.UserName)
 	errMsg := fmt.Sprintf("Failed to mount RBD device %s onto %s",
@@ -2351,7 +2351,7 @@ func (s *storageCeph) ImageMount(fingerprint string) (bool, error) {
 		return false, fmt.Errorf(errMsg)
 	}
 
-	err := driver.TryMount(RBDDevPath, imageMntPoint, RBDFilesystem, mountFlags, mountOptions)
+	err := storageDrivers.TryMount(RBDDevPath, imageMntPoint, RBDFilesystem, mountFlags, mountOptions)
 	if err != nil || ret < 0 {
 		return false, err
 	}
@@ -2368,7 +2368,7 @@ func (s *storageCeph) ImageUmount(fingerprint string) (bool, error) {
 		return false, nil
 	}
 
-	err := driver.TryUnmount(imageMntPoint, 0)
+	err := storageDrivers.TryUnmount(imageMntPoint, 0)
 	if err != nil {
 		return false, err
 	}
diff --git a/lxd/storage_ceph_utils.go b/lxd/storage_ceph_utils.go
index 0a2abbdd98..bf0fc14fad 100644
--- a/lxd/storage_ceph_utils.go
+++ b/lxd/storage_ceph_utils.go
@@ -20,7 +20,7 @@ import (
 	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/rsync"
 	driver "github.com/lxc/lxd/lxd/storage"
-	"github.com/lxc/lxd/lxd/storage/drivers"
+	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
 	"github.com/lxc/lxd/shared/logger"
@@ -1685,14 +1685,14 @@ func (s *storageCeph) cephRBDVolumeBackupCreate(tmpPath string, backup backup.Ba
 	}
 
 	// Mount the volume
-	mountFlags, mountOptions := drivers.ResolveMountOptions(s.getRBDMountOptions())
-	err = driver.TryMount(RBDDevPath, tmpContainerMntPoint, RBDFilesystem, mountFlags, mountOptions)
+	mountFlags, mountOptions := resolveMountOptions(s.getRBDMountOptions())
+	err = storageDrivers.TryMount(RBDDevPath, tmpContainerMntPoint, RBDFilesystem, mountFlags, mountOptions)
 	if err != nil {
 		logger.Errorf("Failed to mount RBD device %s onto %s: %s", RBDDevPath, tmpContainerMntPoint, err)
 		return err
 	}
 	logger.Debugf("Mounted RBD device %s onto %s", RBDDevPath, tmpContainerMntPoint)
-	defer driver.TryUnmount(tmpContainerMntPoint, unix.MNT_DETACH)
+	defer storageDrivers.TryUnmount(tmpContainerMntPoint, unix.MNT_DETACH)
 
 	// Figure out the target name
 	targetName := sourceContainerName
@@ -1772,7 +1772,7 @@ func (s *storageCeph) doContainerCreate(projectName, name string, privileged boo
 
 	// get filesystem
 	RBDFilesystem := s.getRBDFilesystem()
-	output, err := drivers.MakeFSType(RBDDevPath, RBDFilesystem, nil)
+	output, err := makeFSType(RBDDevPath, RBDFilesystem, nil)
 	if err != nil {
 		logger.Errorf(`Failed to create filesystem type "%s" on device path "%s" for RBD storage volume for container "%s" on storage pool "%s": %v (%s)`, RBDFilesystem, RBDDevPath, name, s.pool.Name, err, output)
 		return err
@@ -1839,8 +1839,8 @@ func (s *storageCeph) doContainerMount(projectName string, name string) (bool, e
 			s.OSDPoolName, storagePoolVolumeTypeNameContainer,
 			volumeName, true, s.UserName)
 		if ret >= 0 {
-			mountFlags, mountOptions := drivers.ResolveMountOptions(s.getRBDMountOptions())
-			mounterr = driver.TryMount(RBDDevPath, containerMntPoint,
+			mountFlags, mountOptions := resolveMountOptions(s.getRBDMountOptions())
+			mounterr = storageDrivers.TryMount(RBDDevPath, containerMntPoint,
 				RBDFilesystem, mountFlags, mountOptions)
 			ourMount = true
 		}

From 0f2bf9dc1279d6ba682125a630079a50242e0d1e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 15:00:57 +0000
Subject: [PATCH 09/10] lxd/storage/lvm: Updates to use legacy unexported mount
 functions, except TryMount/TryUnmount

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage_lvm.go       | 36 ++++++++++++++++++------------------
 lxd/storage_lvm_utils.go |  3 +--
 2 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index e4cab25c5e..e82675685e 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -20,7 +20,7 @@ import (
 	"github.com/lxc/lxd/lxd/project"
 	"github.com/lxc/lxd/lxd/rsync"
 	driver "github.com/lxc/lxd/lxd/storage"
-	"github.com/lxc/lxd/lxd/storage/drivers"
+	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
 	"github.com/lxc/lxd/shared/ioprogress"
@@ -398,7 +398,7 @@ func (s *storageLvm) StoragePoolDelete() error {
 	if s.loopInfo != nil {
 		// Set LO_FLAGS_AUTOCLEAR before we remove the loop file
 		// otherwise we will get EBADF.
-		err = drivers.SetAutoclearOnLoopDev(int(s.loopInfo.Fd()))
+		err = storageDrivers.SetAutoclearOnLoopDev(int(s.loopInfo.Fd()))
 		if err != nil {
 			logger.Warnf("Failed to set LO_FLAGS_AUTOCLEAR on loop device: %s, manual cleanup needed", err)
 		}
@@ -470,12 +470,12 @@ func (s *storageLvm) StoragePoolMount() (bool, error) {
 
 	if filepath.IsAbs(source) && !shared.IsBlockdevPath(source) {
 		// Try to prepare new loop device.
-		loopF, loopErr := drivers.PrepareLoopDev(source, 0)
+		loopF, loopErr := storageDrivers.PrepareLoopDev(source, 0)
 		if loopErr != nil {
 			return false, loopErr
 		}
 		// Make sure that LO_FLAGS_AUTOCLEAR is unset.
-		loopErr = drivers.UnsetAutoclearOnLoopDev(int(loopF.Fd()))
+		loopErr = storageDrivers.UnsetAutoclearOnLoopDev(int(loopF.Fd()))
 		if loopErr != nil {
 			return false, loopErr
 		}
@@ -629,8 +629,8 @@ func (s *storageLvm) StoragePoolVolumeMount() (bool, error) {
 	var customerr error
 	ourMount := false
 	if !shared.IsMountPoint(customPoolVolumeMntPoint) {
-		mountFlags, mountOptions := drivers.ResolveMountOptions(s.getLvmMountOptions())
-		customerr = driver.TryMount(lvmVolumePath, customPoolVolumeMntPoint, lvFsType, mountFlags, mountOptions)
+		mountFlags, mountOptions := resolveMountOptions(s.getLvmMountOptions())
+		customerr = storageDrivers.TryMount(lvmVolumePath, customPoolVolumeMntPoint, lvFsType, mountFlags, mountOptions)
 		ourMount = true
 	}
 
@@ -672,7 +672,7 @@ func (s *storageLvm) StoragePoolVolumeUmount() (bool, error) {
 	var customerr error
 	ourUmount := false
 	if shared.IsMountPoint(customPoolVolumeMntPoint) {
-		customerr = driver.TryUnmount(customPoolVolumeMntPoint, 0)
+		customerr = storageDrivers.TryUnmount(customPoolVolumeMntPoint, 0)
 		ourUmount = true
 	}
 
@@ -1079,7 +1079,7 @@ func lvmContainerDeleteInternal(projectName, poolName string, ctName string, isS
 	}
 
 	if shared.IsMountPoint(containerMntPoint) {
-		err := driver.TryUnmount(containerMntPoint, 0)
+		err := storageDrivers.TryUnmount(containerMntPoint, 0)
 		if err != nil {
 			return fmt.Errorf(`Failed to unmount container path `+
 				`"%s": %s`, containerMntPoint, err)
@@ -1271,7 +1271,7 @@ func (s *storageLvm) doContainerMount(project, name string, snap bool) (bool, er
 	var mounterr error
 	ourMount := false
 	if !shared.IsMountPoint(containerMntPoint) {
-		mountFlags, mountOptions := drivers.ResolveMountOptions(s.getLvmMountOptions())
+		mountFlags, mountOptions := resolveMountOptions(s.getLvmMountOptions())
 		if snap && lvFsType == "xfs" {
 			idx := strings.Index(mountOptions, "nouuid")
 			if idx < 0 {
@@ -1279,7 +1279,7 @@ func (s *storageLvm) doContainerMount(project, name string, snap bool) (bool, er
 			}
 		}
 
-		mounterr = driver.TryMount(containerLvmPath, containerMntPoint, lvFsType, mountFlags, mountOptions)
+		mounterr = storageDrivers.TryMount(containerLvmPath, containerMntPoint, lvFsType, mountFlags, mountOptions)
 		ourMount = true
 	}
 
@@ -1327,7 +1327,7 @@ func (s *storageLvm) umount(project, name string, path string) (bool, error) {
 	var imgerr error
 	ourUmount := false
 	if shared.IsMountPoint(containerMntPoint) {
-		imgerr = driver.TryUnmount(containerMntPoint, 0)
+		imgerr = storageDrivers.TryUnmount(containerMntPoint, 0)
 		ourUmount = true
 	}
 
@@ -1602,7 +1602,7 @@ func (s *storageLvm) ContainerSnapshotStart(container instance.Instance) (bool,
 	containerMntPoint := driver.GetSnapshotMountPoint(container.Project(), s.pool.Name, containerName)
 	if !shared.IsMountPoint(containerMntPoint) {
 		mntOptString := s.getLvmMountOptions()
-		mountFlags, mountOptions := drivers.ResolveMountOptions(mntOptString)
+		mountFlags, mountOptions := resolveMountOptions(mntOptString)
 
 		if lvFsType == "xfs" {
 			idx := strings.Index(mountOptions, "nouuid")
@@ -1611,7 +1611,7 @@ func (s *storageLvm) ContainerSnapshotStart(container instance.Instance) (bool,
 			}
 		}
 
-		err = driver.TryMount(containerLvmPath, containerMntPoint, lvFsType, mountFlags, mountOptions)
+		err = storageDrivers.TryMount(containerLvmPath, containerMntPoint, lvFsType, mountFlags, mountOptions)
 		if err != nil {
 			logger.Errorf(`Failed to mount LVM snapshot "%s" with filesystem "%s" options "%s" onto "%s": %s`, s.volume.Name, lvFsType, mntOptString, containerMntPoint, err)
 			return false, err
@@ -1636,7 +1636,7 @@ func (s *storageLvm) ContainerSnapshotStop(container instance.Instance) (bool, e
 	poolName := s.getOnDiskPoolName()
 
 	if shared.IsMountPoint(snapshotMntPoint) {
-		err := driver.TryUnmount(snapshotMntPoint, 0)
+		err := storageDrivers.TryUnmount(snapshotMntPoint, 0)
 		if err != nil {
 			return false, err
 		}
@@ -2023,8 +2023,8 @@ func (s *storageLvm) ImageMount(fingerprint string) (bool, error) {
 
 	poolName := s.getOnDiskPoolName()
 	lvmVolumePath := getLvmDevPath("default", poolName, storagePoolVolumeAPIEndpointImages, fingerprint)
-	mountFlags, mountOptions := drivers.ResolveMountOptions(s.getLvmMountOptions())
-	err := driver.TryMount(lvmVolumePath, imageMntPoint, lvmFstype, mountFlags, mountOptions)
+	mountFlags, mountOptions := resolveMountOptions(s.getLvmMountOptions())
+	err := storageDrivers.TryMount(lvmVolumePath, imageMntPoint, lvmFstype, mountFlags, mountOptions)
 	if err != nil {
 		logger.Errorf(fmt.Sprintf("Error mounting image LV for unpacking: %s", err))
 		return false, fmt.Errorf("Error mounting image LV: %v", err)
@@ -2042,7 +2042,7 @@ func (s *storageLvm) ImageUmount(fingerprint string) (bool, error) {
 		return false, nil
 	}
 
-	err := driver.TryUnmount(imageMntPoint, 0)
+	err := storageDrivers.TryUnmount(imageMntPoint, 0)
 	if err != nil {
 		return false, err
 	}
@@ -2299,7 +2299,7 @@ func (s *storageLvm) StoragePoolVolumeSnapshotDelete() error {
 	snapshotLVName := containerNameToLVName(s.volume.Name)
 	storageVolumeSnapshotPath := driver.GetStoragePoolVolumeSnapshotMountPoint(s.pool.Name, s.volume.Name)
 	if shared.IsMountPoint(storageVolumeSnapshotPath) {
-		err := driver.TryUnmount(storageVolumeSnapshotPath, 0)
+		err := storageDrivers.TryUnmount(storageVolumeSnapshotPath, 0)
 		if err != nil {
 			return fmt.Errorf("Failed to unmount snapshot path \"%s\": %s", storageVolumeSnapshotPath, err)
 		}
diff --git a/lxd/storage_lvm_utils.go b/lxd/storage_lvm_utils.go
index ae3085f8e6..5448118d3b 100644
--- a/lxd/storage_lvm_utils.go
+++ b/lxd/storage_lvm_utils.go
@@ -17,7 +17,6 @@ import (
 	"github.com/lxc/lxd/lxd/rsync"
 	"github.com/lxc/lxd/lxd/state"
 	driver "github.com/lxc/lxd/lxd/storage"
-	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
 	"github.com/lxc/lxd/shared/logger"
@@ -857,7 +856,7 @@ func lvmCreateLv(projectName, vgName string, thinPoolName string, lvName string,
 
 	fsPath := getLvmDevPath(projectName, vgName, volumeType, lvName)
 
-	output, err = storageDrivers.MakeFSType(fsPath, lvFsType, nil)
+	output, err = makeFSType(fsPath, lvFsType, nil)
 	if err != nil {
 		logger.Errorf("Filesystem creation failed: %v (%s)", err, output)
 		return fmt.Errorf("Error making filesystem on image LV: %v (%s)", err, output)

From 53e04d2c10c4676e2634b6755b691030032cf7f0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 18 Dec 2019 15:01:27 +0000
Subject: [PATCH 10/10] lxd/storage/zfs/utils: Consistent import name for
 storage/drivers pkg

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

diff --git a/lxd/storage_zfs_utils.go b/lxd/storage_zfs_utils.go
index 7574ecdb2f..7cefa01bab 100644
--- a/lxd/storage_zfs_utils.go
+++ b/lxd/storage_zfs_utils.go
@@ -15,6 +15,7 @@ import (
 
 	"github.com/lxc/lxd/lxd/project"
 	driver "github.com/lxc/lxd/lxd/storage"
+	storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/logger"
 )
@@ -522,7 +523,7 @@ func zfsUmount(poolName string, path string, mountpoint string) error {
 		fmt.Sprintf("%s/%s", poolName, path))
 	if err != nil {
 		logger.Warnf("Failed to unmount ZFS filesystem via zfs unmount: %s. Trying lazy umount (MNT_DETACH)...", output)
-		err := driver.TryUnmount(mountpoint, unix.MNT_DETACH)
+		err := storageDrivers.TryUnmount(mountpoint, unix.MNT_DETACH)
 		if err != nil {
 			logger.Warnf("Failed to unmount ZFS filesystem via lazy umount (MNT_DETACH)...")
 			return err
@@ -685,7 +686,7 @@ func (s *storageZfs) doContainerMount(projectName, name string, privileged bool)
 	if !shared.IsMountPoint(containerPoolVolumeMntPoint) {
 		source := fmt.Sprintf("%s/%s", s.getOnDiskPoolName(), fs)
 		zfsMountOptions := fmt.Sprintf("rw,zfsutil,mntpoint=%s", containerPoolVolumeMntPoint)
-		mounterr := driver.TryMount(source, containerPoolVolumeMntPoint, "zfs", 0, zfsMountOptions)
+		mounterr := storageDrivers.TryMount(source, containerPoolVolumeMntPoint, "zfs", 0, zfsMountOptions)
 		if mounterr != nil {
 			if mounterr != unix.EBUSY {
 				logger.Errorf("Failed to mount ZFS dataset \"%s\" onto \"%s\": %v", source, containerPoolVolumeMntPoint, mounterr)


More information about the lxc-devel mailing list