overlay2: use index=off if possible
As pointed out in https://github.com/moby/moby/issues/37970, Docker overlay driver can't work with index=on feature of the Linux kernel "overlay" filesystem. In case the global default is set to "yes", Docker will fail with EBUSY when trying to mount, like this: > error creating overlay mount to ...../merged: device or resource busy and the kernel log should contain something like: > overlayfs: upperdir is in-use by another mount, mount with > '-o index=off' to override exclusive upperdir protection. A workaround is to set index=off in overlay kernel module parameters, or even recompile the kernel with CONFIG_OVERLAY_FS_INDEX=n in .config. Surely this is not always practical or even possible. The solution, as pointed out my Amir Goldstein (as well as the above kernel message:) is to use 'index=off' option when mounting. NOTE since older (< 4.13rc1) kernels do not support "index=" overlayfs parameter, try to figure out whether the option is supported. In case it's not possible to figure out, assume it is not. NOTE the default can be changed anytime (by writing to /sys/module/overlay/parameters/index) so we need to always use index=off. [v2: move the detection code to Init()] [v3: don't set index=off if stat() failed] Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> (cherry picked from commit 8422d85087bfa770b62ef4e1daaca95ee6783d86) Signed-off-by: Sebastiaan van Stijn <github@gone.nl> Upstream-commit: 690e097fedd7362f3b2781c32ca872ad966d286e Component: engine
This commit is contained in:
committed by
Sebastiaan van Stijn
parent
c38ae153e0
commit
f3d391be68
@ -112,6 +112,8 @@ var (
|
||||
|
||||
useNaiveDiffLock sync.Once
|
||||
useNaiveDiffOnly bool
|
||||
|
||||
indexOff string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -227,7 +229,18 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
return nil, fmt.Errorf("Storage Option overlay2.size only supported for backingFS XFS. Found %v", backingFs)
|
||||
}
|
||||
|
||||
logger.Debugf("backingFs=%s, projectQuotaSupported=%v", backingFs, projectQuotaSupported)
|
||||
// figure out whether "index=off" option is recognized by the kernel
|
||||
_, err = os.Stat("/sys/module/overlay/parameters/index")
|
||||
switch {
|
||||
case err == nil:
|
||||
indexOff = "index=off,"
|
||||
case os.IsNotExist(err):
|
||||
// old kernel, no index -- do nothing
|
||||
default:
|
||||
logger.Warnf("Unable to detect whether overlay kernel module supports index parameter: %s", err)
|
||||
}
|
||||
|
||||
logger.Debugf("backingFs=%s, projectQuotaSupported=%v, indexOff=%q", backingFs, projectQuotaSupported, indexOff)
|
||||
|
||||
return d, nil
|
||||
}
|
||||
@ -576,7 +589,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
|
||||
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"))
|
||||
opts := indexOff + "lowerdir=" + strings.Join(absLowers, ":") + ",upperdir=" + path.Join(dir, "diff") + ",workdir=" + path.Join(dir, "work")
|
||||
mountData := label.FormatMountLabel(opts, mountLabel)
|
||||
mount := unix.Mount
|
||||
mountTarget := mergedDir
|
||||
@ -605,7 +618,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
|
||||
// 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"))
|
||||
opts = indexOff + "lowerdir=" + string(lowers) + ",upperdir=" + path.Join(id, "diff") + ",workdir=" + path.Join(id, "work")
|
||||
mountData = label.FormatMountLabel(opts, mountLabel)
|
||||
if len(mountData) > pageSize {
|
||||
return nil, fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
|
||||
|
||||
Reference in New Issue
Block a user