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)
| ... | ... |
@@ -31,12 +31,12 @@ type mountOptions struct {
|
| 31 | 31 |
Flag uint32 |
| 32 | 32 |
} |
| 33 | 33 |
|
| 34 |
-func mountFrom(dir, device, target, mType, label string) error {
|
|
| 34 |
+func mountFrom(dir, device, target, mType string, flags uintptr, label string) error {
|
|
| 35 | 35 |
options := &mountOptions{
|
| 36 | 36 |
Device: device, |
| 37 | 37 |
Target: target, |
| 38 | 38 |
Type: mType, |
| 39 |
- Flag: 0, |
|
| 39 |
+ Flag: uint32(flags), |
|
| 40 | 40 |
Label: label, |
| 41 | 41 |
} |
| 42 | 42 |
|
| ... | ... |
@@ -409,13 +409,36 @@ func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
|
| 409 | 409 |
}() |
| 410 | 410 |
|
| 411 | 411 |
workDir := path.Join(dir, "work") |
| 412 |
- opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work"))
|
|
| 413 |
- mountLabel = label.FormatMountLabel(opts, mountLabel) |
|
| 414 |
- if len(mountLabel) > syscall.Getpagesize() {
|
|
| 415 |
- return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountLabel))
|
|
| 412 |
+ splitLowers := strings.Split(string(lowers), ":") |
|
| 413 |
+ absLowers := make([]string, len(splitLowers)) |
|
| 414 |
+ for i, s := range splitLowers {
|
|
| 415 |
+ absLowers[i] = path.Join(d.home, s) |
|
| 416 |
+ } |
|
| 417 |
+ opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), path.Join(dir, "diff"), path.Join(dir, "work"))
|
|
| 418 |
+ mountData := label.FormatMountLabel(opts, mountLabel) |
|
| 419 |
+ mount := syscall.Mount |
|
| 420 |
+ mountTarget := mergedDir |
|
| 421 |
+ |
|
| 422 |
+ pageSize := syscall.Getpagesize() |
|
| 423 |
+ |
|
| 424 |
+ // Use relative paths and mountFrom when the mount data has exceeded |
|
| 425 |
+ // the page size. The mount syscall fails if the mount data cannot |
|
| 426 |
+ // fit within a page and relative links make the mount data much |
|
| 427 |
+ // smaller at the expense of requiring a fork exec to chroot. |
|
| 428 |
+ if len(mountData) > pageSize {
|
|
| 429 |
+ opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work"))
|
|
| 430 |
+ mountData = label.FormatMountLabel(opts, mountLabel) |
|
| 431 |
+ if len(mountData) > pageSize {
|
|
| 432 |
+ return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
|
|
| 433 |
+ } |
|
| 434 |
+ |
|
| 435 |
+ mount = func(source string, target string, mType string, flags uintptr, label string) error {
|
|
| 436 |
+ return mountFrom(d.home, source, target, mType, flags, label) |
|
| 437 |
+ } |
|
| 438 |
+ mountTarget = path.Join(id, "merged") |
|
| 416 | 439 |
} |
| 417 | 440 |
|
| 418 |
- if err := mountFrom(d.home, "overlay", path.Join(id, "merged"), "overlay", mountLabel); err != nil {
|
|
| 441 |
+ if err := mount("overlay", mountTarget, "overlay", 0, mountData); err != nil {
|
|
| 419 | 442 |
return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
|
| 420 | 443 |
} |
| 421 | 444 |
|