Skip to content
This repository was archived by the owner on Oct 13, 2023. It is now read-only.

Commit 546ed3e

Browse files
dmcgowanthaJeztah
authored andcommitted
Fix overlay2 busy error on mount
When mounting overlays which have children, enforce that the mount is always performed as read only. Newer versions of the kernel return a device busy error when a lower directory is in use as an upper directory in another overlay mount. Adds committed file to indicate when an overlay is being used as a parent, ensuring it will no longer be mounted with an upper directory. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (cherry picked from commit 477bf1e413708076f9ed8cd316102765cc5bdb11) Signed-off-by: Sebastiaan van Stijn <github@gone.nl> Upstream-commit: 16342ac1b17b44403ac0a4b0c02fdc110be494f6 Component: engine
1 parent 34c442a commit 546ed3e

1 file changed

Lines changed: 29 additions & 6 deletions

File tree

  • components/engine/daemon/graphdriver/overlay2

components/engine/daemon/graphdriver/overlay2/overlay.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,10 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
446446
return err
447447
}
448448

449+
if err := ioutil.WriteFile(path.Join(d.dir(parent), "committed"), []byte{}, 0600); err != nil {
450+
return err
451+
}
452+
449453
lower, err := d.getLower(parent)
450454
if err != nil {
451455
return err
@@ -592,7 +596,20 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
592596
for i, s := range splitLowers {
593597
absLowers[i] = path.Join(d.home, s)
594598
}
595-
opts := indexOff + "lowerdir=" + strings.Join(absLowers, ":") + ",upperdir=" + diffDir + ",workdir=" + workDir
599+
var readonly bool
600+
if _, err := os.Stat(path.Join(dir, "committed")); err == nil {
601+
readonly = true
602+
} else if !os.IsNotExist(err) {
603+
return nil, err
604+
}
605+
606+
var opts string
607+
if readonly {
608+
opts = indexOff + "lowerdir=" + diffDir + ":" + strings.Join(absLowers, ":")
609+
} else {
610+
opts = indexOff + "lowerdir=" + strings.Join(absLowers, ":") + ",upperdir=" + diffDir + ",workdir=" + workDir
611+
}
612+
596613
mountData := label.FormatMountLabel(opts, mountLabel)
597614
mount := unix.Mount
598615
mountTarget := mergedDir
@@ -612,7 +629,11 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
612629
// fit within a page and relative links make the mount data much
613630
// smaller at the expense of requiring a fork exec to chroot.
614631
if len(mountData) > pageSize {
615-
opts = indexOff + "lowerdir=" + string(lowers) + ",upperdir=" + path.Join(id, diffDirName) + ",workdir=" + path.Join(id, workDirName)
632+
if readonly {
633+
opts = indexOff + "lowerdir=" + path.Join(id, diffDirName) + ":" + string(lowers)
634+
} else {
635+
opts = indexOff + "lowerdir=" + string(lowers) + ",upperdir=" + path.Join(id, diffDirName) + ",workdir=" + path.Join(id, workDirName)
636+
}
616637
mountData = label.FormatMountLabel(opts, mountLabel)
617638
if len(mountData) > pageSize {
618639
return nil, fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
@@ -628,10 +649,12 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
628649
return nil, fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
629650
}
630651

631-
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
632-
// user namespace requires this to move a directory from lower to upper.
633-
if err := os.Chown(path.Join(workDir, workDirName), rootUID, rootGID); err != nil {
634-
return nil, err
652+
if !readonly {
653+
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
654+
// user namespace requires this to move a directory from lower to upper.
655+
if err := os.Chown(path.Join(workDir, workDirName), rootUID, rootGID); err != nil {
656+
return nil, err
657+
}
635658
}
636659

637660
return containerfs.NewLocalContainerFS(mergedDir), nil

0 commit comments

Comments
 (0)