[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