From 09ed95db86c58da975eefd31212725e67a320be1 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 1 Oct 2020 17:23:58 +0200 Subject: [PATCH] mount: support FUSE helper When m.Type starts with either fuse. or fuse3, the mount helper binary mount.fuse or mount.fuse3 is executed. Similar to the changes made in containerd: > This is expected to be used by fuse-overlayfs plugin: https://github.com/AkihiroSuda/containerd-fuse-overlayfs > > Motivation > > The purpose of the containerd fuse-overlayfs snapshotter plugin is to provide > OverlayFS functionality for rootless mode without depending on the Ubuntu/Debian > kernel patch. > Although fuse-overlayfs provides shiftfs functionality and supports CRFS plugin, > these functionalities are not planned to be supported by the containerd fuse-overlayfs Signed-off-by: Sebastiaan van Stijn --- mount/unmount_unix.go | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/mount/unmount_unix.go b/mount/unmount_unix.go index 924d059a..c077cbef 100644 --- a/mount/unmount_unix.go +++ b/mount/unmount_unix.go @@ -2,13 +2,49 @@ package mount -import "golang.org/x/sys/unix" +import ( + "os/exec" + + "golang.org/x/sys/unix" +) func unmountBare(target string, flags int) error { return unix.Unmount(target, flags) } +// 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 + } + } err := unmountBare(target, flags) if err == nil || err == unix.EINVAL { // Ignore "not mounted" error here. Note the same error