Increase max image depth to 127
| ... | ... |
@@ -26,11 +26,11 @@ import ( |
| 26 | 26 |
"github.com/dotcloud/docker/archive" |
| 27 | 27 |
"github.com/dotcloud/docker/graphdriver" |
| 28 | 28 |
"github.com/dotcloud/docker/utils" |
| 29 |
- "log" |
|
| 30 | 29 |
"os" |
| 31 | 30 |
"os/exec" |
| 32 | 31 |
"path" |
| 33 | 32 |
"strings" |
| 33 |
+ "syscall" |
|
| 34 | 34 |
) |
| 35 | 35 |
|
| 36 | 36 |
func init() {
|
| ... | ... |
@@ -313,24 +313,44 @@ func (a *Driver) Cleanup() error {
|
| 313 | 313 |
return nil |
| 314 | 314 |
} |
| 315 | 315 |
|
| 316 |
-func (a *Driver) aufsMount(ro []string, rw, target string) error {
|
|
| 317 |
- rwBranch := fmt.Sprintf("%v=rw", rw)
|
|
| 318 |
- roBranches := "" |
|
| 319 |
- for _, layer := range ro {
|
|
| 320 |
- roBranches += fmt.Sprintf("%v=ro+wh:", layer)
|
|
| 321 |
- } |
|
| 322 |
- branches := fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches)
|
|
| 316 |
+func (a *Driver) aufsMount(ro []string, rw, target string) (err error) {
|
|
| 317 |
+ defer func() {
|
|
| 318 |
+ if err != nil {
|
|
| 319 |
+ Unmount(target) |
|
| 320 |
+ } |
|
| 321 |
+ }() |
|
| 323 | 322 |
|
| 324 |
- //if error, try to load aufs kernel module |
|
| 325 |
- if err := mount("none", target, "aufs", 0, branches); err != nil {
|
|
| 326 |
- log.Printf("Kernel does not support AUFS, trying to load the AUFS module with modprobe...")
|
|
| 327 |
- if err := exec.Command("modprobe", "aufs").Run(); err != nil {
|
|
| 328 |
- return fmt.Errorf("Unable to load the AUFS module")
|
|
| 323 |
+ if err = a.tryMount(ro, rw, target); err != nil {
|
|
| 324 |
+ if err = a.mountRw(rw, target); err != nil {
|
|
| 325 |
+ return |
|
| 329 | 326 |
} |
| 330 |
- log.Printf("...module loaded.")
|
|
| 331 |
- if err := mount("none", target, "aufs", 0, branches); err != nil {
|
|
| 332 |
- return fmt.Errorf("Unable to mount using aufs %s", err)
|
|
| 327 |
+ |
|
| 328 |
+ for _, layer := range ro {
|
|
| 329 |
+ branch := fmt.Sprintf("append:%s=ro+wh", layer)
|
|
| 330 |
+ if err = mount("none", target, "aufs", syscall.MS_REMOUNT, branch); err != nil {
|
|
| 331 |
+ return |
|
| 332 |
+ } |
|
| 333 | 333 |
} |
| 334 | 334 |
} |
| 335 |
- return nil |
|
| 335 |
+ return |
|
| 336 |
+} |
|
| 337 |
+ |
|
| 338 |
+// Try to mount using the aufs fast path, if this fails then |
|
| 339 |
+// append ro layers. |
|
| 340 |
+func (a *Driver) tryMount(ro []string, rw, target string) (err error) {
|
|
| 341 |
+ var ( |
|
| 342 |
+ rwBranch = fmt.Sprintf("%s=rw", rw)
|
|
| 343 |
+ roBranches = fmt.Sprintf("%s=ro+wh:", strings.Join(ro, "=ro+wh:"))
|
|
| 344 |
+ ) |
|
| 345 |
+ return mount("none", target, "aufs", 0, fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches))
|
|
| 346 |
+} |
|
| 347 |
+ |
|
| 348 |
+func (a *Driver) mountRw(rw, target string) error {
|
|
| 349 |
+ return mount("none", target, "aufs", 0, fmt.Sprintf("br:%s,xino=/dev/shm/aufs.xino", rw))
|
|
| 350 |
+} |
|
| 351 |
+ |
|
| 352 |
+func rollbackMount(target string, err error) {
|
|
| 353 |
+ if err != nil {
|
|
| 354 |
+ Unmount(target) |
|
| 355 |
+ } |
|
| 336 | 356 |
} |
| ... | ... |
@@ -1,7 +1,11 @@ |
| 1 | 1 |
package aufs |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "crypto/sha256" |
|
| 5 |
+ "encoding/hex" |
|
| 6 |
+ "fmt" |
|
| 4 | 7 |
"github.com/dotcloud/docker/archive" |
| 8 |
+ "io/ioutil" |
|
| 5 | 9 |
"os" |
| 6 | 10 |
"path" |
| 7 | 11 |
"testing" |
| ... | ... |
@@ -621,3 +625,70 @@ func TestApplyDiff(t *testing.T) {
|
| 621 | 621 |
t.Fatal(err) |
| 622 | 622 |
} |
| 623 | 623 |
} |
| 624 |
+ |
|
| 625 |
+func hash(c string) string {
|
|
| 626 |
+ h := sha256.New() |
|
| 627 |
+ fmt.Fprint(h, c) |
|
| 628 |
+ return hex.EncodeToString(h.Sum(nil)) |
|
| 629 |
+} |
|
| 630 |
+ |
|
| 631 |
+func TestMountMoreThan42Layers(t *testing.T) {
|
|
| 632 |
+ d := newDriver(t) |
|
| 633 |
+ defer os.RemoveAll(tmp) |
|
| 634 |
+ defer d.Cleanup() |
|
| 635 |
+ var last string |
|
| 636 |
+ var expected int |
|
| 637 |
+ |
|
| 638 |
+ for i := 1; i < 127; i++ {
|
|
| 639 |
+ expected++ |
|
| 640 |
+ var ( |
|
| 641 |
+ parent = fmt.Sprintf("%d", i-1)
|
|
| 642 |
+ current = fmt.Sprintf("%d", i)
|
|
| 643 |
+ ) |
|
| 644 |
+ |
|
| 645 |
+ if parent == "0" {
|
|
| 646 |
+ parent = "" |
|
| 647 |
+ } else {
|
|
| 648 |
+ parent = hash(parent) |
|
| 649 |
+ } |
|
| 650 |
+ current = hash(current) |
|
| 651 |
+ |
|
| 652 |
+ if err := d.Create(current, parent); err != nil {
|
|
| 653 |
+ t.Logf("Current layer %d", i)
|
|
| 654 |
+ t.Fatal(err) |
|
| 655 |
+ } |
|
| 656 |
+ point, err := d.Get(current) |
|
| 657 |
+ if err != nil {
|
|
| 658 |
+ t.Logf("Current layer %d", i)
|
|
| 659 |
+ t.Fatal(err) |
|
| 660 |
+ } |
|
| 661 |
+ f, err := os.Create(path.Join(point, current)) |
|
| 662 |
+ if err != nil {
|
|
| 663 |
+ t.Logf("Current layer %d", i)
|
|
| 664 |
+ t.Fatal(err) |
|
| 665 |
+ } |
|
| 666 |
+ f.Close() |
|
| 667 |
+ |
|
| 668 |
+ if i%10 == 0 {
|
|
| 669 |
+ if err := os.Remove(path.Join(point, parent)); err != nil {
|
|
| 670 |
+ t.Logf("Current layer %d", i)
|
|
| 671 |
+ t.Fatal(err) |
|
| 672 |
+ } |
|
| 673 |
+ expected-- |
|
| 674 |
+ } |
|
| 675 |
+ last = current |
|
| 676 |
+ } |
|
| 677 |
+ |
|
| 678 |
+ // Perform the actual mount for the top most image |
|
| 679 |
+ point, err := d.Get(last) |
|
| 680 |
+ if err != nil {
|
|
| 681 |
+ t.Fatal(err) |
|
| 682 |
+ } |
|
| 683 |
+ files, err := ioutil.ReadDir(point) |
|
| 684 |
+ if err != nil {
|
|
| 685 |
+ t.Fatal(err) |
|
| 686 |
+ } |
|
| 687 |
+ if len(files) != expected {
|
|
| 688 |
+ t.Fatalf("Expected %d got %d", expected, len(files))
|
|
| 689 |
+ } |
|
| 690 |
+} |
| ... | ... |
@@ -2,6 +2,6 @@ package aufs |
| 2 | 2 |
|
| 3 | 3 |
import "syscall" |
| 4 | 4 |
|
| 5 |
-func mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
|
|
| 5 |
+func mount(source string, target string, fstype string, flags uintptr, data string) error {
|
|
| 6 | 6 |
return syscall.Mount(source, target, fstype, flags, data) |
| 7 | 7 |
} |
| ... | ... |
@@ -24,8 +24,10 @@ import ( |
| 24 | 24 |
"time" |
| 25 | 25 |
) |
| 26 | 26 |
|
| 27 |
-// Set the max depth to the aufs restriction |
|
| 28 |
-const MaxImageDepth = 42 |
|
| 27 |
+// Set the max depth to the aufs default that most |
|
| 28 |
+// kernels are compiled with |
|
| 29 |
+// For more information see: http://sourceforge.net/p/aufs/aufs3-standalone/ci/aufs3.12/tree/config.mk |
|
| 30 |
+const MaxImageDepth = 127 |
|
| 29 | 31 |
|
| 30 | 32 |
var defaultDns = []string{"8.8.8.8", "8.8.4.4"}
|
| 31 | 33 |
|