Merge pull request #37993 from kolyshkin/ovr2-index

overlay2: use index=off if possible (fix EBUSY on mount)
This commit is contained in:
Yong Tang 2018-10-13 08:28:10 -07:00 committed by GitHub
commit ee6fc90b2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 21 deletions

View file

@ -12,7 +12,6 @@ import (
"github.com/docker/docker/pkg/system"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@ -27,7 +26,7 @@ func doesSupportNativeDiff(d string) error {
}
defer func() {
if err := os.RemoveAll(td); err != nil {
logrus.WithField("storage-driver", "overlay2").Warnf("Failed to remove check directory %v: %v", td, err)
logger.Warnf("Failed to remove check directory %v: %v", td, err)
}
}()
@ -62,7 +61,7 @@ func doesSupportNativeDiff(d string) error {
}
defer func() {
if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil {
logrus.WithField("storage-driver", "overlay2").Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
logger.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
}
}()
@ -113,7 +112,7 @@ func supportsMultipleLowerDir(d string) error {
}
defer func() {
if err := os.RemoveAll(td); err != nil {
logrus.WithField("storage-driver", "overlay2").Warnf("Failed to remove check directory %v: %v", td, err)
logger.Warnf("Failed to remove check directory %v: %v", td, err)
}
}()
@ -128,7 +127,7 @@ func supportsMultipleLowerDir(d string) error {
return errors.Wrap(err, "failed to mount overlay")
}
if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil {
logrus.WithField("storage-driver", "overlay2").Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
logger.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
}
return nil
}

View file

@ -106,11 +106,14 @@ type Driver struct {
}
var (
logger = logrus.WithField("storage-driver", "overlay2")
backingFs = "<unknown>"
projectQuotaSupported = false
useNaiveDiffLock sync.Once
useNaiveDiffOnly bool
indexOff string
)
func init() {
@ -155,8 +158,6 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
backingFs = fsName
}
logger := logrus.WithField("storage-driver", "overlay2")
switch fsMagic {
case graphdriver.FsMagicAufs, graphdriver.FsMagicEcryptfs, graphdriver.FsMagicNfsFs, graphdriver.FsMagicOverlay, graphdriver.FsMagicZfs:
logger.Errorf("'overlay2' is not supported over %s", backingFs)
@ -228,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
}
@ -277,14 +289,14 @@ func supportsOverlay() error {
return nil
}
}
logrus.WithField("storage-driver", "overlay2").Error("'overlay' not found as a supported filesystem on this host. Please ensure kernel is new enough and has overlay support loaded.")
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 {
logrus.WithField("storage-driver", "overlay2").Warnf("Not using native diff for overlay2, this may cause degraded performance for building images: %v", err)
logger.Warnf("Not using native diff for overlay2, this may cause degraded performance for building images: %v", err)
useNaiveDiffOnly = true
}
})
@ -522,9 +534,9 @@ func (d *Driver) Remove(id string) error {
lid, err := ioutil.ReadFile(path.Join(dir, "link"))
if err == nil {
if len(lid) == 0 {
logrus.WithField("storage-driver", "overlay2").Errorf("refusing to remove empty link for layer %v", id)
logger.Errorf("refusing to remove empty link for layer %v", id)
} else if err := os.RemoveAll(path.Join(d.home, linkDir, string(lid))); err != nil {
logrus.WithField("storage-driver", "overlay2").Debugf("Failed to remove link: %v", err)
logger.Debugf("Failed to remove link: %v", err)
}
}
@ -561,11 +573,11 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
if retErr != nil {
if c := d.ctr.Decrement(mergedDir); c <= 0 {
if mntErr := unix.Unmount(mergedDir, 0); mntErr != nil {
logrus.WithField("storage-driver", "overlay2").Errorf("error unmounting %v: %v", mergedDir, mntErr)
logger.Errorf("error unmounting %v: %v", mergedDir, mntErr)
}
// Cleanup the created merged directory; see the comment in Put's rmdir
if rmErr := unix.Rmdir(mergedDir); rmErr != nil && !os.IsNotExist(rmErr) {
logrus.WithField("storage-driver", "overlay2").Debugf("Failed to remove %s: %v: %v", id, rmErr, err)
logger.Debugf("Failed to remove %s: %v: %v", id, rmErr, err)
}
}
}
@ -577,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
@ -606,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))
@ -648,7 +660,6 @@ func (d *Driver) Put(id string) error {
}
mountpoint := path.Join(dir, "merged")
logger := logrus.WithField("storage-driver", "overlay2")
if count := d.ctr.Decrement(mountpoint); count > 0 {
return nil
}
@ -704,7 +715,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
applyDir := d.getDiffPath(id)
logrus.WithField("storage-driver", "overlay2").Debugf("Applying tar in %s", applyDir)
logger.Debugf("Applying tar in %s", applyDir)
// Overlay doesn't need the parent id to apply the diff
if err := untar(diff, applyDir, &archive.TarOptions{
UIDMaps: d.uidMaps,
@ -742,7 +753,7 @@ func (d *Driver) Diff(id, parent string) (io.ReadCloser, error) {
}
diffPath := d.getDiffPath(id)
logrus.WithField("storage-driver", "overlay2").Debugf("Tar with options on %s", diffPath)
logger.Debugf("Tar with options on %s", diffPath)
return archive.TarWithOptions(diffPath, &archive.TarOptions{
Compression: archive.Uncompressed,
UIDMaps: d.uidMaps,

View file

@ -11,7 +11,6 @@ import (
"syscall"
"time"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@ -47,7 +46,7 @@ func generateID(l int) string {
if retryOnError(err) && retries < maxretries {
count += n
retries++
logrus.Errorf("error generating version 4 uuid, retrying: %v", err)
logger.Errorf("error generating version 4 uuid, retrying: %v", err)
continue
}