[lxc-devel] [lxd/master] Storage performance improvements

stgraber on Github lxc-bot at linuxcontainers.org
Sun Apr 3 21:24:45 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160403/3ebc7953/attachment.bin>
-------------- next part --------------
From cd6663f2a1cd55448ec6f76b582df21235291c3e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sun, 3 Apr 2016 17:14:51 -0400
Subject: [PATCH 1/2] zfs: Dynamically mount/umount filesystems
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/storage_zfs.go | 80 ++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 63 insertions(+), 17 deletions(-)

diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 438d2a7..eb3d4af 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -84,10 +84,24 @@ func (s *storageZfs) Init(config map[string]interface{}) (storage, error) {
 
 // Things we don't need to care about
 func (s *storageZfs) ContainerStart(container container) error {
+	fs := fmt.Sprintf("containers/%s", container.Name())
+
+	err := s.zfsMount(fs)
+	if err != nil && !s.zfsMounted(fs) {
+		return err
+	}
+
 	return nil
 }
 
 func (s *storageZfs) ContainerStop(container container) error {
+	fs := fmt.Sprintf("containers/%s", container.Name())
+
+	err := s.zfsUnmount(fs)
+	if err != nil {
+		return err
+	}
+
 	return nil
 }
 
@@ -101,6 +115,12 @@ func (s *storageZfs) ContainerCreate(container container) error {
 		return err
 	}
 
+	err = s.zfsMount(fs)
+	if err != nil && !s.zfsMounted(fs) {
+		return err
+	}
+	defer s.zfsUnmount(fs)
+
 	err = os.Symlink(cPath+".zfs", cPath)
 	if err != nil {
 		return err
@@ -140,6 +160,12 @@ func (s *storageZfs) ContainerCreateFromImage(container container, fingerprint s
 		return err
 	}
 
+	err = s.zfsMount(fs)
+	if err != nil && !s.zfsMounted(fs) {
+		return err
+	}
+	defer s.zfsUnmount(fs)
+
 	err = os.Symlink(cPath+".zfs", cPath)
 	if err != nil {
 		return err
@@ -288,6 +314,12 @@ func (s *storageZfs) ContainerCopy(container container, sourceContainer containe
 			return err
 		}
 
+		err = s.zfsMount(destFs)
+		if err != nil && !s.zfsMounted(destFs) {
+			return nil
+		}
+		defer s.zfsUnmount(destFs)
+
 		cPath := container.Path()
 		err = os.Symlink(cPath+".zfs", cPath)
 		if err != nil {
@@ -311,6 +343,12 @@ func (s *storageZfs) ContainerCopy(container container, sourceContainer containe
 			return err
 		}
 
+		err = s.zfsMount(destFs)
+		if err != nil && !s.zfsMounted(destFs) {
+			return nil
+		}
+		defer s.zfsUnmount(destFs)
+
 		output, err := storageRsyncCopy(sourceContainer.Path(), container.Path())
 		if err != nil {
 			return fmt.Errorf("rsync failed: %s", string(output))
@@ -358,20 +396,6 @@ func (s *storageZfs) ContainerRename(container container, newName string) error
 		return err
 	}
 
-	// In case ZFS didn't mount the filesystem, do it ourselves
-	if !shared.PathExists(shared.VarPath(fmt.Sprintf("containers/%s.zfs", newName))) {
-		for i := 0; i < 20; i++ {
-			err = s.zfsMount(fmt.Sprintf("containers/%s", newName))
-			if err == nil {
-				break
-			}
-			time.Sleep(500 * time.Millisecond)
-		}
-		if err != nil {
-			return err
-		}
-	}
-
 	// In case the change of mountpoint didn't remove the old path, do it ourselves
 	if shared.PathExists(shared.VarPath(fmt.Sprintf("containers/%s.zfs", oldName))) {
 		err = os.Remove(shared.VarPath(fmt.Sprintf("containers/%s.zfs", oldName)))
@@ -571,6 +595,11 @@ func (s *storageZfs) ContainerSnapshotStart(container container) error {
 		return err
 	}
 
+	err = s.zfsMount(destFs)
+	if err != nil && !s.zfsMounted(destFs) {
+		return nil
+	}
+
 	return nil
 }
 
@@ -583,7 +612,12 @@ func (s *storageZfs) ContainerSnapshotStop(container container) error {
 	sName := fields[1]
 	destFs := fmt.Sprintf("snapshots/%s/%s", cName, sName)
 
-	err := s.zfsDestroy(destFs)
+	err := s.zfsUnmount(destFs)
+	if err != nil {
+		return nil
+	}
+
+	err = s.zfsDestroy(destFs)
 	if err != nil {
 		return err
 	}
@@ -622,6 +656,12 @@ func (s *storageZfs) ImageCreate(fingerprint string) error {
 		return err
 	}
 
+	err = s.zfsMount(fs)
+	if err != nil && !s.zfsMounted(fs) {
+		return err
+	}
+	defer s.zfsUnmount(fs)
+
 	err = untarImage(imagePath, subvol)
 	if err != nil {
 		return err
@@ -701,6 +741,7 @@ func (s *storageZfs) zfsClone(source string, name string, dest string, dotZfs bo
 		"clone",
 		"-p",
 		"-o", fmt.Sprintf("mountpoint=%s", mountpoint),
+		"-o", "canmount=noauto",
 		fmt.Sprintf("%s/%s@%s", s.zfsPool, source, name),
 		fmt.Sprintf("%s/%s", s.zfsPool, dest)).CombinedOutput()
 	if err != nil {
@@ -734,6 +775,7 @@ func (s *storageZfs) zfsClone(source string, name string, dest string, dotZfs bo
 			"clone",
 			"-p",
 			"-o", fmt.Sprintf("mountpoint=%s", mountpoint),
+			"-o", "canmount=noauto",
 			fmt.Sprintf("%s/%s@%s", s.zfsPool, sub, name),
 			fmt.Sprintf("%s/%s", s.zfsPool, destSubvol)).CombinedOutput()
 		if err != nil {
@@ -751,6 +793,7 @@ func (s *storageZfs) zfsCreate(path string) error {
 		"create",
 		"-p",
 		"-o", fmt.Sprintf("mountpoint=%s.zfs", shared.VarPath(path)),
+		"-o", "canmount=noauto",
 		fmt.Sprintf("%s/%s", s.zfsPool, path)).CombinedOutput()
 	if err != nil {
 		s.log.Error("zfs create failed", log.Ctx{"output": string(output)})
@@ -979,6 +1022,10 @@ func (s *storageZfs) zfsSnapshotRename(path string, oldName string, newName stri
 }
 
 func (s *storageZfs) zfsUnmount(path string) error {
+	if !s.zfsMounted(path) {
+		return nil
+	}
+
 	output, err := exec.Command(
 		"zfs",
 		"unmount",
@@ -1363,9 +1410,8 @@ func (s *storageZfs) MigrationSink(live bool, container container, snapshots []c
 	 * before doing a recv.
 	 */
 	zfsName := fmt.Sprintf("containers/%s", container.Name())
-	fsPath := shared.VarPath(fmt.Sprintf("containers/%s.zfs", container.Name()))
 	for i := 0; i < 20; i++ {
-		if shared.IsMountPoint(fsPath) || s.zfsMounted(zfsName) {
+		if s.zfsMounted(zfsName) {
 			if err := s.zfsUnmount(zfsName); err != nil {
 				shared.Log.Error("zfs umount error for", "path", zfsName, "err", err)
 			}

From 061abc91c5fd086981a7692066417b2d057f8c98 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sun, 3 Apr 2016 17:19:46 -0400
Subject: [PATCH 2/2] Stop container storage after startup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

No need keeping the mount on the host.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/container_lxc.go | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 7262e00..1cc62d2 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1151,9 +1151,15 @@ func (c *containerLXC) Start(stateful bool) error {
 			return err
 		}
 
+		err = c.StorageStop()
+		if err != nil {
+			return err
+		}
+
 		os.RemoveAll(c.StatePath())
 		c.stateful = false
 		return dbContainerSetStateful(c.daemon.db, c.id, false)
+
 	} else if c.stateful {
 		/* stateless start required when we have state, let's delete it */
 		err := os.RemoveAll(c.StatePath())
@@ -1191,6 +1197,11 @@ func (c *containerLXC) Start(stateful bool) error {
 			err)
 	}
 
+	err = c.StorageStop()
+	if err != nil {
+		return err
+	}
+
 	return nil
 }
 
@@ -1433,13 +1444,6 @@ func (c *containerLXC) OnStop(target string) error {
 	// Make sure we can't call go-lxc functions by mistake
 	c.fromHook = true
 
-	// Stop the storage for this container
-	err := c.StorageStop()
-	if err != nil {
-		wg.Done()
-		return err
-	}
-
 	// Unload the apparmor profile
 	AAUnloadProfile(c)
 
@@ -1474,7 +1478,7 @@ func (c *containerLXC) OnStop(target string) error {
 		}
 
 		// Clean all the unix devices
-		err = c.removeUnixDevices()
+		err := c.removeUnixDevices()
 		if err != nil {
 			shared.Log.Error("Unable to remove unix devices", log.Ctx{"err": err})
 		}


More information about the lxc-devel mailing list