func findOverlayLowerdirs(opts []string) (int, []string) {
	var (
		idx    = -1
		prefix = "lowerdir="
	)
	for i, opt := range opts {
		if strings.HasPrefix(opt, prefix) {
			idx = i
			break
		}
	}
	if idx == -1 {
		return -1, nil
	}
	return idx, strings.Split(opts[idx][len(prefix):], ":")
}
findOverlayLowerdirs returns the index of lowerdir in mount's options and
all the lowerdir target.
package mount
import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"strings"
	"time"
	"github.com/containerd/containerd/sys"
	"github.com/pkg/errors"
	"golang.org/x/sys/unix"
)
var (
	pagesize              = 4096
	allowedHelperBinaries = []string{"mount.fuse", "mount.fuse3"}
)
func init() {
	pagesize = os.Getpagesize()
}
func (m *Mount) Mount(target string) (err error) {
	for _, helperBinary := range allowedHelperBinaries {
		typePrefix := strings.TrimPrefix(helperBinary, "mount.") + "."
		if strings.HasPrefix(m.Type, typePrefix) {
			return m.mountWithHelper(helperBinary, typePrefix, target)
		}
	}
	var (
		chdir   string
		options = m.Options
	)
	if m.Type == "overlay" && optionsSize(options) >= pagesize-512 {
		chdir, options = compactLowerdirOption(options)
	}
	flags, data, losetup := parseMountOptions(options)
	if len(data) > pagesize {
		return errors.Errorf("mount options is too long")
	}
	const ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE
	oflags := flags &^ ptypes
	if flags&unix.MS_REMOUNT == 0 || data != "" {
		source := m.Source
		if losetup {
			loFile, err := setupLoop(m.Source, LoopParams{
				Readonly:  oflags&unix.MS_RDONLY == unix.MS_RDONLY,
				Autoclear: true})
			if err != nil {
				return err
			}
			defer loFile.Close()
			source = loFile.Name()
		}
		if err := mountAt(chdir, source, target, m.Type, uintptr(oflags), data); err != nil {
			return err
		}
	}
	if flags&ptypes != 0 {
		const pflags = ptypes | unix.MS_REC | unix.MS_SILENT
		if err := unix.Mount("", target, "", uintptr(flags&pflags), ""); err != nil {
			return err
		}
	}
	const broflags = unix.MS_BIND | unix.MS_RDONLY
	if oflags&broflags == broflags {
		return unix.Mount("", target, "", uintptr(oflags|unix.MS_REMOUNT), "")
	}
	return nil
}
func Unmount(target string, flags int) error {
	if err := unmount(target, flags); err != nil && err != unix.EINVAL {
		return err
	}
	return nil
}
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
}
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 errors.Wrapf(unix.EBUSY, "failed to unmount target %s", target)
}
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 {
			if err == unix.EINVAL {
				return nil
			}
			return err
		}
	}
}
func parseMountOptions(options []string) (int, string, bool) {
	var (
		flag    int
		losetup bool
		data    []string
	)
	loopOpt := "loop"
	flags := map[string]struct {
		clear bool
		flag  int
	}{
		"async":         {true, unix.MS_SYNCHRONOUS},
		"atime":         {true, unix.MS_NOATIME},
		"bind":          {false, unix.MS_BIND},
		"defaults":      {false, 0},
		"dev":           {true, unix.MS_NODEV},
		"diratime":      {true, unix.MS_NODIRATIME},
		"dirsync":       {false, unix.MS_DIRSYNC},
		"exec":          {true, unix.MS_NOEXEC},
		"mand":          {false, unix.MS_MANDLOCK},
		"noatime":       {false, unix.MS_NOATIME},
		"nodev":         {false, unix.MS_NODEV},
		"nodiratime":    {false, unix.MS_NODIRATIME},
		"noexec":        {false, unix.MS_NOEXEC},
		"nomand":        {true, unix.MS_MANDLOCK},
		"norelatime":    {true, unix.MS_RELATIME},
		"nostrictatime": {true, unix.MS_STRICTATIME},
		"nosuid":        {false, unix.MS_NOSUID},
		"rbind":         {false, unix.MS_BIND | unix.MS_REC},
		"relatime":      {false, unix.MS_RELATIME},
		"remount":       {false, unix.MS_REMOUNT},
		"ro":            {false, unix.MS_RDONLY},
		"rw":            {true, unix.MS_RDONLY},
		"strictatime":   {false, unix.MS_STRICTATIME},
		"suid":          {true, unix.MS_NOSUID},
		"sync":          {false, unix.MS_SYNCHRONOUS},
	}
	for _, o := range options {
		if f, exists := flags[o]; exists && f.flag != 0 {
			if f.clear {
				flag &^= f.flag
			} else {
				flag |= f.flag
			}
		} else if o == loopOpt {
			losetup = true
		} else {
			data = append(data, o)
		}
	}
	return flag, strings.Join(data, ","), losetup
}
func compactLowerdirOption(opts []string) (string, []string) {
	idx, dirs := findOverlayLowerdirs(opts)
	if idx == -1 || len(dirs) == 1 {
		return "", opts
	}
	commondir := longestCommonPrefix(dirs)
	if commondir == "" {
		return "", opts
	}
	commondir = path.Dir(commondir)
	if commondir == "/" {
		return "", opts
	}
	commondir = commondir + "/"
	newdirs := make([]string, 0, len(dirs))
	for _, dir := range dirs {
		newdirs = append(newdirs, dir[len(commondir):])
	}
	newopts := copyOptions(opts)
	newopts = append(newopts[:idx], newopts[idx+1:]...)
	newopts = append(newopts, fmt.Sprintf("lowerdir=%s", strings.Join(newdirs, ":")))
	return commondir, newopts
}