mirror of https://github.com/docker/docs.git
Merge pull request #9151 from tonistiigi/aufs-clipping-fix
Fix AUFS silent mount errors on many layers
This commit is contained in:
commit
8682bac309
|
@ -412,39 +412,44 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err = a.tryMount(ro, rw, target, mountLabel); err != nil {
|
// Mount options are clipped to page size(4096 bytes). If there are more
|
||||||
if err = a.mountRw(rw, target, mountLabel); err != nil {
|
// layers then these are remounted individually using append.
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, layer := range ro {
|
b := make([]byte, syscall.Getpagesize()-len(mountLabel)-50) // room for xino & mountLabel
|
||||||
data := label.FormatMountLabel(fmt.Sprintf("append:%s=ro+wh", layer), mountLabel)
|
bp := copy(b, fmt.Sprintf("br:%s=rw", rw))
|
||||||
if err = mount("none", target, "aufs", MsRemount, data); err != nil {
|
|
||||||
return
|
firstMount := true
|
||||||
|
i := 0
|
||||||
|
|
||||||
|
for {
|
||||||
|
for ; i < len(ro); i++ {
|
||||||
|
layer := fmt.Sprintf(":%s=ro+wh", ro[i])
|
||||||
|
|
||||||
|
if firstMount {
|
||||||
|
if bp+len(layer) > len(b) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
bp += copy(b[bp:], layer)
|
||||||
|
} else {
|
||||||
|
data := label.FormatMountLabel(fmt.Sprintf("append%s", layer), mountLabel)
|
||||||
|
if err = mount("none", target, "aufs", MsRemount, data); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if firstMount {
|
||||||
|
data := label.FormatMountLabel(fmt.Sprintf("%s,xino=/dev/shm/aufs.xino", string(b[:bp])), mountLabel)
|
||||||
|
if err = mount("none", target, "aufs", 0, data); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
firstMount = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == len(ro) {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to mount using the aufs fast path, if this fails then
|
|
||||||
// append ro layers.
|
|
||||||
func (a *Driver) tryMount(ro []string, rw, target, mountLabel string) (err error) {
|
|
||||||
var (
|
|
||||||
rwBranch = fmt.Sprintf("%s=rw", rw)
|
|
||||||
roBranches = fmt.Sprintf("%s=ro+wh:", strings.Join(ro, "=ro+wh:"))
|
|
||||||
data = label.FormatMountLabel(fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches), mountLabel)
|
|
||||||
)
|
|
||||||
return mount("none", target, "aufs", 0, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Driver) mountRw(rw, target, mountLabel string) error {
|
|
||||||
data := label.FormatMountLabel(fmt.Sprintf("br:%s,xino=/dev/shm/aufs.xino", rw), mountLabel)
|
|
||||||
return mount("none", target, "aufs", 0, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func rollbackMount(target string, err error) {
|
|
||||||
if err != nil {
|
|
||||||
Unmount(target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -635,9 +635,13 @@ func hash(c string) string {
|
||||||
return hex.EncodeToString(h.Sum(nil))
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMountMoreThan42Layers(t *testing.T) {
|
func testMountMoreThan42Layers(t *testing.T, mountPath string) {
|
||||||
d := newDriver(t)
|
if err := os.MkdirAll(mountPath, 0755); err != nil {
|
||||||
defer os.RemoveAll(tmp)
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d := testInit(mountPath, t).(*Driver)
|
||||||
|
defer os.RemoveAll(mountPath)
|
||||||
defer d.Cleanup()
|
defer d.Cleanup()
|
||||||
var last string
|
var last string
|
||||||
var expected int
|
var expected int
|
||||||
|
@ -695,3 +699,25 @@ func TestMountMoreThan42Layers(t *testing.T) {
|
||||||
t.Fatalf("Expected %d got %d", expected, len(files))
|
t.Fatalf("Expected %d got %d", expected, len(files))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMountMoreThan42Layers(t *testing.T) {
|
||||||
|
testMountMoreThan42Layers(t, tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMountMoreThan42LayersMatchingPathLength(t *testing.T) {
|
||||||
|
tmp := "aufs-tests"
|
||||||
|
for {
|
||||||
|
// This finds a mount path so that when combined into aufs mount options
|
||||||
|
// 4096 byte boundary would be in between the paths or in permission
|
||||||
|
// section. For '/tmp' it will use '/tmp/aufs-tests00000000/aufs'
|
||||||
|
mountPath := path.Join(os.TempDir(), tmp, "aufs")
|
||||||
|
pathLength := 77 + len(mountPath)
|
||||||
|
|
||||||
|
if mod := 4095 % pathLength; mod == 0 || mod > pathLength-2 {
|
||||||
|
t.Logf("Using path: %s", mountPath)
|
||||||
|
testMountMoreThan42Layers(t, mountPath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tmp += "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue