mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rebase: update k8s.io/mount-utils to current master
kubernetes/kubernetes#111083 has been merged and synced into k8s.io/mount-utils. This should remove any systemd log messages while calling NodeStageVolume and NodeGetVolumeStats. Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
3c3cbc8005
commit
533994daff
22
vendor/k8s.io/mount-utils/fake_mounter.go
generated
vendored
22
vendor/k8s.io/mount-utils/fake_mounter.go
generated
vendored
@ -32,8 +32,9 @@ type FakeMounter struct {
|
||||
MountCheckErrors map[string]error
|
||||
// Some tests run things in parallel, make sure the mounter does not produce
|
||||
// any golang's DATA RACE warnings.
|
||||
mutex sync.Mutex
|
||||
UnmountFunc UnmountFunc
|
||||
mutex sync.Mutex
|
||||
UnmountFunc UnmountFunc
|
||||
skipMountPointCheck bool
|
||||
}
|
||||
|
||||
// UnmountFunc is a function callback to be executed during the Unmount() call.
|
||||
@ -64,6 +65,11 @@ func NewFakeMounter(mps []MountPoint) *FakeMounter {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FakeMounter) WithSkipMountPointCheck() *FakeMounter {
|
||||
f.skipMountPointCheck = true
|
||||
return f
|
||||
}
|
||||
|
||||
// ResetLog clears all the log entries in FakeMounter
|
||||
func (f *FakeMounter) ResetLog() {
|
||||
f.mutex.Lock()
|
||||
@ -212,6 +218,18 @@ func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) canSafelySkipMountPointCheck() bool {
|
||||
return f.skipMountPointCheck
|
||||
}
|
||||
|
||||
func (f *FakeMounter) IsMountPoint(file string) (bool, error) {
|
||||
notMnt, err := f.IsLikelyNotMountPoint(file)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !notMnt, nil
|
||||
}
|
||||
|
||||
// GetMountRefs finds all mount references to the path, returns a
|
||||
// list of paths.
|
||||
func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
|
80
vendor/k8s.io/mount-utils/mount.go
generated
vendored
80
vendor/k8s.io/mount-utils/mount.go
generated
vendored
@ -21,7 +21,6 @@ package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
@ -66,6 +65,18 @@ type Interface interface {
|
||||
// care about such situations, this is a faster alternative to calling List()
|
||||
// and scanning that output.
|
||||
IsLikelyNotMountPoint(file string) (bool, error)
|
||||
// canSafelySkipMountPointCheck indicates whether this mounter returns errors on
|
||||
// operations for targets that are not mount points. If this returns true, no such
|
||||
// errors will be returned.
|
||||
canSafelySkipMountPointCheck() bool
|
||||
// IsMountPoint determines if a directory is a mountpoint.
|
||||
// It should return ErrNotExist when the directory does not exist.
|
||||
// IsMountPoint is more expensive than IsLikelyNotMountPoint.
|
||||
// IsMountPoint detects bind mounts in linux.
|
||||
// IsMountPoint may enumerate all the mountpoints using List() and
|
||||
// the list of mountpoints may be large, then it uses
|
||||
// isMountPointMatch to evaluate whether the directory is a mountpoint.
|
||||
IsMountPoint(file string) (bool, error)
|
||||
// GetMountRefs finds all mount references to pathname, returning a slice of
|
||||
// paths. Pathname can be a mountpoint path or a normal directory
|
||||
// (for bind mount). On Linux, pathname is excluded from the slice.
|
||||
@ -187,6 +198,24 @@ func getMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
// IsNotMountPoint determines if a directory is a mountpoint.
|
||||
// It should return ErrNotExist when the directory does not exist.
|
||||
// IsNotMountPoint is more expensive than IsLikelyNotMountPoint
|
||||
// and depends on IsMountPoint.
|
||||
//
|
||||
// If an error occurs, it returns true (assuming it is not a mountpoint)
|
||||
// when ErrNotExist is returned for callers similar to IsLikelyNotMountPoint.
|
||||
//
|
||||
// Deprecated: This function is kept to keep changes backward compatible with
|
||||
// previous library version. Callers should prefer mounter.IsMountPoint.
|
||||
func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
||||
isMnt, err := mounter.IsMountPoint(file)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return !isMnt, nil
|
||||
}
|
||||
|
||||
// GetDeviceNameFromMount given a mnt point, find the device from /proc/mounts
|
||||
// returns the device name, reference count, and error code.
|
||||
func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, error) {
|
||||
@ -220,56 +249,11 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e
|
||||
return device, refCount, nil
|
||||
}
|
||||
|
||||
// IsNotMountPoint determines if a directory is a mountpoint.
|
||||
// It should return ErrNotExist when the directory does not exist.
|
||||
// IsNotMountPoint is more expensive than IsLikelyNotMountPoint.
|
||||
// IsNotMountPoint detects bind mounts in linux.
|
||||
// IsNotMountPoint enumerates all the mountpoints using List() and
|
||||
// the list of mountpoints may be large, then it uses
|
||||
// isMountPointMatch to evaluate whether the directory is a mountpoint.
|
||||
func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
||||
// IsLikelyNotMountPoint provides a quick check
|
||||
// to determine whether file IS A mountpoint.
|
||||
notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
|
||||
if notMntErr != nil && os.IsPermission(notMntErr) {
|
||||
// We were not allowed to do the simple stat() check, e.g. on NFS with
|
||||
// root_squash. Fall back to /proc/mounts check below.
|
||||
notMnt = true
|
||||
notMntErr = nil
|
||||
}
|
||||
if notMntErr != nil {
|
||||
return notMnt, notMntErr
|
||||
}
|
||||
// identified as mountpoint, so return this fact.
|
||||
if notMnt == false {
|
||||
return notMnt, nil
|
||||
}
|
||||
|
||||
// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts.
|
||||
resolvedFile, err := filepath.EvalSymlinks(file)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
// check all mountpoints since IsLikelyNotMountPoint
|
||||
// is not reliable for some mountpoint types.
|
||||
mountPoints, mountPointsErr := mounter.List()
|
||||
if mountPointsErr != nil {
|
||||
return notMnt, mountPointsErr
|
||||
}
|
||||
for _, mp := range mountPoints {
|
||||
if isMountPointMatch(mp, resolvedFile) {
|
||||
notMnt = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return notMnt, nil
|
||||
}
|
||||
|
||||
// MakeBindOpts detects whether a bind mount is being requested and makes the remount options to
|
||||
// use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
|
||||
// The list equals:
|
||||
// options - 'bind' + 'remount' (no duplicate)
|
||||
//
|
||||
// options - 'bind' + 'remount' (no duplicate)
|
||||
func MakeBindOpts(options []string) (bool, []string, []string) {
|
||||
bind, bindOpts, bindRemountOpts, _ := MakeBindOptsSensitive(options, nil /* sensitiveOptions */)
|
||||
return bind, bindOpts, bindRemountOpts
|
||||
|
66
vendor/k8s.io/mount-utils/mount_helper_common.go
generated
vendored
66
vendor/k8s.io/mount-utils/mount_helper_common.go
generated
vendored
@ -31,7 +31,7 @@ import (
|
||||
func CleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool) error {
|
||||
pathExists, pathErr := PathExists(mountPath)
|
||||
if !pathExists && pathErr == nil {
|
||||
klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath)
|
||||
klog.Warningf("Warning: mount cleanup skipped because path does not exist: %v", mountPath)
|
||||
return nil
|
||||
}
|
||||
corruptedMnt := IsCorruptedMnt(pathErr)
|
||||
@ -44,36 +44,41 @@ func CleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointC
|
||||
func CleanupMountWithForce(mountPath string, mounter MounterForceUnmounter, extensiveMountPointCheck bool, umountTimeout time.Duration) error {
|
||||
pathExists, pathErr := PathExists(mountPath)
|
||||
if !pathExists && pathErr == nil {
|
||||
klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath)
|
||||
klog.Warningf("Warning: mount cleanup skipped because path does not exist: %v", mountPath)
|
||||
return nil
|
||||
}
|
||||
corruptedMnt := IsCorruptedMnt(pathErr)
|
||||
if pathErr != nil && !corruptedMnt {
|
||||
return fmt.Errorf("Error checking path: %v", pathErr)
|
||||
}
|
||||
var notMnt bool
|
||||
var err error
|
||||
if !corruptedMnt {
|
||||
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||
// if mountPath was not a mount point - we would have attempted to remove mountPath
|
||||
// and hence return errors if any.
|
||||
if err != nil || notMnt {
|
||||
|
||||
if corruptedMnt || mounter.canSafelySkipMountPointCheck() {
|
||||
klog.V(4).Infof("unmounting %q (corruptedMount: %t, mounterCanSkipMountPointChecks: %t)",
|
||||
mountPath, corruptedMnt, mounter.canSafelySkipMountPointCheck())
|
||||
if err := mounter.UnmountWithForce(mountPath, umountTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
return removePath(mountPath)
|
||||
}
|
||||
|
||||
notMnt, err := removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||
// if mountPath is not a mount point, it's just been removed or there was an error
|
||||
if err != nil || notMnt {
|
||||
return err
|
||||
}
|
||||
|
||||
// Unmount the mount path
|
||||
klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath)
|
||||
if err := mounter.UnmountWithForce(mountPath, umountTimeout); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||
// mountPath is not a mount point we should return whatever error we saw
|
||||
// if mountPath is not a mount point, it's either just been removed or there was an error
|
||||
if notMnt {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("Failed to unmount path %v", mountPath)
|
||||
// mountPath is still a mount point
|
||||
return fmt.Errorf("failed to cleanup mount point %v", mountPath)
|
||||
}
|
||||
|
||||
// doCleanupMountPoint unmounts the given path and
|
||||
@ -82,31 +87,35 @@ func CleanupMountWithForce(mountPath string, mounter MounterForceUnmounter, exte
|
||||
// IsNotMountPoint will be called instead of IsLikelyNotMountPoint.
|
||||
// IsNotMountPoint is more expensive but properly handles bind mounts within the same fs.
|
||||
// if corruptedMnt is true, it means that the mountPath is a corrupted mountpoint, and the mount point check
|
||||
// will be skipped
|
||||
// will be skipped. The mount point check will also be skipped if the mounter supports it.
|
||||
func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool, corruptedMnt bool) error {
|
||||
var notMnt bool
|
||||
var err error
|
||||
if !corruptedMnt {
|
||||
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||
// if mountPath was not a mount point - we would have attempted to remove mountPath
|
||||
// and hence return errors if any.
|
||||
if err != nil || notMnt {
|
||||
if corruptedMnt || mounter.canSafelySkipMountPointCheck() {
|
||||
klog.V(4).Infof("unmounting %q (corruptedMount: %t, mounterCanSkipMountPointChecks: %t)",
|
||||
mountPath, corruptedMnt, mounter.canSafelySkipMountPointCheck())
|
||||
if err := mounter.Unmount(mountPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return removePath(mountPath)
|
||||
}
|
||||
|
||||
notMnt, err := removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||
// if mountPath is not a mount point, it's just been removed or there was an error
|
||||
if err != nil || notMnt {
|
||||
return err
|
||||
}
|
||||
|
||||
// Unmount the mount path
|
||||
klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath)
|
||||
if err := mounter.Unmount(mountPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||
// mountPath is not a mount point we should return whatever error we saw
|
||||
// if mountPath is not a mount point, it's either just been removed or there was an error
|
||||
if notMnt {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("Failed to unmount path %v", mountPath)
|
||||
// mountPath is still a mount point
|
||||
return fmt.Errorf("failed to cleanup mount point %v", mountPath)
|
||||
}
|
||||
|
||||
// removePathIfNotMountPoint verifies if given mountPath is a mount point if not it attempts
|
||||
@ -135,3 +144,14 @@ func removePathIfNotMountPoint(mountPath string, mounter Interface, extensiveMou
|
||||
}
|
||||
return notMnt, nil
|
||||
}
|
||||
|
||||
// removePath attempts to remove the directory. Returns nil if the directory was removed or does not exist.
|
||||
func removePath(mountPath string) error {
|
||||
klog.V(4).Infof("Warning: deleting path %q", mountPath)
|
||||
err := os.Remove(mountPath)
|
||||
if os.IsNotExist(err) {
|
||||
klog.V(4).Infof("%q does not exist", mountPath)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
149
vendor/k8s.io/mount-utils/mount_linux.go
generated
vendored
149
vendor/k8s.io/mount-utils/mount_linux.go
generated
vendored
@ -21,7 +21,11 @@ package mount
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/moby/sys/mountinfo"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -48,14 +52,18 @@ const (
|
||||
fsckErrorsUncorrected = 4
|
||||
// Error thrown by exec cmd.Run() when process spawned by cmd.Start() completes before cmd.Wait() is called (see - k/k issue #103753)
|
||||
errNoChildProcesses = "wait: no child processes"
|
||||
// Error returned by some `umount` implementations when the specified path is not a mount point
|
||||
errNotMounted = "not mounted"
|
||||
)
|
||||
|
||||
// Mounter provides the default implementation of mount.Interface
|
||||
// for the linux platform. This implementation assumes that the
|
||||
// kubelet is running in the host's root mount namespace.
|
||||
type Mounter struct {
|
||||
mounterPath string
|
||||
withSystemd bool
|
||||
mounterPath string
|
||||
withSystemd *bool
|
||||
trySystemd bool
|
||||
withSafeNotMountedBehavior bool
|
||||
}
|
||||
|
||||
var _ MounterForceUnmounter = &Mounter{}
|
||||
@ -65,11 +73,39 @@ var _ MounterForceUnmounter = &Mounter{}
|
||||
// mounterPath allows using an alternative to `/bin/mount` for mounting.
|
||||
func New(mounterPath string) Interface {
|
||||
return &Mounter{
|
||||
mounterPath: mounterPath,
|
||||
withSystemd: detectSystemd(),
|
||||
mounterPath: mounterPath,
|
||||
trySystemd: true,
|
||||
withSafeNotMountedBehavior: detectSafeNotMountedBehavior(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewWithoutSystemd returns a Linux specific mount.Interface for the current
|
||||
// system. It provides options to override the default mounter behavior.
|
||||
// mounterPath allows using an alternative to `/bin/mount` for mounting. Any
|
||||
// detection for systemd functionality is disabled with this Mounter.
|
||||
func NewWithoutSystemd(mounterPath string) Interface {
|
||||
return &Mounter{
|
||||
mounterPath: mounterPath,
|
||||
trySystemd: false,
|
||||
withSafeNotMountedBehavior: detectSafeNotMountedBehavior(),
|
||||
}
|
||||
}
|
||||
|
||||
// hasSystemd validates that the withSystemd bool is set, if it is not,
|
||||
// detectSystemd will be called once for this Mounter instance.
|
||||
func (mounter *Mounter) hasSystemd() bool {
|
||||
if !mounter.trySystemd {
|
||||
mounter.withSystemd = &mounter.trySystemd
|
||||
}
|
||||
|
||||
if mounter.withSystemd == nil {
|
||||
withSystemd := detectSystemd()
|
||||
mounter.withSystemd = &withSystemd
|
||||
}
|
||||
|
||||
return *mounter.withSystemd
|
||||
}
|
||||
|
||||
// Mount mounts source to target as fstype with given options. 'source' and 'fstype' must
|
||||
// be an empty string in case it's not required, e.g. for remount, or for auto filesystem
|
||||
// type, where kernel handles fstype for you. The mount 'options' is a list of options,
|
||||
@ -90,11 +126,11 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
||||
mounterPath := ""
|
||||
bind, bindOpts, bindRemountOpts, bindRemountOptsSensitive := MakeBindOptsSensitive(options, sensitiveOptions)
|
||||
if bind {
|
||||
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, nil /* mountFlags */, true)
|
||||
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, nil /* mountFlags */, mounter.trySystemd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, nil /* mountFlags */, true)
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, nil /* mountFlags */, mounter.trySystemd)
|
||||
}
|
||||
// The list of filesystems that require containerized mounter on GCI image cluster
|
||||
fsTypesNeedMounter := map[string]struct{}{
|
||||
@ -106,7 +142,7 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
||||
if _, ok := fsTypesNeedMounter[fstype]; ok {
|
||||
mounterPath = mounter.mounterPath
|
||||
}
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, options, sensitiveOptions, nil /* mountFlags */, true)
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, options, sensitiveOptions, nil /* mountFlags */, mounter.trySystemd)
|
||||
}
|
||||
|
||||
// MountSensitiveWithoutSystemd is the same as MountSensitive() but disable using systemd mount.
|
||||
@ -149,7 +185,7 @@ func (mounter *Mounter) doMount(mounterPath string, mountCmd string, source stri
|
||||
mountCmd = mounterPath
|
||||
}
|
||||
|
||||
if mounter.withSystemd && systemdMountRequired {
|
||||
if systemdMountRequired && mounter.hasSystemd() {
|
||||
// Try to run mount via systemd-run --scope. This will escape the
|
||||
// service where kubelet runs and any fuse daemons will be started in a
|
||||
// specific scope. kubelet service than can be restarted without killing
|
||||
@ -223,6 +259,36 @@ func detectSystemd() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// detectSafeNotMountedBehavior returns true if the umount implementation replies "not mounted"
|
||||
// when the specified path is not mounted. When not sure (permission errors, ...), it returns false.
|
||||
// When possible, we will trust umount's message and avoid doing our own mount point checks.
|
||||
// More info: https://github.com/util-linux/util-linux/blob/v2.2/mount/umount.c#L179
|
||||
func detectSafeNotMountedBehavior() bool {
|
||||
return detectSafeNotMountedBehaviorWithExec(utilexec.New())
|
||||
}
|
||||
|
||||
// detectSafeNotMountedBehaviorWithExec is for testing with FakeExec.
|
||||
func detectSafeNotMountedBehaviorWithExec(exec utilexec.Interface) bool {
|
||||
// create a temp dir and try to umount it
|
||||
path, err := ioutil.TempDir("", "kubelet-detect-safe-umount")
|
||||
if err != nil {
|
||||
klog.V(4).Infof("Cannot create temp dir to detect safe 'not mounted' behavior: %v", err)
|
||||
return false
|
||||
}
|
||||
defer os.RemoveAll(path)
|
||||
cmd := exec.Command("umount", path)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if strings.Contains(string(output), errNotMounted) {
|
||||
klog.V(4).Infof("Detected umount with safe 'not mounted' behavior")
|
||||
return true
|
||||
}
|
||||
klog.V(4).Infof("'umount %s' failed with: %v, output: %s", path, err, string(output))
|
||||
}
|
||||
klog.V(4).Infof("Detected umount with unsafe 'not mounted' behavior")
|
||||
return false
|
||||
}
|
||||
|
||||
// MakeMountArgs makes the arguments to the mount(8) command.
|
||||
// options MUST not contain sensitive material (like passwords).
|
||||
func MakeMountArgs(source, target, fstype string, options []string) (mountArgs []string) {
|
||||
@ -290,6 +356,7 @@ func AddSystemdScopeSensitive(systemdRunPath, mountName, command string, args []
|
||||
}
|
||||
|
||||
// Unmount unmounts the target.
|
||||
// If the mounter has safe "not mounted" behavior, no error will be returned when the target is not a mount point.
|
||||
func (mounter *Mounter) Unmount(target string) error {
|
||||
klog.V(4).Infof("Unmounting %s", target)
|
||||
command := exec.Command("umount", target)
|
||||
@ -303,6 +370,10 @@ func (mounter *Mounter) Unmount(target string) error {
|
||||
// Rewrite err with the actual exit error of the process.
|
||||
err = &exec.ExitError{ProcessState: command.ProcessState}
|
||||
}
|
||||
if mounter.withSafeNotMountedBehavior && strings.Contains(string(output), errNotMounted) {
|
||||
klog.V(4).Infof("ignoring 'not mounted' error for %s", target)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unmount failed: %v\nUnmounting arguments: %s\nOutput: %s", err, target, string(output))
|
||||
}
|
||||
return nil
|
||||
@ -351,6 +422,11 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// canSafelySkipMountPointCheck relies on the detected behavior of umount when given a target that is not a mount point.
|
||||
func (mounter *Mounter) canSafelySkipMountPointCheck() bool {
|
||||
return mounter.withSafeNotMountedBehavior
|
||||
}
|
||||
|
||||
// GetMountRefs finds all mount references to pathname, returns a
|
||||
// list of paths. Path could be a mountpoint or a normal
|
||||
// directory (for bind mount).
|
||||
@ -637,6 +713,63 @@ func SearchMountPoints(hostSource, mountInfoPath string) ([]string, error) {
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
// IsMountPoint determines if a file is a mountpoint.
|
||||
// It first detects bind & any other mountpoints using
|
||||
// MountedFast function. If the MountedFast function returns
|
||||
// sure as true and err as nil, then a mountpoint is detected
|
||||
// successfully. When an error is returned by MountedFast, the
|
||||
// following is true:
|
||||
// 1. All errors are returned with IsMountPoint as false
|
||||
// except os.IsPermission.
|
||||
// 2. When os.IsPermission is returned by MountedFast, List()
|
||||
// is called to confirm if the given file is a mountpoint are not.
|
||||
//
|
||||
// os.ErrNotExist should always be returned if a file does not exist
|
||||
// as callers have in past relied on this error and not fallback.
|
||||
//
|
||||
// When MountedFast returns sure as false and err as nil (eg: in
|
||||
// case of bindmounts on kernel version 5.10- ); mounter.List()
|
||||
// endpoint is called to enumerate all the mountpoints and check if
|
||||
// it is mountpoint match or not.
|
||||
func (mounter *Mounter) IsMountPoint(file string) (bool, error) {
|
||||
isMnt, sure, isMntErr := mountinfo.MountedFast(file)
|
||||
if sure && isMntErr == nil {
|
||||
return isMnt, nil
|
||||
}
|
||||
if isMntErr != nil {
|
||||
if errors.Is(isMntErr, fs.ErrNotExist) {
|
||||
return false, fs.ErrNotExist
|
||||
}
|
||||
// We were not allowed to do the simple stat() check, e.g. on NFS with
|
||||
// root_squash. Fall back to /proc/mounts check below when
|
||||
// fs.ErrPermission is returned.
|
||||
if !errors.Is(isMntErr, fs.ErrPermission) {
|
||||
return false, isMntErr
|
||||
}
|
||||
}
|
||||
// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts.
|
||||
resolvedFile, err := filepath.EvalSymlinks(file)
|
||||
if err != nil {
|
||||
if errors.Is(isMntErr, fs.ErrNotExist) {
|
||||
return false, fs.ErrNotExist
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// check all mountpoints since MountedFast is not sure.
|
||||
// is not reliable for some mountpoint types.
|
||||
mountPoints, mountPointsErr := mounter.List()
|
||||
if mountPointsErr != nil {
|
||||
return false, mountPointsErr
|
||||
}
|
||||
for _, mp := range mountPoints {
|
||||
if isMountPointMatch(mp, resolvedFile) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// tryUnmount calls plain "umount" and waits for unmountTimeout for it to finish.
|
||||
func tryUnmount(path string, unmountTimeout time.Duration) error {
|
||||
klog.V(4).Infof("Unmounting %s", path)
|
||||
|
17
vendor/k8s.io/mount-utils/mount_unsupported.go
generated
vendored
17
vendor/k8s.io/mount-utils/mount_unsupported.go
generated
vendored
@ -74,6 +74,17 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, errUnsupported
|
||||
}
|
||||
|
||||
// canSafelySkipMountPointCheck always returns false on unsupported platforms
|
||||
func (mounter *Mounter) canSafelySkipMountPointCheck() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsMountPoint determines if a directory is a mountpoint.
|
||||
// It always returns an error on unsupported platforms.
|
||||
func (mounter *Mounter) IsMountPoint(file string) (bool, error) {
|
||||
return false, errUnsupported
|
||||
}
|
||||
|
||||
// GetMountRefs always returns an error on unsupported platforms
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, errUnsupported
|
||||
@ -86,3 +97,9 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
||||
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
|
||||
return true, errUnsupported
|
||||
}
|
||||
|
||||
// IsMountPoint determines if a directory is a mountpoint.
|
||||
// It always returns an error on unsupported platforms.
|
||||
func (mounter *SafeFormatAndMount) IsMountPoint(file string) (bool, error) {
|
||||
return false, errUnsupported
|
||||
}
|
||||
|
14
vendor/k8s.io/mount-utils/mount_windows.go
generated
vendored
14
vendor/k8s.io/mount-utils/mount_windows.go
generated
vendored
@ -244,6 +244,20 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// canSafelySkipMountPointCheck always returns false on Windows
|
||||
func (mounter *Mounter) canSafelySkipMountPointCheck() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsMountPoint: determines if a directory is a mountpoint.
|
||||
func (mounter *Mounter) IsMountPoint(file string) (bool, error) {
|
||||
isNotMnt, err := mounter.IsLikelyNotMountPoint(file)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !isNotMnt, nil
|
||||
}
|
||||
|
||||
// GetMountRefs : empty implementation here since there is no place to query all mount points on Windows
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
windowsPath := NormalizeWindowsPath(pathname)
|
||||
|
5
vendor/k8s.io/mount-utils/resizefs_unsupported.go
generated
vendored
5
vendor/k8s.io/mount-utils/resizefs_unsupported.go
generated
vendored
@ -39,3 +39,8 @@ func NewResizeFs(exec utilexec.Interface) *ResizeFs {
|
||||
func (resizefs *ResizeFs) Resize(devicePath string, deviceMountPath string) (bool, error) {
|
||||
return false, fmt.Errorf("Resize is not supported for this build")
|
||||
}
|
||||
|
||||
// NeedResize check whether mounted volume needs resize
|
||||
func (resizefs *ResizeFs) NeedResize(devicePath string, deviceMountPath string) (bool, error) {
|
||||
return false, fmt.Errorf("NeedResize is not supported for this build")
|
||||
}
|
||||
|
Reference in New Issue
Block a user