[lxc-devel] [lxd/master] Bugfixes

stgraber on Github lxc-bot at linuxcontainers.org
Sun Nov 20 05:31:13 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 700 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20161120/a07216f6/attachment.bin>
-------------- next part --------------
From d00b6e2e080085409e5632e4b83c24ee071f1e67 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sun, 20 Nov 2016 00:28:48 -0500
Subject: [PATCH] zfs: Fix 10s delay on removing used images
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

For some reason "zfs rename" attempts to unmount and remount all
descendants. This behavior, combined with what looks like lack of
support for mount namespaces in ZFS, causes "zfs rename" to fail despite
having succesfuly renamed the dataset.

So instead of believing the return code, always check if the rename happened.

Closes #2617

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

diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 85d57b4..333ac12 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -9,6 +9,7 @@ import (
 	"strconv"
 	"strings"
 	"syscall"
+	"time"
 
 	"github.com/gorilla/websocket"
 
@@ -924,20 +925,33 @@ func (s *storageZfs) zfsGet(path string, key string) (string, error) {
 }
 
 func (s *storageZfs) zfsRename(source string, dest string) error {
-	output, err := tryExec(
-		"zfs",
-		"rename",
-		"-p",
-		fmt.Sprintf("%s/%s", s.zfsPool, source),
-		fmt.Sprintf("%s/%s", s.zfsPool, dest))
-	if err != nil {
-		if s.zfsExists(source) || !s.zfsExists(dest) {
-			s.log.Error("zfs rename failed", log.Ctx{"output": string(output)})
-			return fmt.Errorf("Failed to rename ZFS filesystem: %s", output)
+	var err error
+	var output []byte
+
+	for i := 0; i < 20; i++ {
+		output, err = exec.Command(
+			"zfs",
+			"rename",
+			"-p",
+			fmt.Sprintf("%s/%s", s.zfsPool, source),
+			fmt.Sprintf("%s/%s", s.zfsPool, dest)).CombinedOutput()
+
+		// Success
+		if err == nil {
+			return nil
+		}
+
+		// zfs rename can fail because of descendants, yet still manage the rename
+		if !s.zfsExists(source) && s.zfsExists(dest) {
+			return nil
 		}
+
+		time.Sleep(500 * time.Millisecond)
 	}
 
-	return nil
+	// Timeout
+	s.log.Error("zfs rename failed", log.Ctx{"output": string(output)})
+	return fmt.Errorf("Failed to rename ZFS filesystem: %s", output)
 }
 
 func (s *storageZfs) zfsSet(path string, key string, value string) error {


More information about the lxc-devel mailing list