From 955c1f881ac94af19c99f0f7d5635e6a574789f2 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 16 Nov 2017 17:34:33 +0100 Subject: [PATCH] Detect overlay2 support on pre-4.0 kernels The overlay2 storage-driver requires multiple lower dir support for overlayFs. Support for this feature was added in kernel 4.x, but some distros (RHEL 7.4, CentOS 7.4) ship with an older kernel with this feature backported. This patch adds feature-detection for multiple lower dirs, and will perform this feature-detection on pre-4.x kernels with overlayFS support. With this patch applied, daemons running on a kernel with multiple lower dir support will now select "overlay2" as storage-driver, instead of falling back to "overlay". Signed-off-by: Sebastiaan van Stijn --- daemon/graphdriver/overlay2/check.go | 32 ++++++++++++++++++++++++++ daemon/graphdriver/overlay2/overlay.go | 23 ++++++++++-------- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/daemon/graphdriver/overlay2/check.go b/daemon/graphdriver/overlay2/check.go index f29630bd2f..c1c44200fd 100644 --- a/daemon/graphdriver/overlay2/check.go +++ b/daemon/graphdriver/overlay2/check.go @@ -100,3 +100,35 @@ func doesSupportNativeDiff(d string) error { return nil } + +// supportsMultipleLowerDir checks if the system supports multiple lowerdirs, +// which is required for the overlay2 driver. On 4.x kernels, multiple lowerdirs +// are always available (so this check isn't needed), and backported to RHEL and +// CentOS 3.x kernels (3.10.0-693.el7.x86_64 and up). This function is to detect +// support on those kernels, without doing a kernel version compare. +func supportsMultipleLowerDir(d string) error { + td, err := ioutil.TempDir(d, "multiple-lowerdir-check") + if err != nil { + return err + } + defer func() { + if err := os.RemoveAll(td); err != nil { + logrus.Warnf("Failed to remove check directory %v: %v", td, err) + } + }() + + for _, dir := range []string{"lower1", "lower2", "upper", "work", "merged"} { + if err := os.Mkdir(filepath.Join(td, dir), 0755); err != nil { + return err + } + } + + opts := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", path.Join(td, "lower2"), path.Join(td, "lower1"), path.Join(td, "upper"), path.Join(td, "work")) + if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", 0, opts); err != nil { + return errors.Wrap(err, "failed to mount overlay") + } + if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil { + logrus.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err) + } + return nil +} diff --git a/daemon/graphdriver/overlay2/overlay.go b/daemon/graphdriver/overlay2/overlay.go index c2023c7252..a399bf2fa2 100644 --- a/daemon/graphdriver/overlay2/overlay.go +++ b/daemon/graphdriver/overlay2/overlay.go @@ -16,8 +16,6 @@ import ( "strings" "sync" - "github.com/sirupsen/logrus" - "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/daemon/graphdriver/overlayutils" "github.com/docker/docker/daemon/graphdriver/quota" @@ -32,9 +30,9 @@ import ( "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/system" - units "github.com/docker/go-units" - + "github.com/docker/go-units" "github.com/opencontainers/selinux/go-selinux/label" + "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -134,12 +132,6 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap if err != nil { return nil, err } - if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 4, Major: 0, Minor: 0}) < 0 { - if !opts.overrideKernelCheck { - return nil, graphdriver.ErrNotSupported - } - logrus.Warn("Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update") - } fsMagic, err := graphdriver.GetFSMagic(home) if err != nil { @@ -166,6 +158,17 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap } } + if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 4, Major: 0, Minor: 0}) < 0 { + if opts.overrideKernelCheck { + logrus.Warn("Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update") + } else { + if err := supportsMultipleLowerDir(filepath.Dir(home)); err != nil { + logrus.Debugf("Multiple lower dirs not supported: %v", err) + return nil, graphdriver.ErrNotSupported + } + } + } + rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err