diff --git a/daemon/containerd/mount.go b/daemon/containerd/mount.go index 7f9b7ca929..47e875985e 100644 --- a/daemon/containerd/mount.go +++ b/daemon/containerd/mount.go @@ -2,6 +2,7 @@ package containerd import ( "context" + "errors" "fmt" "github.com/containerd/log" @@ -30,11 +31,21 @@ func (i *ImageService) Mount(ctx context.Context, container *container.Container // Unmount unmounts the container base filesystem func (i *ImageService) Unmount(ctx context.Context, container *container.Container) error { - root := container.BaseFS + baseFS := container.BaseFS + if baseFS == "" { + target, err := i.refCountMounter.Mounted(container.ID) + if err != nil { + log.G(ctx).WithField("containerID", container.ID).Warn("failed to determine if container is already mounted") + } + if target == "" { + return errors.New("BaseFS is empty") + } + baseFS = target + } - if err := i.refCountMounter.Unmount(root); err != nil { + if err := i.refCountMounter.Unmount(baseFS); err != nil { log.G(ctx).WithField("container", container.ID).WithError(err).Error("error unmounting container") - return fmt.Errorf("failed to unmount %s: %w", root, err) + return fmt.Errorf("failed to unmount %s: %w", baseFS, err) } return nil diff --git a/daemon/snapshotter/mount.go b/daemon/snapshotter/mount.go index 0133626f51..23c74baa74 100644 --- a/daemon/snapshotter/mount.go +++ b/daemon/snapshotter/mount.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/pkg/idtools" "github.com/moby/locker" + "github.com/moby/sys/mountinfo" ) // List of known filesystems that can't be re-mounted or have shared layers @@ -22,6 +23,8 @@ type Mounter interface { Mount(mounts []mount.Mount, containerID string) (string, error) // Unmount unmounts the container rootfs Unmount(target string) error + // Mounted returns a target mountpoint if it's already mounted + Mounted(containerID string) (string, error) } // inSlice tests whether a string is contained in a slice of strings or not. @@ -110,6 +113,23 @@ func (m *refCountMounter) Unmount(target string) error { return nil } +func (m *refCountMounter) Mounted(containerID string) (string, error) { + mounted, err := m.base.Mounted(containerID) + if err != nil || mounted == "" { + return mounted, err + } + + target := m.base.target(containerID) + + // Check if the refcount is non-zero. + m.rc.Increment(target) + if m.rc.Decrement(target) > 0 { + return mounted, nil + } + + return "", nil +} + type mounter struct { home string snapshotter string @@ -137,6 +157,16 @@ func (m mounter) Unmount(target string) error { return unmount(target) } +func (m mounter) Mounted(containerID string) (string, error) { + target := m.target(containerID) + + mounted, err := mountinfo.Mounted(target) + if err != nil || !mounted { + return "", err + } + return target, nil +} + func (m mounter) target(containerID string) string { return filepath.Join(m.home, "rootfs", m.snapshotter, containerID) }