[lxc-devel] [lxd/master] Bugfixes

stgraber on Github lxc-bot at linuxcontainers.org
Mon Jan 30 22:40:24 UTC 2017


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/20170130/442c833c/attachment.bin>
-------------- next part --------------
From 4b86598132caf1991bedae40f20add1f396b4307 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 30 Jan 2017 16:34:41 -0500
Subject: [PATCH 1/2] simplestreams: Always prefer squashfs when available
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Makes things less random for users and is usually a bit faster to unpack.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 shared/simplestreams/simplestreams.go | 76 ++++++++++++++++++-----------------
 1 file changed, 39 insertions(+), 37 deletions(-)

diff --git a/shared/simplestreams/simplestreams.go b/shared/simplestreams/simplestreams.go
index 490cc4f..6ca7666 100644
--- a/shared/simplestreams/simplestreams.go
+++ b/shared/simplestreams/simplestreams.go
@@ -107,58 +107,60 @@ func (s *SimpleStreamsManifest) ToLXD() ([]api.Image, map[string][][]string) {
 				continue
 			}
 
-			size := int64(0)
-			filename := ""
-			fingerprint := ""
+			var meta SimpleStreamsManifestProductVersionItem
+			var rootTar SimpleStreamsManifestProductVersionItem
+			var rootSquash SimpleStreamsManifestProductVersionItem
 
-			metaPath := ""
-			metaHash := ""
-			rootfsPath := ""
-			rootfsHash := ""
-
-			found := 0
 			for _, item := range version.Items {
 				// Skip the files we don't care about
 				if !shared.StringInSlice(item.FileType, []string{"root.tar.xz", "lxd.tar.xz", "squashfs"}) {
 					continue
 				}
-				found += 1
-
-				if fingerprint == "" {
-					if item.LXDHashSha256SquashFs != "" {
-						fingerprint = item.LXDHashSha256SquashFs
-					} else if item.LXDHashSha256RootXz != "" {
-						fingerprint = item.LXDHashSha256RootXz
-					} else if item.LXDHashSha256 != "" {
-						fingerprint = item.LXDHashSha256
-					}
-				}
 
 				if item.FileType == "lxd.tar.xz" {
-					fields := strings.Split(item.Path, "/")
-					filename = fields[len(fields)-1]
-					metaPath = item.Path
-					metaHash = item.HashSha256
-
-					size += item.Size
+					meta = item
+				} else if item.FileType == "squashfs" {
+					rootSquash = item
+				} else if item.FileType == "root.tar.xz" {
+					rootTar = item
 				}
+			}
 
-				if rootfsPath == "" || rootfsHash == "" {
-					if item.FileType == "squashfs" {
-						rootfsPath = item.Path
-						rootfsHash = item.HashSha256
-					}
+			if meta.FileType == "" || (rootTar.FileType == "" && rootSquash.FileType == "") {
+				// Invalid image
+				continue
+			}
 
-					if item.FileType == "root.tar.xz" {
-						rootfsPath = item.Path
-						rootfsHash = item.HashSha256
-					}
+			metaPath := meta.Path
+			metaHash := meta.HashSha256
+			rootfsPath := ""
+			rootfsHash := ""
+			fields := strings.Split(meta.Path, "/")
+			filename := fields[len(fields)-1]
+			size := meta.Size
+			fingerprint := ""
 
-					size += item.Size
+			if rootSquash.FileType != "" {
+				if meta.LXDHashSha256SquashFs != "" {
+					fingerprint = meta.LXDHashSha256SquashFs
+				} else {
+					fingerprint = meta.LXDHashSha256
+				}
+				size += rootSquash.Size
+				rootfsPath = rootSquash.Path
+				rootfsHash = rootSquash.HashSha256
+			} else {
+				if meta.LXDHashSha256RootXz != "" {
+					fingerprint = meta.LXDHashSha256RootXz
+				} else {
+					fingerprint = meta.LXDHashSha256
 				}
+				size += rootTar.Size
+				rootfsPath = rootTar.Path
+				rootfsHash = rootTar.HashSha256
 			}
 
-			if found < 2 || size == 0 || filename == "" || fingerprint == "" {
+			if size == 0 || filename == "" || fingerprint == "" {
 				// Invalid image
 				continue
 			}

From 44da2259ed4d790ebeba7a33953cb3c470805781 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 30 Jan 2017 17:38:34 -0500
Subject: [PATCH 2/2] btrfs: Fix recursive subvol deletion
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

 - Always iterate through the filesystem to find the subvolumes as there
   doesn't seem to be a good way to get a long tree of nested subvolumes
   out of btrfs subvolume list.

 - To improve performance of above, change isSubvolume to do a single
   syscall and not fork btrfs.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/storage_btrfs.go | 129 ++++++++++++---------------------------------------
 1 file changed, 30 insertions(+), 99 deletions(-)

diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index cf70b21..2b9f2ab 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -8,6 +8,7 @@ import (
 	"os/exec"
 	"path"
 	"path/filepath"
+	"sort"
 	"strconv"
 	"strings"
 	"syscall"
@@ -694,38 +695,14 @@ func (s *storageBtrfs) subvolsSnapshot(
  * else false.
  */
 func (s *storageBtrfs) isSubvolume(subvolPath string) bool {
-	if runningInUserns {
-		// subvolume show is restricted to real root, use a workaround
-
-		fs := syscall.Statfs_t{}
-		err := syscall.Statfs(subvolPath, &fs)
-		if err != nil {
-			return false
-		}
-
-		if fs.Type != filesystemSuperMagicBtrfs {
-			return false
-		}
-
-		parentFs := syscall.Statfs_t{}
-		err = syscall.Statfs(path.Dir(subvolPath), &parentFs)
-		if err != nil {
-			return false
-		}
-
-		if fs.Fsid == parentFs.Fsid {
-			return false
-		}
-
-		return true
+	fs := syscall.Stat_t{}
+	err := syscall.Lstat(subvolPath, &fs)
+	if err != nil {
+		return false
 	}
 
-	output, err := exec.Command(
-		"btrfs",
-		"subvolume",
-		"show",
-		subvolPath).CombinedOutput()
-	if err != nil || strings.HasPrefix(string(output), "ERROR: ") {
+	// Check if BTRFS_FIRST_FREE_OBJECTID
+	if fs.Ino != 256 {
 		return false
 	}
 
@@ -736,82 +713,36 @@ func (s *storageBtrfs) isSubvolume(subvolPath string) bool {
 func (s *storageBtrfs) getSubVolumes(path string) ([]string, error) {
 	result := []string{}
 
-	if runningInUserns {
-		if !strings.HasSuffix(path, "/") {
-			path = path + "/"
-		}
-
-		// Unprivileged users can't get to fs internals
-		filepath.Walk(path, func(fpath string, fi os.FileInfo, err error) error {
-			if strings.TrimRight(fpath, "/") == strings.TrimRight(path, "/") {
-				return nil
-			}
-
-			if err != nil {
-				return nil
-			}
-
-			if !fi.IsDir() {
-				return nil
-			}
-
-			if s.isSubvolume(fpath) {
-				result = append(result, strings.TrimPrefix(fpath, path))
-			}
-			return nil
-		})
-
-		return result, nil
+	if !strings.HasSuffix(path, "/") {
+		path = path + "/"
 	}
 
-	out, err := exec.Command(
-		"btrfs",
-		"inspect-internal",
-		"rootid",
-		path).CombinedOutput()
-	if err != nil {
-		return result, fmt.Errorf(
-			"Unable to get btrfs rootid, path='%s', err='%s'",
-			path,
-			err)
-	}
-	rootid := strings.TrimRight(string(out), "\n")
+	// Unprivileged users can't get to fs internals
+	filepath.Walk(path, func(fpath string, fi os.FileInfo, err error) error {
+		// Skip walk errors
+		if err != nil {
+			return nil
+		}
 
-	out, err = exec.Command(
-		"btrfs",
-		"inspect-internal",
-		"subvolid-resolve",
-		rootid, path).CombinedOutput()
-	if err != nil {
-		return result, fmt.Errorf(
-			"Unable to resolve btrfs rootid, path='%s', err='%s'",
-			path,
-			err)
-	}
-	basePath := strings.TrimRight(string(out), "\n")
+		// Ignore the base path
+		if strings.TrimRight(fpath, "/") == strings.TrimRight(path, "/") {
+			return nil
+		}
 
-	out, err = exec.Command(
-		"btrfs",
-		"subvolume",
-		"list",
-		"-o",
-		path).CombinedOutput()
-	if err != nil {
-		return result, fmt.Errorf(
-			"Unable to list subvolumes, path='%s', err='%s'",
-			path,
-			err)
-	}
+		// Subvolumes can only be directories
+		if !fi.IsDir() {
+			return nil
+		}
 
-	lines := strings.Split(string(out), "\n")
-	for _, line := range lines {
-		if line == "" {
-			continue
+		// Check if a btrfs subvolume
+		if s.isSubvolume(fpath) {
+			result = append(result, strings.TrimPrefix(fpath, path))
 		}
 
-		cols := strings.Fields(line)
-		result = append(result, cols[8][len(basePath):])
-	}
+		return nil
+	})
+
+	sort.Sort(sort.Reverse(sort.StringSlice(result)))
 
 	return result, nil
 }


More information about the lxc-devel mailing list