瀏覽代碼

Merge pull request #2897 from crosbymichael/aufs-42

Increase max image depth to 127
Guillaume J. Charmes 11 年之前
父節點
當前提交
f5ab2516d8
共有 4 個文件被更改,包括 113 次插入20 次删除
  1. 37 17
      graphdriver/aufs/aufs.go
  2. 71 0
      graphdriver/aufs/aufs_test.go
  3. 1 1
      graphdriver/aufs/mount_linux.go
  4. 4 2
      runtime.go

+ 37 - 17
graphdriver/aufs/aufs.go

@@ -26,11 +26,11 @@ import (
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/graphdriver"
 	"github.com/dotcloud/docker/utils"
-	"log"
 	"os"
 	"os/exec"
 	"path"
 	"strings"
+	"syscall"
 )
 
 func init() {
@@ -313,24 +313,44 @@ func (a *Driver) Cleanup() error {
 	return nil
 }
 
-func (a *Driver) aufsMount(ro []string, rw, target string) error {
-	rwBranch := fmt.Sprintf("%v=rw", rw)
-	roBranches := ""
-	for _, layer := range ro {
-		roBranches += fmt.Sprintf("%v=ro+wh:", layer)
-	}
-	branches := fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches)
+func (a *Driver) aufsMount(ro []string, rw, target string) (err error) {
+	defer func() {
+		if err != nil {
+			Unmount(target)
+		}
+	}()
 
-	//if error, try to load aufs kernel module
-	if err := mount("none", target, "aufs", 0, branches); err != nil {
-		log.Printf("Kernel does not support AUFS, trying to load the AUFS module with modprobe...")
-		if err := exec.Command("modprobe", "aufs").Run(); err != nil {
-			return fmt.Errorf("Unable to load the AUFS module")
+	if err = a.tryMount(ro, rw, target); err != nil {
+		if err = a.mountRw(rw, target); err != nil {
+			return
 		}
-		log.Printf("...module loaded.")
-		if err := mount("none", target, "aufs", 0, branches); err != nil {
-			return fmt.Errorf("Unable to mount using aufs %s", err)
+
+		for _, layer := range ro {
+			branch := fmt.Sprintf("append:%s=ro+wh", layer)
+			if err = mount("none", target, "aufs", syscall.MS_REMOUNT, branch); err != nil {
+				return
+			}
 		}
 	}
-	return nil
+	return
+}
+
+// Try to mount using the aufs fast path, if this fails then
+// append ro layers.
+func (a *Driver) tryMount(ro []string, rw, target string) (err error) {
+	var (
+		rwBranch   = fmt.Sprintf("%s=rw", rw)
+		roBranches = fmt.Sprintf("%s=ro+wh:", strings.Join(ro, "=ro+wh:"))
+	)
+	return mount("none", target, "aufs", 0, fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches))
+}
+
+func (a *Driver) mountRw(rw, target string) error {
+	return mount("none", target, "aufs", 0, fmt.Sprintf("br:%s,xino=/dev/shm/aufs.xino", rw))
+}
+
+func rollbackMount(target string, err error) {
+	if err != nil {
+		Unmount(target)
+	}
 }

+ 71 - 0
graphdriver/aufs/aufs_test.go

@@ -1,7 +1,11 @@
 package aufs
 
 import (
+	"crypto/sha256"
+	"encoding/hex"
+	"fmt"
 	"github.com/dotcloud/docker/archive"
+	"io/ioutil"
 	"os"
 	"path"
 	"testing"
@@ -621,3 +625,70 @@ func TestApplyDiff(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func hash(c string) string {
+	h := sha256.New()
+	fmt.Fprint(h, c)
+	return hex.EncodeToString(h.Sum(nil))
+}
+
+func TestMountMoreThan42Layers(t *testing.T) {
+	d := newDriver(t)
+	defer os.RemoveAll(tmp)
+	defer d.Cleanup()
+	var last string
+	var expected int
+
+	for i := 1; i < 127; i++ {
+		expected++
+		var (
+			parent  = fmt.Sprintf("%d", i-1)
+			current = fmt.Sprintf("%d", i)
+		)
+
+		if parent == "0" {
+			parent = ""
+		} else {
+			parent = hash(parent)
+		}
+		current = hash(current)
+
+		if err := d.Create(current, parent); err != nil {
+			t.Logf("Current layer %d", i)
+			t.Fatal(err)
+		}
+		point, err := d.Get(current)
+		if err != nil {
+			t.Logf("Current layer %d", i)
+			t.Fatal(err)
+		}
+		f, err := os.Create(path.Join(point, current))
+		if err != nil {
+			t.Logf("Current layer %d", i)
+			t.Fatal(err)
+		}
+		f.Close()
+
+		if i%10 == 0 {
+			if err := os.Remove(path.Join(point, parent)); err != nil {
+				t.Logf("Current layer %d", i)
+				t.Fatal(err)
+			}
+			expected--
+		}
+		last = current
+	}
+
+	// Perform the actual mount for the top most image
+	point, err := d.Get(last)
+	if err != nil {
+		t.Fatal(err)
+	}
+	files, err := ioutil.ReadDir(point)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(files) != expected {
+		t.Fatalf("Expected %d got %d", expected, len(files))
+	}
+}

+ 1 - 1
graphdriver/aufs/mount_linux.go

@@ -2,6 +2,6 @@ package aufs
 
 import "syscall"
 
-func mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
+func mount(source string, target string, fstype string, flags uintptr, data string) error {
 	return syscall.Mount(source, target, fstype, flags, data)
 }

+ 4 - 2
runtime.go

@@ -24,8 +24,10 @@ import (
 	"time"
 )
 
-// Set the max depth to the aufs restriction
-const MaxImageDepth = 42
+// Set the max depth to the aufs default that most
+// kernels are compiled with
+// For more information see: http://sourceforge.net/p/aufs/aufs3-standalone/ci/aufs3.12/tree/config.mk
+const MaxImageDepth = 127
 
 var defaultDns = []string{"8.8.8.8", "8.8.4.4"}