docker/patch/0131-docker-fix-mount-loop-on-docker-cp.patch
2019-12-25 19:10:46 +08:00

139 lines
4.7 KiB
Diff

From cdcaf9f39ebde63ed3fce4d062224e4198589368 Mon Sep 17 00:00:00 2001
From: liuzekun <liuzekun@huawei.com>
Date: Mon, 9 Dec 2019 04:02:10 -0500
Subject: [PATCH] docker: fix mount loop on "docker cp"
reason: fix mount loop on "docker cp"
Cherry-pick from upstream: https://github.com/moby/moby/pull/38993
---
components/engine/container/container_unix.go | 9 ++++++++-
components/engine/daemon/archive.go | 15 +++++++++++++--
components/engine/daemon/volumes_unix.go | 9 +++++++++
components/engine/pkg/mount/mount.go | 5 +++++
4 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/components/engine/container/container_unix.go b/components/engine/container/container_unix.go
index 5a21b8c..43dd759 100644
--- a/components/engine/container/container_unix.go
+++ b/components/engine/container/container_unix.go
@@ -385,7 +385,14 @@ func (container *Container) DetachAndUnmount(volumeEventLog func(name, action st
logrus.Warnf("%s unmountVolumes: Failed to do lazy umount fo volume '%s': %v", container.ID, mountPath, err)
}
}
- return container.UnmountVolumes(volumeEventLog)
+ err := container.UnmountVolumes(volumeEventLog)
+ // (daemon *).mountVolumes() calls mount.MakeMountAndRUnbindable() for
+ // container root, which results in an extra bind mount, unmount it.
+ if root, err := container.GetResourcePath(""); err == nil {
+ mount.Unmount(root)
+ }
+
+ return err
}
// copyExistingContents copies from the source to the destination and
diff --git a/components/engine/daemon/archive.go b/components/engine/daemon/archive.go
index 0053e53..0bac763 100644
--- a/components/engine/daemon/archive.go
+++ b/components/engine/daemon/archive.go
@@ -12,6 +12,7 @@ import (
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/ioutils"
+ "github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/system"
"github.com/pkg/errors"
)
@@ -172,6 +173,9 @@ func (daemon *Daemon) containerStatPath(container *container.Container, path str
defer daemon.Unmount(container)
err = daemon.mountVolumes(container)
+ if err == mount.ErrMountAndRUnbindFailed {
+ return nil, err
+ }
defer container.DetachAndUnmount(daemon.LogVolumeEvent)
if err != nil {
return nil, err
@@ -208,9 +212,11 @@ func (daemon *Daemon) containerArchivePath(container *container.Container, path
}
defer func() {
- if err != nil {
+ if err != nil && err != mount.ErrMountAndRUnbindFailed {
// unmount any volumes
container.DetachAndUnmount(daemon.LogVolumeEvent)
+ }
+ if err != nil {
// unmount the container's rootfs
daemon.Unmount(container)
}
@@ -286,6 +292,9 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path
defer daemon.Unmount(container)
err = daemon.mountVolumes(container)
+ if err == mount.ErrMountAndRUnbindFailed {
+ return err
+ }
defer container.DetachAndUnmount(daemon.LogVolumeEvent)
if err != nil {
return err
@@ -410,9 +419,11 @@ func (daemon *Daemon) containerCopy(container *container.Container, resource str
}
defer func() {
- if err != nil {
+ if err != nil && err != mount.ErrMountAndRUnbindFailed {
// unmount any volumes
container.DetachAndUnmount(daemon.LogVolumeEvent)
+ }
+ if err != nil {
// unmount the container's rootfs
daemon.Unmount(container)
}
diff --git a/components/engine/daemon/volumes_unix.go b/components/engine/daemon/volumes_unix.go
index 5ddb926..e9a6d37 100644
--- a/components/engine/daemon/volumes_unix.go
+++ b/components/engine/daemon/volumes_unix.go
@@ -109,6 +109,15 @@ func setBindModeIfNull(bind *volumemounts.MountPoint) {
}
func (daemon *Daemon) mountVolumes(container *container.Container) error {
+ if root, err := container.GetResourcePath(""); err == nil {
+ err = mount.ForceMount(root, root, "none", "bind")
+ if err != nil {
+ return mount.ErrMountAndRUnbindFailed
+ } else {
+ mount.ForceMount("", root, "none", "runbindable")
+ }
+ }
+
mounts, err := daemon.setupMounts(container)
if err != nil {
return err
diff --git a/components/engine/pkg/mount/mount.go b/components/engine/pkg/mount/mount.go
index 874aff6..a784e0d 100644
--- a/components/engine/pkg/mount/mount.go
+++ b/components/engine/pkg/mount/mount.go
@@ -1,6 +1,7 @@
package mount // import "github.com/docker/docker/pkg/mount"
import (
+ "errors"
"sort"
"strings"
"syscall"
@@ -8,6 +9,10 @@ import (
"github.com/sirupsen/logrus"
)
+var (
+ ErrMountAndRUnbindFailed = errors.New("make mount and runbind failed")
+)
+
// FilterFunc is a type defining a callback function
// to filter out unwanted entries. It takes a pointer
// to an Info struct (not fully populated, currently
--
2.20.1