139 lines
4.7 KiB
Diff
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
|
|
|