Revert "Add support for mounts on Darwin"
This reverts commit 2799b28e61
.
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
parent
e939d13195
commit
98f27e1d9c
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package mount
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
// fuseSuperMagic is defined in statfs(2)
|
|
||||||
const fuseSuperMagic = 0x65735546
|
|
||||||
|
|
||||||
func isFUSE(dir string) bool {
|
|
||||||
var st unix.Statfs_t
|
|
||||||
if err := unix.Statfs(dir, &st); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return st.Type == fuseSuperMagic
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmountFUSE attempts to unmount using fusermount/fusermount3 helper binary.
|
|
||||||
//
|
|
||||||
// For FUSE mounts, using these helper binaries is preferred, see:
|
|
||||||
// https://github.com/containerd/containerd/pull/3765#discussion_r342083514
|
|
||||||
func unmountFUSE(target string) error {
|
|
||||||
var err error
|
|
||||||
for _, helperBinary := range []string{"fusermount3", "fusermount"} {
|
|
||||||
cmd := exec.Command(helperBinary, "-u", target)
|
|
||||||
err = cmd.Run()
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
//go:build !linux && !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package mount
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func isFUSE(dir string) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmountFUSE is not implemented on this platform
|
|
||||||
func unmountFUSE(target string) error {
|
|
||||||
return fmt.Errorf("FUSE is not supported on this platform")
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package mount
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Mount to the provided target.
|
|
||||||
func (m *Mount) mount(target string) error {
|
|
||||||
// See https://github.com/slonopotamus/containerd-darwin-mount-helper for reference implementation
|
|
||||||
const commandName = "containerd-darwin-mount-helper"
|
|
||||||
|
|
||||||
args := []string{"-t", m.Type}
|
|
||||||
for _, option := range m.Options {
|
|
||||||
args = append(args, "-o", option)
|
|
||||||
}
|
|
||||||
args = append(args, m.Source, target)
|
|
||||||
|
|
||||||
cmd := exec.Command(commandName, args...)
|
|
||||||
output, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("%s [%v] failed: %q: %w", commandName, args, string(output), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -19,11 +19,18 @@ package mount
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
exec "golang.org/x/sys/execabs"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNotImplementOnUnix is returned for methods that are not implemented
|
||||||
|
ErrNotImplementOnUnix = errors.New("not implemented under unix")
|
||||||
|
)
|
||||||
|
|
||||||
// Mount to the provided target.
|
// Mount to the provided target.
|
||||||
//
|
//
|
||||||
// The "syscall" and "golang.org/x/sys/unix" packages do not define a Mount
|
// The "syscall" and "golang.org/x/sys/unix" packages do not define a Mount
|
||||||
@ -70,3 +77,57 @@ func (m *Mount) mount(target string) error {
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("mount [%v] failed with ECHILD (retried %d times)", args, retriesOnECHILD)
|
return fmt.Errorf("mount [%v] failed with ECHILD (retried %d times)", args, retriesOnECHILD)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unmount the provided mount path with the flags
|
||||||
|
func Unmount(target string, flags int) error {
|
||||||
|
if err := unmount(target, flags); err != nil && err != unix.EINVAL {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmount(target string, flags int) error {
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
if err := unix.Unmount(target, flags); err != nil {
|
||||||
|
switch err {
|
||||||
|
case unix.EBUSY:
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to unmount target %s: %w", target, unix.EBUSY)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmountAll repeatedly unmounts the given mount point until there
|
||||||
|
// are no mounts remaining (EINVAL is returned by mount), which is
|
||||||
|
// useful for undoing a stack of mounts on the same mount point.
|
||||||
|
// UnmountAll all is noop when the first argument is an empty string.
|
||||||
|
// This is done when the containerd client did not specify any rootfs
|
||||||
|
// mounts (e.g. because the rootfs is managed outside containerd)
|
||||||
|
// UnmountAll is noop when the mount path does not exist.
|
||||||
|
func UnmountAll(mount string, flags int) error {
|
||||||
|
if mount == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(mount); os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if err := unmount(mount, flags); err != nil {
|
||||||
|
// EINVAL is returned if the target is not a
|
||||||
|
// mount point, indicating that we are
|
||||||
|
// done. It can also indicate a few other
|
||||||
|
// things (such as invalid flags) which we
|
||||||
|
// unfortunately end up squelching here too.
|
||||||
|
if err == unix.EINVAL {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
exec "golang.org/x/sys/execabs"
|
exec "golang.org/x/sys/execabs"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
@ -119,6 +120,92 @@ func (m *Mount) mount(target string) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unmount the provided mount path with the flags
|
||||||
|
func Unmount(target string, flags int) error {
|
||||||
|
if err := unmount(target, flags); err != nil && err != unix.EINVAL {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fuseSuperMagic is defined in statfs(2)
|
||||||
|
const fuseSuperMagic = 0x65735546
|
||||||
|
|
||||||
|
func isFUSE(dir string) bool {
|
||||||
|
var st unix.Statfs_t
|
||||||
|
if err := unix.Statfs(dir, &st); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return st.Type == fuseSuperMagic
|
||||||
|
}
|
||||||
|
|
||||||
|
// unmountFUSE attempts to unmount using fusermount/fusermount3 helper binary.
|
||||||
|
//
|
||||||
|
// For FUSE mounts, using these helper binaries is preferred, see:
|
||||||
|
// https://github.com/containerd/containerd/pull/3765#discussion_r342083514
|
||||||
|
func unmountFUSE(target string) error {
|
||||||
|
var err error
|
||||||
|
for _, helperBinary := range []string{"fusermount3", "fusermount"} {
|
||||||
|
cmd := exec.Command(helperBinary, "-u", target)
|
||||||
|
err = cmd.Run()
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmount(target string, flags int) error {
|
||||||
|
if isFUSE(target) {
|
||||||
|
if err := unmountFUSE(target); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
if err := unix.Unmount(target, flags); err != nil {
|
||||||
|
switch err {
|
||||||
|
case unix.EBUSY:
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to unmount target %s: %w", target, unix.EBUSY)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmountAll repeatedly unmounts the given mount point until there
|
||||||
|
// are no mounts remaining (EINVAL is returned by mount), which is
|
||||||
|
// useful for undoing a stack of mounts on the same mount point.
|
||||||
|
// UnmountAll all is noop when the first argument is an empty string.
|
||||||
|
// This is done when the containerd client did not specify any rootfs
|
||||||
|
// mounts (e.g. because the rootfs is managed outside containerd)
|
||||||
|
// UnmountAll is noop when the mount path does not exist.
|
||||||
|
func UnmountAll(mount string, flags int) error {
|
||||||
|
if mount == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(mount); os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if err := unmount(mount, flags); err != nil {
|
||||||
|
// EINVAL is returned if the target is not a
|
||||||
|
// mount point, indicating that we are
|
||||||
|
// done. It can also indicate a few other
|
||||||
|
// things (such as invalid flags) which we
|
||||||
|
// unfortunately end up squelching here too.
|
||||||
|
if err == unix.EINVAL {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// parseMountOptions takes fstab style mount options and parses them for
|
// parseMountOptions takes fstab style mount options and parses them for
|
||||||
// use with a standard mount() syscall
|
// use with a standard mount() syscall
|
||||||
func parseMountOptions(options []string) (int, []string, bool) {
|
func parseMountOptions(options []string) (int, []string, bool) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//go:build !windows && !openbsd
|
//go:build !windows && !darwin && !openbsd
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright The containerd Authors.
|
Copyright The containerd Authors.
|
||||||
@ -19,13 +19,9 @@
|
|||||||
package mount
|
package mount
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/moby/sys/mountinfo"
|
"github.com/moby/sys/mountinfo"
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnmountRecursive unmounts the target and all mounts underneath, starting
|
// UnmountRecursive unmounts the target and all mounts underneath, starting
|
||||||
@ -63,64 +59,3 @@ func UnmountRecursive(target string, flags int) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmount(target string, flags int) error {
|
|
||||||
if isFUSE(target) {
|
|
||||||
// TODO: Why error is ignored?
|
|
||||||
// Shouldn't this just be "return unmountFUSE(target)"?
|
|
||||||
if err := unmountFUSE(target); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < 50; i++ {
|
|
||||||
if err := unix.Unmount(target, flags); err != nil {
|
|
||||||
switch err {
|
|
||||||
case unix.EBUSY:
|
|
||||||
time.Sleep(50 * time.Millisecond)
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("failed to unmount target %s: %w", target, unix.EBUSY)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmount the provided mount path with the flags
|
|
||||||
func Unmount(target string, flags int) error {
|
|
||||||
if err := unmount(target, flags); err != nil && err != unix.EINVAL {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmountAll repeatedly unmounts the given mount point until there
|
|
||||||
// are no mounts remaining (EINVAL is returned by mount), which is
|
|
||||||
// useful for undoing a stack of mounts on the same mount point.
|
|
||||||
// UnmountAll all is noop when the first argument is an empty string.
|
|
||||||
// This is done when the containerd client did not specify any rootfs
|
|
||||||
// mounts (e.g. because the rootfs is managed outside containerd)
|
|
||||||
// UnmountAll is noop when the mount path does not exist.
|
|
||||||
func UnmountAll(mount string, flags int) error {
|
|
||||||
if mount == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(mount); os.IsNotExist(err) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
if err := unmount(mount, flags); err != nil {
|
|
||||||
// EINVAL is returned if the target is not a
|
|
||||||
// mount point, indicating that we are
|
|
||||||
// done. It can also indicate a few other
|
|
||||||
// things (such as invalid flags) which we
|
|
||||||
// unfortunately end up squelching here too.
|
|
||||||
if err == unix.EINVAL {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//go:build openbsd
|
//go:build darwin || openbsd
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright The containerd Authors.
|
Copyright The containerd Authors.
|
||||||
@ -18,26 +18,29 @@
|
|||||||
|
|
||||||
package mount
|
package mount
|
||||||
|
|
||||||
import (
|
import "errors"
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
|
var (
|
||||||
|
// ErrNotImplementOnUnix is returned for methods that are not implemented
|
||||||
|
ErrNotImplementOnUnix = errors.New("not implemented under unix")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mount is not implemented on this platform
|
// Mount is not implemented on this platform
|
||||||
func (m *Mount) mount(target string) error {
|
func (m *Mount) mount(target string) error {
|
||||||
return errdefs.ErrNotImplemented
|
return ErrNotImplementOnUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmount is not implemented on this platform
|
// Unmount is not implemented on this platform
|
||||||
func Unmount(mount string, flags int) error {
|
func Unmount(mount string, flags int) error {
|
||||||
return errdefs.ErrNotImplemented
|
return ErrNotImplementOnUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmountAll is not implemented on this platform
|
// UnmountAll is not implemented on this platform
|
||||||
func UnmountAll(mount string, flags int) error {
|
func UnmountAll(mount string, flags int) error {
|
||||||
return errdefs.ErrNotImplemented
|
return ErrNotImplementOnUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmountRecursive is not implemented on this platform
|
// UnmountRecursive is not implemented on this platform
|
||||||
func UnmountRecursive(mount string, flags int) error {
|
func UnmountRecursive(mount string, flags int) error {
|
||||||
return errdefs.ErrNotImplemented
|
return ErrNotImplementOnUnix
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,11 @@ import (
|
|||||||
|
|
||||||
const sourceStreamName = "containerd.io-source"
|
const sourceStreamName = "containerd.io-source"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNotImplementOnWindows is returned when an action is not implemented for windows
|
||||||
|
ErrNotImplementOnWindows = errors.New("not implemented under windows")
|
||||||
|
)
|
||||||
|
|
||||||
// Mount to the provided target.
|
// Mount to the provided target.
|
||||||
func (m *Mount) mount(target string) (retErr error) {
|
func (m *Mount) mount(target string) (retErr error) {
|
||||||
if m.Type != "windows-layer" {
|
if m.Type != "windows-layer" {
|
||||||
|
@ -19,13 +19,12 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mount will call unix.Mount to mount the file.
|
// Mount will call unix.Mount to mount the file.
|
||||||
func (RealOS) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
func (RealOS) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
||||||
return errdefs.ErrNotImplemented
|
return mount.ErrNotImplementOnUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmount will call Unmount to unmount the file.
|
// Unmount will call Unmount to unmount the file.
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/containerd/containerd/identifiers"
|
"github.com/containerd/containerd/identifiers"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
@ -128,9 +129,11 @@ type Bundle struct {
|
|||||||
func (b *Bundle) Delete() error {
|
func (b *Bundle) Delete() error {
|
||||||
work, werr := os.Readlink(filepath.Join(b.Path, "work"))
|
work, werr := os.Readlink(filepath.Join(b.Path, "work"))
|
||||||
rootfs := filepath.Join(b.Path, "rootfs")
|
rootfs := filepath.Join(b.Path, "rootfs")
|
||||||
|
if runtime.GOOS != "darwin" {
|
||||||
if err := mount.UnmountRecursive(rootfs, 0); err != nil {
|
if err := mount.UnmountRecursive(rootfs, 0); err != nil {
|
||||||
return fmt.Errorf("unmount rootfs %s: %w", rootfs, err)
|
return fmt.Errorf("unmount rootfs %s: %w", rootfs, err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if err := os.Remove(rootfs); err != nil && !os.IsNotExist(err) {
|
if err := os.Remove(rootfs); err != nil && !os.IsNotExist(err) {
|
||||||
return fmt.Errorf("failed to remove bundle rootfs: %w", err)
|
return fmt.Errorf("failed to remove bundle rootfs: %w", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user