Avoid fork on mount for overlay2 in common case
In the common case where the user is using /var/lib/docker and an image with less than 60 layers, forking is not needed. Calculate whether absolute paths can be used and avoid forking to mount in those cases. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
parent
9a3e7d9e34
commit
c13a985fa1
2 changed files with 30 additions and 7 deletions
|
@ -31,12 +31,12 @@ type mountOptions struct {
|
|||
Flag uint32
|
||||
}
|
||||
|
||||
func mountFrom(dir, device, target, mType, label string) error {
|
||||
func mountFrom(dir, device, target, mType string, flags uintptr, label string) error {
|
||||
options := &mountOptions{
|
||||
Device: device,
|
||||
Target: target,
|
||||
Type: mType,
|
||||
Flag: 0,
|
||||
Flag: uint32(flags),
|
||||
Label: label,
|
||||
}
|
||||
|
||||
|
|
|
@ -409,13 +409,36 @@ func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
|||
}()
|
||||
|
||||
workDir := path.Join(dir, "work")
|
||||
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work"))
|
||||
mountLabel = label.FormatMountLabel(opts, mountLabel)
|
||||
if len(mountLabel) > syscall.Getpagesize() {
|
||||
return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountLabel))
|
||||
splitLowers := strings.Split(string(lowers), ":")
|
||||
absLowers := make([]string, len(splitLowers))
|
||||
for i, s := range splitLowers {
|
||||
absLowers[i] = path.Join(d.home, s)
|
||||
}
|
||||
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), path.Join(dir, "diff"), path.Join(dir, "work"))
|
||||
mountData := label.FormatMountLabel(opts, mountLabel)
|
||||
mount := syscall.Mount
|
||||
mountTarget := mergedDir
|
||||
|
||||
pageSize := syscall.Getpagesize()
|
||||
|
||||
// Use relative paths and mountFrom when the mount data has exceeded
|
||||
// the page size. The mount syscall fails if the mount data cannot
|
||||
// fit within a page and relative links make the mount data much
|
||||
// smaller at the expense of requiring a fork exec to chroot.
|
||||
if len(mountData) > pageSize {
|
||||
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work"))
|
||||
mountData = label.FormatMountLabel(opts, mountLabel)
|
||||
if len(mountData) > pageSize {
|
||||
return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
|
||||
}
|
||||
|
||||
mount = func(source string, target string, mType string, flags uintptr, label string) error {
|
||||
return mountFrom(d.home, source, target, mType, flags, label)
|
||||
}
|
||||
mountTarget = path.Join(id, "merged")
|
||||
}
|
||||
|
||||
if err := mountFrom(d.home, "overlay", path.Join(id, "merged"), "overlay", mountLabel); err != nil {
|
||||
if err := mount("overlay", mountTarget, "overlay", 0, mountData); err != nil {
|
||||
return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue