From 649e4c88899878c9cdf9036f6bc7d62e2b39c04b Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Thu, 7 Nov 2019 15:03:29 -0800 Subject: [PATCH] Fix/improve overlay support check Before this commit, overlay check was performed by looking for `overlay` in /proc/filesystem. This obviously might not work for rootless Docker (fs is there, but one can't use it as non-root). This commit changes the check to perform the actual mount, by reusing the code previously written to check for multiple lower dirs support. The old check is removed from both drivers, as well as the additional check for the multiple lower dirs support in overlay2 since it's now a part of the main check. Signed-off-by: Kir Kolyshkin --- daemon/graphdriver/overlay/overlay.go | 37 ++------------- daemon/graphdriver/overlay2/overlay.go | 47 ++----------------- .../graphdriver/overlayutils/overlayutils.go | 20 ++++---- 3 files changed, 22 insertions(+), 82 deletions(-) diff --git a/daemon/graphdriver/overlay/overlay.go b/daemon/graphdriver/overlay/overlay.go index eda0d7cd53..1d850ed186 100644 --- a/daemon/graphdriver/overlay/overlay.go +++ b/daemon/graphdriver/overlay/overlay.go @@ -3,7 +3,6 @@ package overlay // import "github.com/docker/docker/daemon/graphdriver/overlay" import ( - "bufio" "fmt" "io" "io/ioutil" @@ -123,10 +122,6 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, err } - if err := supportsOverlay(); err != nil { - return nil, graphdriver.ErrNotSupported - } - // Perform feature detection on /var/lib/docker/overlay if it's an existing directory. // This covers situations where /var/lib/docker/overlay is a mount, and on a different // filesystem than /var/lib/docker. @@ -136,6 +131,11 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap testdir = filepath.Dir(testdir) } + if err := overlayutils.SupportsOverlay(testdir, false); err != nil { + logrus.WithField("storage-driver", "overlay").Error(err) + return nil, graphdriver.ErrNotSupported + } + fsMagic, err := graphdriver.GetFSMagic(testdir) if err != nil { return nil, err @@ -199,33 +199,6 @@ func parseOptions(options []string) (*overlayOptions, error) { return o, nil } -func supportsOverlay() error { - // Access overlay filesystem so that Linux loads it (if possible). - mountTarget, err := ioutil.TempDir("", "supportsOverlay") - if err != nil { - logrus.WithError(err).WithField("storage-driver", "overlay2").Error("could not create temporary directory, so assuming that 'overlay' is not supported") - return graphdriver.ErrNotSupported - } - /* The mounting will fail--after the module has been loaded.*/ - defer os.RemoveAll(mountTarget) - unix.Mount("overlay", mountTarget, "overlay", 0, "") - - f, err := os.Open("/proc/filesystems") - if err != nil { - return err - } - defer f.Close() - - s := bufio.NewScanner(f) - for s.Scan() { - if s.Text() == "nodev\toverlay" { - return nil - } - } - logrus.WithField("storage-driver", "overlay").Error("'overlay' not found as a supported filesystem on this host. Please ensure kernel is new enough and has overlay support loaded.") - return graphdriver.ErrNotSupported -} - func (d *Driver) String() string { return "overlay" } diff --git a/daemon/graphdriver/overlay2/overlay.go b/daemon/graphdriver/overlay2/overlay.go index 06240312f9..638b1cae63 100644 --- a/daemon/graphdriver/overlay2/overlay.go +++ b/daemon/graphdriver/overlay2/overlay.go @@ -3,7 +3,6 @@ package overlay2 // import "github.com/docker/docker/daemon/graphdriver/overlay2" import ( - "bufio" "context" "errors" "fmt" @@ -133,10 +132,6 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, err } - if err := supportsOverlay(); err != nil { - return nil, graphdriver.ErrNotSupported - } - // require kernel 4.0.0 to ensure multiple lower dirs are supported v, err := kernel.GetKernelVersion() if err != nil { @@ -152,6 +147,11 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap testdir = filepath.Dir(testdir) } + if err := overlayutils.SupportsOverlay(testdir, true); err != nil { + logger.Error(err) + return nil, graphdriver.ErrNotSupported + } + fsMagic, err := graphdriver.GetFSMagic(testdir) if err != nil { return nil, err @@ -176,16 +176,6 @@ 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 { - logger.Warn("Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update") - } else { - if err := overlayutils.SupportsMultipleLowerDir(testdir); err != nil { - logger.Debugf("Multiple lower dirs not supported: %v", err) - return nil, graphdriver.ErrNotSupported - } - } - } supportsDType, err := fsutils.SupportsDType(testdir) if err != nil { return nil, err @@ -274,33 +264,6 @@ func parseOptions(options []string) (*overlayOptions, error) { return o, nil } -func supportsOverlay() error { - // Access overlay filesystem so that Linux loads it (if possible). - mountTarget, err := ioutil.TempDir("", "supportsOverlay2") - if err != nil { - logrus.WithError(err).WithField("storage-driver", "overlay2").Error("could not create temporary directory, so assuming that 'overlay' is not supported") - return graphdriver.ErrNotSupported - } - /* The mounting will fail--after the module has been loaded.*/ - defer os.RemoveAll(mountTarget) - unix.Mount("overlay", mountTarget, "overlay", 0, "") - - f, err := os.Open("/proc/filesystems") - if err != nil { - return err - } - defer f.Close() - - s := bufio.NewScanner(f) - for s.Scan() { - if s.Text() == "nodev\toverlay" { - return nil - } - } - logger.Error("'overlay' not found as a supported filesystem on this host. Please ensure kernel is new enough and has overlay support loaded.") - return graphdriver.ErrNotSupported -} - func useNaiveDiff(home string) bool { useNaiveDiffLock.Do(func() { if err := doesSupportNativeDiff(home); err != nil { diff --git a/daemon/graphdriver/overlayutils/overlayutils.go b/daemon/graphdriver/overlayutils/overlayutils.go index 3cd6b2a2a4..e0553a09f7 100644 --- a/daemon/graphdriver/overlayutils/overlayutils.go +++ b/daemon/graphdriver/overlayutils/overlayutils.go @@ -31,13 +31,13 @@ func ErrDTypeNotSupported(driver, backingFs string) error { return graphdriver.NotSupportedError(msg) } -// 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") +// SupportsOverlay checks if the system supports overlay filesystem +// by performing an actual overlay mount. +// +// checkMultipleLowers parameter enables check for multiple lowerdirs, +// which is required for the overlay2 driver. +func SupportsOverlay(d string, checkMultipleLowers bool) error { + td, err := ioutil.TempDir(d, "check-overlayfs-support") if err != nil { return err } @@ -54,7 +54,11 @@ func SupportsMultipleLowerDir(d string) error { } mnt := filepath.Join(td, "merged") - 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")) + lowerDir := path.Join(td, "lower2") + if checkMultipleLowers { + lowerDir += ":" + path.Join(td, "lower1") + } + opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, path.Join(td, "upper"), path.Join(td, "work")) if err := unix.Mount("overlay", mnt, "overlay", 0, opts); err != nil { return errors.Wrap(err, "failed to mount overlay") }