mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-04-11 18:13:00 +00:00
util: do not use mount-utils.IsLikelyNotMountPoint
anymore
`IsLikelyNotMountPoint()` is an optimized version for `IsMountPoint()` which can not detect all type of mounts (anymore). The slower `IsMountPoint()` is more safe to use. This can cause a slight performance regression in the case there are many mountpoints on the system, but correctness is more important than speed while mounting. Fixes: #4633 Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
parent
76b4f53897
commit
79cf0321dd
26
e2e/go.mod
26
e2e/go.mod
@ -16,6 +16,7 @@ require (
|
||||
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0
|
||||
github.com/onsi/ginkgo/v2 v2.23.0
|
||||
github.com/onsi/gomega v1.36.2
|
||||
// when updating k8s.io modules, update the 'replace' section below too
|
||||
k8s.io/api v0.32.2
|
||||
k8s.io/apimachinery v0.32.2
|
||||
k8s.io/client-go v12.0.0+incompatible
|
||||
@ -24,6 +25,18 @@ require (
|
||||
k8s.io/pod-security-admission v0.32.2
|
||||
)
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.32.2
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.2
|
||||
k8s.io/client-go => k8s.io/client-go v0.32.2
|
||||
k8s.io/cri-client => k8s.io/cri-client v0.32.2
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.2
|
||||
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.32.2
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.32.2
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.32.2
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.32.2
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.19.1 // indirect
|
||||
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab // indirect
|
||||
@ -155,18 +168,5 @@ require (
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.32.2
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.2
|
||||
k8s.io/client-go => k8s.io/client-go v0.32.2
|
||||
k8s.io/cri-client => k8s.io/cri-client v0.32.2
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.2
|
||||
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.32.2
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.32.2
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.32.2
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.32.2
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.29.3
|
||||
)
|
||||
|
||||
// version 3.9 is really old, don't use that!
|
||||
exclude github.com/openshift/api v3.9.0+incompatible
|
||||
|
@ -368,8 +368,8 @@ k8s.io/kubelet v0.32.2 h1:WFTSYdt3BB1aTApDuKNI16x/4MYqqX8WBBBBh3KupDg=
|
||||
k8s.io/kubelet v0.32.2/go.mod h1:cC1ms5RS+lu0ckVr6AviCQXHLSPKEBC3D5oaCBdTGkI=
|
||||
k8s.io/kubernetes v1.32.2 h1:mShetlA102UpjRVSGzB+5vjJwy8oPy8FMWrkTH5f37o=
|
||||
k8s.io/kubernetes v1.32.2/go.mod h1:tiIKO63GcdPRBHW2WiUFm3C0eoLczl3f7qi56Dm1W8I=
|
||||
k8s.io/mount-utils v0.29.3 h1:iEcqPP7Vv8UClH8nnMfovtmy/04fIloRW9JuSXykoZ0=
|
||||
k8s.io/mount-utils v0.29.3/go.mod h1:9IWJTMe8tG0MYMLEp60xK9GYVeCdA3g4LowmnVi+t9Y=
|
||||
k8s.io/mount-utils v0.32.2 h1:aDwp+ucWiVnDr/LpRg88/dsXf/vm6gI1VZkYH3+3+Vw=
|
||||
k8s.io/mount-utils v0.32.2/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0=
|
||||
k8s.io/pod-security-admission v0.32.2 h1:zDfAb/t0LbNU3z0ZMHtCb1zp8x05gWCGhmBYpUptm9A=
|
||||
k8s.io/pod-security-admission v0.32.2/go.mod h1:yxMPB3i1pGMLfxbe4BiWMuowMD7cdHR32y4nCj4wH+s=
|
||||
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
|
||||
|
8
e2e/vendor/k8s.io/mount-utils/mount_helper_unix.go
generated
vendored
8
e2e/vendor/k8s.io/mount-utils/mount_helper_unix.go
generated
vendored
@ -61,7 +61,13 @@ func IsCorruptedMnt(err error) bool {
|
||||
underlyingError = err
|
||||
}
|
||||
|
||||
return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO || underlyingError == syscall.EACCES || underlyingError == syscall.EHOSTDOWN || underlyingError == syscall.EWOULDBLOCK
|
||||
return errors.Is(underlyingError, syscall.ENOTCONN) ||
|
||||
errors.Is(underlyingError, syscall.ESTALE) ||
|
||||
errors.Is(underlyingError, syscall.EIO) ||
|
||||
errors.Is(underlyingError, syscall.EACCES) ||
|
||||
errors.Is(underlyingError, syscall.EHOSTDOWN) ||
|
||||
errors.Is(underlyingError, syscall.EWOULDBLOCK) ||
|
||||
errors.Is(underlyingError, syscall.ENODEV)
|
||||
}
|
||||
|
||||
// MountInfo represents a single line in /proc/<pid>/mountinfo.
|
||||
|
145
e2e/vendor/k8s.io/mount-utils/mount_linux.go
generated
vendored
145
e2e/vendor/k8s.io/mount-utils/mount_linux.go
generated
vendored
@ -33,7 +33,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/moby/sys/mountinfo"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
inuserns "github.com/moby/sys/userns"
|
||||
"k8s.io/klog/v2"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
@ -55,6 +57,11 @@ const (
|
||||
errNotMounted = "not mounted"
|
||||
)
|
||||
|
||||
var (
|
||||
// Error statx support since Linux 4.11, https://man7.org/linux/man-pages/man2/statx.2.html
|
||||
errStatxNotSupport = errors.New("the statx syscall is not supported. At least Linux kernel 4.11 is needed")
|
||||
)
|
||||
|
||||
// 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.
|
||||
@ -105,6 +112,59 @@ func (mounter *Mounter) hasSystemd() bool {
|
||||
return *mounter.withSystemd
|
||||
}
|
||||
|
||||
// Map unix.Statfs mount flags ro, nodev, noexec, nosuid, noatime, relatime,
|
||||
// nodiratime to mount option flag strings.
|
||||
func getUserNSBindMountOptions(path string, statfs func(path string, buf *unix.Statfs_t) (err error)) ([]string, error) {
|
||||
var s unix.Statfs_t
|
||||
var mountOpts []string
|
||||
if err := statfs(path, &s); err != nil {
|
||||
return nil, &os.PathError{Op: "statfs", Path: path, Err: err}
|
||||
}
|
||||
flagMapping := map[int]string{
|
||||
unix.MS_RDONLY: "ro",
|
||||
unix.MS_NODEV: "nodev",
|
||||
unix.MS_NOEXEC: "noexec",
|
||||
unix.MS_NOSUID: "nosuid",
|
||||
unix.MS_NOATIME: "noatime",
|
||||
unix.MS_RELATIME: "relatime",
|
||||
unix.MS_NODIRATIME: "nodiratime",
|
||||
}
|
||||
for k, v := range flagMapping {
|
||||
if int(s.Flags)&k == k {
|
||||
mountOpts = append(mountOpts, v)
|
||||
}
|
||||
}
|
||||
return mountOpts, nil
|
||||
}
|
||||
|
||||
// Do a bind mount including the needed remount for applying the bind opts.
|
||||
// If the remount fails and we are running in a user namespace
|
||||
// figure out if the source filesystem has the ro, nodev, noexec, nosuid,
|
||||
// noatime, relatime or nodiratime flag set and try another remount with the found flags.
|
||||
func (mounter *Mounter) bindMountSensitive(mounterPath string, mountCmd string, source string, target string, fstype string, bindOpts []string, bindRemountOpts []string, bindRemountOptsSensitive []string, mountFlags []string, systemdMountRequired bool) error {
|
||||
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
|
||||
if inuserns.RunningInUserNS() {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
// Check if the source has ro, nodev, noexec, nosuid, noatime, relatime,
|
||||
// nodiratime flag...
|
||||
fixMountOpts, err := getUserNSBindMountOptions(source, unix.Statfs)
|
||||
if err != nil {
|
||||
return &os.PathError{Op: "statfs", Path: source, Err: err}
|
||||
}
|
||||
// ... and retry the mount with flags found above.
|
||||
bindRemountOpts = append(bindRemountOpts, fixMountOpts...)
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 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,
|
||||
@ -125,11 +185,7 @@ 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 */, mounter.trySystemd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, nil /* mountFlags */, mounter.trySystemd)
|
||||
return mounter.bindMountSensitive(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOpts, bindRemountOptsSensitive, nil /* mountFlags */, mounter.trySystemd)
|
||||
}
|
||||
// The list of filesystems that require containerized mounter on GCI image cluster
|
||||
fsTypesNeedMounter := map[string]struct{}{
|
||||
@ -154,11 +210,7 @@ func (mounter *Mounter) MountSensitiveWithoutSystemdWithMountFlags(source string
|
||||
mounterPath := ""
|
||||
bind, bindOpts, bindRemountOpts, bindRemountOptsSensitive := MakeBindOptsSensitive(options, sensitiveOptions)
|
||||
if bind {
|
||||
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, mountFlags, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, false)
|
||||
return mounter.bindMountSensitive(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOpts, bindRemountOptsSensitive, mountFlags, false)
|
||||
}
|
||||
// The list of filesystems that require containerized mounter on GCI image cluster
|
||||
fsTypesNeedMounter := map[string]struct{}{
|
||||
@ -385,14 +437,20 @@ func (*Mounter) List() ([]MountPoint, error) {
|
||||
return ListProcMounts(procMountsPath)
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
|
||||
// It is fast but not necessarily ALWAYS correct. If the path is in fact
|
||||
// a bind mount from one part of a mount to another it will not be detected.
|
||||
// It also can not distinguish between mountpoints and symbolic links.
|
||||
// mkdir /tmp/a /tmp/b; mount --bind /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
|
||||
// will return true. When in fact /tmp/b is a mount point. If this situation
|
||||
// is of interest to you, don't use this function...
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
func statx(file string) (unix.Statx_t, error) {
|
||||
var stat unix.Statx_t
|
||||
if err := unix.Statx(unix.AT_FDCWD, file, unix.AT_STATX_DONT_SYNC, 0, &stat); err != nil {
|
||||
if err == unix.ENOSYS {
|
||||
return stat, errStatxNotSupport
|
||||
}
|
||||
|
||||
return stat, err
|
||||
}
|
||||
|
||||
return stat, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) isLikelyNotMountPointStat(file string) (bool, error) {
|
||||
stat, err := os.Stat(file)
|
||||
if err != nil {
|
||||
return true, err
|
||||
@ -409,6 +467,51 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) isLikelyNotMountPointStatx(file string) (bool, error) {
|
||||
var stat, rootStat unix.Statx_t
|
||||
var err error
|
||||
|
||||
if stat, err = statx(file); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
if stat.Attributes_mask != 0 {
|
||||
if stat.Attributes_mask&unix.STATX_ATTR_MOUNT_ROOT != 0 {
|
||||
if stat.Attributes&unix.STATX_ATTR_MOUNT_ROOT != 0 {
|
||||
// file is a mountpoint
|
||||
return false, nil
|
||||
} else {
|
||||
// no need to check rootStat if unix.STATX_ATTR_MOUNT_ROOT supported
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root := filepath.Dir(strings.TrimSuffix(file, "/"))
|
||||
if rootStat, err = statx(root); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
return (stat.Dev_major == rootStat.Dev_major && stat.Dev_minor == rootStat.Dev_minor), nil
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
|
||||
// It is fast but not necessarily ALWAYS correct. If the path is in fact
|
||||
// a bind mount from one part of a mount to another it will not be detected.
|
||||
// It also can not distinguish between mountpoints and symbolic links.
|
||||
// mkdir /tmp/a /tmp/b; mount --bind /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
|
||||
// will return true. When in fact /tmp/b is a mount point. If this situation
|
||||
// is of interest to you, don't use this function...
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
notMountPoint, err := mounter.isLikelyNotMountPointStatx(file)
|
||||
if errors.Is(err, errStatxNotSupport) {
|
||||
// fall back to isLikelyNotMountPointStat
|
||||
return mounter.isLikelyNotMountPointStat(file)
|
||||
}
|
||||
|
||||
return notMountPoint, err
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -520,7 +623,7 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
||||
sensitiveOptionsLog := sanitizedOptionsForLogging(options, sensitiveOptions)
|
||||
detailedErr := fmt.Sprintf("format of disk %q failed: type:(%q) target:(%q) options:(%q) errcode:(%v) output:(%v) ", source, fstype, target, sensitiveOptionsLog, err, string(output))
|
||||
klog.Error(detailedErr)
|
||||
return NewMountError(FormatFailed, detailedErr)
|
||||
return NewMountError(FormatFailed, "%s", detailedErr)
|
||||
}
|
||||
|
||||
klog.Infof("Disk successfully formatted (mkfs): %s - %s %s", fstype, source, target)
|
||||
@ -528,7 +631,7 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
||||
if fstype != existingFormat {
|
||||
// Verify that the disk is formatted with filesystem type we are expecting
|
||||
mountErrorValue = FilesystemMismatch
|
||||
klog.Warningf("Configured to mount disk %s as %s but current format is %s, things might break", source, existingFormat, fstype)
|
||||
klog.Warningf("Configured to mount disk %s as %s but current format is %s, things might break", source, fstype, existingFormat)
|
||||
}
|
||||
|
||||
if !readOnly {
|
||||
@ -543,7 +646,7 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
||||
// Mount the disk
|
||||
klog.V(4).Infof("Attempting to mount disk %s in %s format at %s", source, fstype, target)
|
||||
if err := mounter.MountSensitive(source, target, fstype, options, sensitiveOptions); err != nil {
|
||||
return NewMountError(mountErrorValue, err.Error())
|
||||
return NewMountError(mountErrorValue, "%s", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
6
e2e/vendor/k8s.io/mount-utils/mount_windows.go
generated
vendored
6
e2e/vendor/k8s.io/mount-utils/mount_windows.go
generated
vendored
@ -164,7 +164,7 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
||||
// return (output, error)
|
||||
func newSMBMapping(username, password, remotepath string) (string, error) {
|
||||
if username == "" || password == "" || remotepath == "" {
|
||||
return "", fmt.Errorf("invalid parameter(username: %s, password: %s, remoteapth: %s)", username, sensitiveOptionsRemoved, remotepath)
|
||||
return "", fmt.Errorf("invalid parameter(username: %s, password: %s, remotepath: %s)", username, sensitiveOptionsRemoved, remotepath)
|
||||
}
|
||||
|
||||
// use PowerShell Environment Variables to store user input string to prevent command line injection
|
||||
@ -193,8 +193,8 @@ func isSMBMappingExist(remotepath string) bool {
|
||||
// check whether remotepath is valid
|
||||
// return (true, nil) if remotepath is valid
|
||||
func isValidPath(remotepath string) (bool, error) {
|
||||
cmd := exec.Command("powershell", "/c", `Test-Path $Env:remoteapth`)
|
||||
cmd.Env = append(os.Environ(), fmt.Sprintf("remoteapth=%s", remotepath))
|
||||
cmd := exec.Command("powershell", "/c", `Test-Path $Env:remotepath`)
|
||||
cmd.Env = append(os.Environ(), fmt.Sprintf("remotepath=%s", remotepath))
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("returned output: %s, error: %v", string(output), err)
|
||||
|
5
e2e/vendor/modules.txt
vendored
5
e2e/vendor/modules.txt
vendored
@ -1648,8 +1648,8 @@ k8s.io/kubernetes/test/utils/kubeconfig
|
||||
k8s.io/kubernetes/third_party/forked/golang/expansion
|
||||
k8s.io/kubernetes/third_party/forked/libcontainer/apparmor
|
||||
k8s.io/kubernetes/third_party/forked/libcontainer/utils
|
||||
# k8s.io/mount-utils v0.32.2 => k8s.io/mount-utils v0.29.3
|
||||
## explicit; go 1.21
|
||||
# k8s.io/mount-utils v0.32.2
|
||||
## explicit; go 1.23.0
|
||||
k8s.io/mount-utils
|
||||
# k8s.io/pod-security-admission v0.32.2
|
||||
## explicit; go 1.23.0
|
||||
@ -1708,4 +1708,3 @@ sigs.k8s.io/yaml/goyaml.v2
|
||||
# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.32.2
|
||||
# k8s.io/kubectl => k8s.io/kubectl v0.32.2
|
||||
# k8s.io/kubelet => k8s.io/kubelet v0.32.2
|
||||
# k8s.io/mount-utils => k8s.io/mount-utils v0.29.3
|
||||
|
7
go.mod
7
go.mod
@ -39,6 +39,7 @@ require (
|
||||
k8s.io/cloud-provider v0.32.2
|
||||
k8s.io/klog/v2 v2.130.1
|
||||
k8s.io/kubernetes v1.32.2
|
||||
k8s.io/mount-utils v0.32.2
|
||||
k8s.io/utils v0.0.0-20241210054802-24370beab758
|
||||
)
|
||||
|
||||
@ -50,11 +51,6 @@ require (
|
||||
|
||||
replace k8s.io/client-go => k8s.io/client-go v0.32.2
|
||||
|
||||
// TODO: replaced by v0.29.3 until https://github.com/ceph/ceph-csi/issues/4633 is fixed
|
||||
require k8s.io/mount-utils v0.32.2
|
||||
|
||||
replace k8s.io/mount-utils => k8s.io/mount-utils v0.29.3
|
||||
|
||||
exclude (
|
||||
// missing tag, referred to by github.com/hashicorp/go-kms-wrapping@v0.5.1
|
||||
github.com/hashicorp/vault/sdk v0.1.14-0.20191229212425-c478d00be0d6
|
||||
@ -126,6 +122,7 @@ require (
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
|
13
go.sum
13
go.sum
@ -120,8 +120,6 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 h1:PZV5W8yk4OtH1JAuhV2PXwwO9v5G5Aoj+eMCn4T+1Kc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
|
||||
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
||||
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
|
||||
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
@ -136,10 +134,6 @@ github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/ceph/go-ceph v0.32.0 h1:iXRUGdPmH7h9Vf/WA1Dg3Wo1tgL7gcUbylfpbxrlGLs=
|
||||
github.com/ceph/go-ceph v0.32.0/go.mod h1:42eoJzyLS3VREzqrg2ot44NtuluQZi55hFRSoLF36GQ=
|
||||
github.com/ceph/go-ceph v0.32.1-0.20250303071035-7740b94e7f49 h1:0q5Ye65vYS5szvVsH5VILBGTv80p6v+znzPHsjiheDg=
|
||||
github.com/ceph/go-ceph v0.32.1-0.20250303071035-7740b94e7f49/go.mod h1:FtN9DMlp/aS7VuO0VXdpdFfaetHNwtvn5q8gIhW/hQ4=
|
||||
github.com/ceph/go-ceph v0.32.1-0.20250307053135-38b9676b1d4e h1:Ykum5wAFYzyUi+yW0qQFDsbP9pAuRKTOf+ttMoo1jZ4=
|
||||
github.com/ceph/go-ceph v0.32.1-0.20250307053135-38b9676b1d4e/go.mod h1:bIS41nqhGmD7gQVoSBu3IYCwCiVEMeIxFU5qaqmC4a8=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
@ -511,6 +505,8 @@ github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0Gq
|
||||
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -731,6 +727,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
@ -1383,8 +1380,8 @@ k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8X
|
||||
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
|
||||
k8s.io/kubernetes v1.32.2 h1:mShetlA102UpjRVSGzB+5vjJwy8oPy8FMWrkTH5f37o=
|
||||
k8s.io/kubernetes v1.32.2/go.mod h1:tiIKO63GcdPRBHW2WiUFm3C0eoLczl3f7qi56Dm1W8I=
|
||||
k8s.io/mount-utils v0.29.3 h1:iEcqPP7Vv8UClH8nnMfovtmy/04fIloRW9JuSXykoZ0=
|
||||
k8s.io/mount-utils v0.29.3/go.mod h1:9IWJTMe8tG0MYMLEp60xK9GYVeCdA3g4LowmnVi+t9Y=
|
||||
k8s.io/mount-utils v0.32.2 h1:aDwp+ucWiVnDr/LpRg88/dsXf/vm6gI1VZkYH3+3+Vw=
|
||||
k8s.io/mount-utils v0.32.2/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0=
|
||||
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
|
@ -47,7 +47,7 @@ func (ms mountState) String() string {
|
||||
}
|
||||
|
||||
func (ns *NodeServer) getMountState(path string) (mountState, error) {
|
||||
isMnt, err := util.IsMountPoint(ns.Mounter, path)
|
||||
isMnt, err := ns.Mounter.IsMountPoint(path)
|
||||
if err != nil {
|
||||
if util.IsCorruptedMountError(err) {
|
||||
return msCorrupted, nil
|
||||
|
@ -263,7 +263,7 @@ func (ns *NodeServer) NodeStageVolume(
|
||||
}
|
||||
}
|
||||
|
||||
isMnt, err := util.IsMountPoint(ns.Mounter, stagingTargetPath)
|
||||
isMnt, err := ns.Mounter.IsMountPoint(stagingTargetPath)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, "stat failed: %v", err)
|
||||
|
||||
@ -539,7 +539,7 @@ func (ns *NodeServer) NodePublishVolume(
|
||||
|
||||
// Ensure staging target path is a mountpoint.
|
||||
|
||||
isMnt, err := util.IsMountPoint(ns.Mounter, stagingTargetPath)
|
||||
isMnt, err := ns.Mounter.IsMountPoint(stagingTargetPath)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, "stat failed: %v", err)
|
||||
|
||||
@ -552,7 +552,7 @@ func (ns *NodeServer) NodePublishVolume(
|
||||
|
||||
// Check if the volume is already mounted
|
||||
|
||||
isMnt, err = util.IsMountPoint(ns.Mounter, targetPath)
|
||||
isMnt, err = ns.Mounter.IsMountPoint(targetPath)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, "stat failed: %v", err)
|
||||
|
||||
@ -615,7 +615,7 @@ func (ns *NodeServer) NodeUnpublishVolume(
|
||||
// stop the health-checker that may have been started in NodeGetVolumeStats()
|
||||
ns.healthChecker.StopChecker(volID, targetPath)
|
||||
|
||||
isMnt, err := util.IsMountPoint(ns.Mounter, targetPath)
|
||||
isMnt, err := ns.Mounter.IsMountPoint(targetPath)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, "stat failed: %v", err)
|
||||
|
||||
@ -687,7 +687,7 @@ func (ns *NodeServer) NodeUnstageVolume(
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
isMnt, err := util.IsMountPoint(ns.Mounter, stagingTargetPath)
|
||||
isMnt, err := ns.Mounter.IsMountPoint(stagingTargetPath)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, "stat failed: %v", err)
|
||||
|
||||
|
@ -25,7 +25,6 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ceph/ceph-csi/internal/util"
|
||||
"github.com/ceph/ceph-csi/internal/util/log"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
@ -351,7 +350,7 @@ func FilesystemNodeGetVolumeStats(
|
||||
targetPath string,
|
||||
includeInodes bool,
|
||||
) (*csi.NodeGetVolumeStatsResponse, error) {
|
||||
isMnt, err := util.IsMountPoint(mounter, targetPath)
|
||||
isMnt, err := mounter.IsMountPoint(targetPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "targetpath %s does not exist", targetPath)
|
||||
|
@ -200,19 +200,19 @@ func (ns *NodeServer) mountNFS(
|
||||
err error
|
||||
)
|
||||
|
||||
notMnt, err := ns.Mounter.IsLikelyNotMountPoint(mountPoint)
|
||||
isMnt, err := ns.Mounter.IsMountPoint(mountPoint)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = os.MkdirAll(mountPoint, defaultMountPermission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
notMnt = true
|
||||
isMnt = false
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !notMnt {
|
||||
if isMnt {
|
||||
log.DebugLog(ctx, "nfs: volume is already mounted to %s", mountPoint)
|
||||
|
||||
return nil
|
||||
|
@ -880,9 +880,9 @@ func (ns *NodeServer) mountVolume(ctx context.Context, stagingPath string, req *
|
||||
|
||||
func (ns *NodeServer) createTargetMountPath(ctx context.Context, mountPath string, isBlock bool) (bool, error) {
|
||||
// Check if that mount path exists properly
|
||||
notMnt, err := ns.Mounter.IsLikelyNotMountPoint(mountPath)
|
||||
isMnt, err := ns.Mounter.IsMountPoint(mountPath)
|
||||
if err == nil {
|
||||
return notMnt, nil
|
||||
return !isMnt, nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return false, status.Error(codes.Internal, err.Error())
|
||||
@ -893,22 +893,22 @@ func (ns *NodeServer) createTargetMountPath(ctx context.Context, mountPath strin
|
||||
if e != nil {
|
||||
log.DebugLog(ctx, "Failed to create mountPath:%s with error: %v", mountPath, err)
|
||||
|
||||
return notMnt, status.Error(codes.Internal, e.Error())
|
||||
return !isMnt, status.Error(codes.Internal, e.Error())
|
||||
}
|
||||
if err = pathFile.Close(); err != nil {
|
||||
log.DebugLog(ctx, "Failed to close mountPath:%s with error: %v", mountPath, err)
|
||||
|
||||
return notMnt, status.Error(codes.Internal, err.Error())
|
||||
return !isMnt, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
} else {
|
||||
// Create a mountpath directory
|
||||
if err = util.CreateMountPoint(mountPath); err != nil {
|
||||
return notMnt, status.Error(codes.Internal, err.Error())
|
||||
return !isMnt, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
}
|
||||
notMnt = true
|
||||
isMnt = false
|
||||
|
||||
return notMnt, err
|
||||
return !isMnt, err
|
||||
}
|
||||
|
||||
// NodeUnpublishVolume unmounts the volume from the target path.
|
||||
|
@ -219,16 +219,6 @@ func checkDirExists(p string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsMountPoint checks if the given path is mountpoint or not.
|
||||
func IsMountPoint(mounter mount.Interface, p string) (bool, error) {
|
||||
notMnt, err := mounter.IsLikelyNotMountPoint(p)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return !notMnt, nil
|
||||
}
|
||||
|
||||
// IsCorruptedMountError checks if the given error is a result of a corrupted
|
||||
// mountpoint.
|
||||
func IsCorruptedMountError(err error) bool {
|
||||
|
202
vendor/github.com/moby/sys/userns/LICENSE
generated
vendored
Normal file
202
vendor/github.com/moby/sys/userns/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
16
vendor/github.com/moby/sys/userns/userns.go
generated
vendored
Normal file
16
vendor/github.com/moby/sys/userns/userns.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// Package userns provides utilities to detect whether we are currently running
|
||||
// in a Linux user namespace.
|
||||
//
|
||||
// This code was migrated from [libcontainer/runc], which based its implementation
|
||||
// on code from [lcx/incus].
|
||||
//
|
||||
// [libcontainer/runc]: https://github.com/opencontainers/runc/blob/3778ae603c706494fd1e2c2faf83b406e38d687d/libcontainer/userns/userns_linux.go#L12-L49
|
||||
// [lcx/incus]: https://github.com/lxc/incus/blob/e45085dd42f826b3c8c3228e9733c0b6f998eafe/shared/util.go#L678-L700
|
||||
package userns
|
||||
|
||||
// RunningInUserNS detects whether we are currently running in a Linux
|
||||
// user namespace and memoizes the result. It returns false on non-Linux
|
||||
// platforms.
|
||||
func RunningInUserNS() bool {
|
||||
return inUserNS()
|
||||
}
|
53
vendor/github.com/moby/sys/userns/userns_linux.go
generated
vendored
Normal file
53
vendor/github.com/moby/sys/userns/userns_linux.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
package userns
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var inUserNS = sync.OnceValue(runningInUserNS)
|
||||
|
||||
// runningInUserNS detects whether we are currently running in a user namespace.
|
||||
//
|
||||
// This code was migrated from [libcontainer/runc] and based on an implementation
|
||||
// from [lcx/incus].
|
||||
//
|
||||
// [libcontainer/runc]: https://github.com/opencontainers/runc/blob/3778ae603c706494fd1e2c2faf83b406e38d687d/libcontainer/userns/userns_linux.go#L12-L49
|
||||
// [lcx/incus]: https://github.com/lxc/incus/blob/e45085dd42f826b3c8c3228e9733c0b6f998eafe/shared/util.go#L678-L700
|
||||
func runningInUserNS() bool {
|
||||
file, err := os.Open("/proc/self/uid_map")
|
||||
if err != nil {
|
||||
// This kernel-provided file only exists if user namespaces are supported.
|
||||
return false
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
buf := bufio.NewReader(file)
|
||||
l, _, err := buf.ReadLine()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return uidMapInUserNS(string(l))
|
||||
}
|
||||
|
||||
func uidMapInUserNS(uidMap string) bool {
|
||||
if uidMap == "" {
|
||||
// File exist but empty (the initial state when userns is created,
|
||||
// see user_namespaces(7)).
|
||||
return true
|
||||
}
|
||||
|
||||
var a, b, c int64
|
||||
if _, err := fmt.Sscanf(uidMap, "%d %d %d", &a, &b, &c); err != nil {
|
||||
// Assume we are in a regular, non user namespace.
|
||||
return false
|
||||
}
|
||||
|
||||
// As per user_namespaces(7), /proc/self/uid_map of
|
||||
// the initial user namespace shows 0 0 4294967295.
|
||||
initNS := a == 0 && b == 0 && c == 4294967295
|
||||
return !initNS
|
||||
}
|
8
vendor/github.com/moby/sys/userns/userns_linux_fuzzer.go
generated
vendored
Normal file
8
vendor/github.com/moby/sys/userns/userns_linux_fuzzer.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build linux && gofuzz
|
||||
|
||||
package userns
|
||||
|
||||
func FuzzUIDMap(uidmap []byte) int {
|
||||
_ = uidMapInUserNS(string(uidmap))
|
||||
return 1
|
||||
}
|
6
vendor/github.com/moby/sys/userns/userns_unsupported.go
generated
vendored
Normal file
6
vendor/github.com/moby/sys/userns/userns_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
//go:build !linux
|
||||
|
||||
package userns
|
||||
|
||||
// inUserNS is a stub for non-Linux systems. Always returns false.
|
||||
func inUserNS() bool { return false }
|
8
vendor/k8s.io/mount-utils/mount_helper_unix.go
generated
vendored
8
vendor/k8s.io/mount-utils/mount_helper_unix.go
generated
vendored
@ -61,7 +61,13 @@ func IsCorruptedMnt(err error) bool {
|
||||
underlyingError = err
|
||||
}
|
||||
|
||||
return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO || underlyingError == syscall.EACCES || underlyingError == syscall.EHOSTDOWN || underlyingError == syscall.EWOULDBLOCK
|
||||
return errors.Is(underlyingError, syscall.ENOTCONN) ||
|
||||
errors.Is(underlyingError, syscall.ESTALE) ||
|
||||
errors.Is(underlyingError, syscall.EIO) ||
|
||||
errors.Is(underlyingError, syscall.EACCES) ||
|
||||
errors.Is(underlyingError, syscall.EHOSTDOWN) ||
|
||||
errors.Is(underlyingError, syscall.EWOULDBLOCK) ||
|
||||
errors.Is(underlyingError, syscall.ENODEV)
|
||||
}
|
||||
|
||||
// MountInfo represents a single line in /proc/<pid>/mountinfo.
|
||||
|
145
vendor/k8s.io/mount-utils/mount_linux.go
generated
vendored
145
vendor/k8s.io/mount-utils/mount_linux.go
generated
vendored
@ -33,7 +33,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/moby/sys/mountinfo"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
inuserns "github.com/moby/sys/userns"
|
||||
"k8s.io/klog/v2"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
@ -55,6 +57,11 @@ const (
|
||||
errNotMounted = "not mounted"
|
||||
)
|
||||
|
||||
var (
|
||||
// Error statx support since Linux 4.11, https://man7.org/linux/man-pages/man2/statx.2.html
|
||||
errStatxNotSupport = errors.New("the statx syscall is not supported. At least Linux kernel 4.11 is needed")
|
||||
)
|
||||
|
||||
// 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.
|
||||
@ -105,6 +112,59 @@ func (mounter *Mounter) hasSystemd() bool {
|
||||
return *mounter.withSystemd
|
||||
}
|
||||
|
||||
// Map unix.Statfs mount flags ro, nodev, noexec, nosuid, noatime, relatime,
|
||||
// nodiratime to mount option flag strings.
|
||||
func getUserNSBindMountOptions(path string, statfs func(path string, buf *unix.Statfs_t) (err error)) ([]string, error) {
|
||||
var s unix.Statfs_t
|
||||
var mountOpts []string
|
||||
if err := statfs(path, &s); err != nil {
|
||||
return nil, &os.PathError{Op: "statfs", Path: path, Err: err}
|
||||
}
|
||||
flagMapping := map[int]string{
|
||||
unix.MS_RDONLY: "ro",
|
||||
unix.MS_NODEV: "nodev",
|
||||
unix.MS_NOEXEC: "noexec",
|
||||
unix.MS_NOSUID: "nosuid",
|
||||
unix.MS_NOATIME: "noatime",
|
||||
unix.MS_RELATIME: "relatime",
|
||||
unix.MS_NODIRATIME: "nodiratime",
|
||||
}
|
||||
for k, v := range flagMapping {
|
||||
if int(s.Flags)&k == k {
|
||||
mountOpts = append(mountOpts, v)
|
||||
}
|
||||
}
|
||||
return mountOpts, nil
|
||||
}
|
||||
|
||||
// Do a bind mount including the needed remount for applying the bind opts.
|
||||
// If the remount fails and we are running in a user namespace
|
||||
// figure out if the source filesystem has the ro, nodev, noexec, nosuid,
|
||||
// noatime, relatime or nodiratime flag set and try another remount with the found flags.
|
||||
func (mounter *Mounter) bindMountSensitive(mounterPath string, mountCmd string, source string, target string, fstype string, bindOpts []string, bindRemountOpts []string, bindRemountOptsSensitive []string, mountFlags []string, systemdMountRequired bool) error {
|
||||
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
|
||||
if inuserns.RunningInUserNS() {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
// Check if the source has ro, nodev, noexec, nosuid, noatime, relatime,
|
||||
// nodiratime flag...
|
||||
fixMountOpts, err := getUserNSBindMountOptions(source, unix.Statfs)
|
||||
if err != nil {
|
||||
return &os.PathError{Op: "statfs", Path: source, Err: err}
|
||||
}
|
||||
// ... and retry the mount with flags found above.
|
||||
bindRemountOpts = append(bindRemountOpts, fixMountOpts...)
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 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,
|
||||
@ -125,11 +185,7 @@ 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 */, mounter.trySystemd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, nil /* mountFlags */, mounter.trySystemd)
|
||||
return mounter.bindMountSensitive(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOpts, bindRemountOptsSensitive, nil /* mountFlags */, mounter.trySystemd)
|
||||
}
|
||||
// The list of filesystems that require containerized mounter on GCI image cluster
|
||||
fsTypesNeedMounter := map[string]struct{}{
|
||||
@ -154,11 +210,7 @@ func (mounter *Mounter) MountSensitiveWithoutSystemdWithMountFlags(source string
|
||||
mounterPath := ""
|
||||
bind, bindOpts, bindRemountOpts, bindRemountOptsSensitive := MakeBindOptsSensitive(options, sensitiveOptions)
|
||||
if bind {
|
||||
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, mountFlags, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, false)
|
||||
return mounter.bindMountSensitive(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOpts, bindRemountOptsSensitive, mountFlags, false)
|
||||
}
|
||||
// The list of filesystems that require containerized mounter on GCI image cluster
|
||||
fsTypesNeedMounter := map[string]struct{}{
|
||||
@ -385,14 +437,20 @@ func (*Mounter) List() ([]MountPoint, error) {
|
||||
return ListProcMounts(procMountsPath)
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
|
||||
// It is fast but not necessarily ALWAYS correct. If the path is in fact
|
||||
// a bind mount from one part of a mount to another it will not be detected.
|
||||
// It also can not distinguish between mountpoints and symbolic links.
|
||||
// mkdir /tmp/a /tmp/b; mount --bind /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
|
||||
// will return true. When in fact /tmp/b is a mount point. If this situation
|
||||
// is of interest to you, don't use this function...
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
func statx(file string) (unix.Statx_t, error) {
|
||||
var stat unix.Statx_t
|
||||
if err := unix.Statx(unix.AT_FDCWD, file, unix.AT_STATX_DONT_SYNC, 0, &stat); err != nil {
|
||||
if err == unix.ENOSYS {
|
||||
return stat, errStatxNotSupport
|
||||
}
|
||||
|
||||
return stat, err
|
||||
}
|
||||
|
||||
return stat, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) isLikelyNotMountPointStat(file string) (bool, error) {
|
||||
stat, err := os.Stat(file)
|
||||
if err != nil {
|
||||
return true, err
|
||||
@ -409,6 +467,51 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) isLikelyNotMountPointStatx(file string) (bool, error) {
|
||||
var stat, rootStat unix.Statx_t
|
||||
var err error
|
||||
|
||||
if stat, err = statx(file); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
if stat.Attributes_mask != 0 {
|
||||
if stat.Attributes_mask&unix.STATX_ATTR_MOUNT_ROOT != 0 {
|
||||
if stat.Attributes&unix.STATX_ATTR_MOUNT_ROOT != 0 {
|
||||
// file is a mountpoint
|
||||
return false, nil
|
||||
} else {
|
||||
// no need to check rootStat if unix.STATX_ATTR_MOUNT_ROOT supported
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root := filepath.Dir(strings.TrimSuffix(file, "/"))
|
||||
if rootStat, err = statx(root); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
return (stat.Dev_major == rootStat.Dev_major && stat.Dev_minor == rootStat.Dev_minor), nil
|
||||
}
|
||||
|
||||
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
|
||||
// It is fast but not necessarily ALWAYS correct. If the path is in fact
|
||||
// a bind mount from one part of a mount to another it will not be detected.
|
||||
// It also can not distinguish between mountpoints and symbolic links.
|
||||
// mkdir /tmp/a /tmp/b; mount --bind /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
|
||||
// will return true. When in fact /tmp/b is a mount point. If this situation
|
||||
// is of interest to you, don't use this function...
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
notMountPoint, err := mounter.isLikelyNotMountPointStatx(file)
|
||||
if errors.Is(err, errStatxNotSupport) {
|
||||
// fall back to isLikelyNotMountPointStat
|
||||
return mounter.isLikelyNotMountPointStat(file)
|
||||
}
|
||||
|
||||
return notMountPoint, err
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -520,7 +623,7 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
||||
sensitiveOptionsLog := sanitizedOptionsForLogging(options, sensitiveOptions)
|
||||
detailedErr := fmt.Sprintf("format of disk %q failed: type:(%q) target:(%q) options:(%q) errcode:(%v) output:(%v) ", source, fstype, target, sensitiveOptionsLog, err, string(output))
|
||||
klog.Error(detailedErr)
|
||||
return NewMountError(FormatFailed, detailedErr)
|
||||
return NewMountError(FormatFailed, "%s", detailedErr)
|
||||
}
|
||||
|
||||
klog.Infof("Disk successfully formatted (mkfs): %s - %s %s", fstype, source, target)
|
||||
@ -528,7 +631,7 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
||||
if fstype != existingFormat {
|
||||
// Verify that the disk is formatted with filesystem type we are expecting
|
||||
mountErrorValue = FilesystemMismatch
|
||||
klog.Warningf("Configured to mount disk %s as %s but current format is %s, things might break", source, existingFormat, fstype)
|
||||
klog.Warningf("Configured to mount disk %s as %s but current format is %s, things might break", source, fstype, existingFormat)
|
||||
}
|
||||
|
||||
if !readOnly {
|
||||
@ -543,7 +646,7 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
||||
// Mount the disk
|
||||
klog.V(4).Infof("Attempting to mount disk %s in %s format at %s", source, fstype, target)
|
||||
if err := mounter.MountSensitive(source, target, fstype, options, sensitiveOptions); err != nil {
|
||||
return NewMountError(mountErrorValue, err.Error())
|
||||
return NewMountError(mountErrorValue, "%s", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
6
vendor/k8s.io/mount-utils/mount_windows.go
generated
vendored
6
vendor/k8s.io/mount-utils/mount_windows.go
generated
vendored
@ -164,7 +164,7 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
||||
// return (output, error)
|
||||
func newSMBMapping(username, password, remotepath string) (string, error) {
|
||||
if username == "" || password == "" || remotepath == "" {
|
||||
return "", fmt.Errorf("invalid parameter(username: %s, password: %s, remoteapth: %s)", username, sensitiveOptionsRemoved, remotepath)
|
||||
return "", fmt.Errorf("invalid parameter(username: %s, password: %s, remotepath: %s)", username, sensitiveOptionsRemoved, remotepath)
|
||||
}
|
||||
|
||||
// use PowerShell Environment Variables to store user input string to prevent command line injection
|
||||
@ -193,8 +193,8 @@ func isSMBMappingExist(remotepath string) bool {
|
||||
// check whether remotepath is valid
|
||||
// return (true, nil) if remotepath is valid
|
||||
func isValidPath(remotepath string) (bool, error) {
|
||||
cmd := exec.Command("powershell", "/c", `Test-Path $Env:remoteapth`)
|
||||
cmd.Env = append(os.Environ(), fmt.Sprintf("remoteapth=%s", remotepath))
|
||||
cmd := exec.Command("powershell", "/c", `Test-Path $Env:remotepath`)
|
||||
cmd.Env = append(os.Environ(), fmt.Sprintf("remotepath=%s", remotepath))
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("returned output: %s, error: %v", string(output), err)
|
||||
|
8
vendor/modules.txt
vendored
8
vendor/modules.txt
vendored
@ -432,6 +432,9 @@ github.com/mitchellh/mapstructure
|
||||
# github.com/moby/sys/mountinfo v0.7.2
|
||||
## explicit; go 1.17
|
||||
github.com/moby/sys/mountinfo
|
||||
# github.com/moby/sys/userns v0.1.0
|
||||
## explicit; go 1.21
|
||||
github.com/moby/sys/userns
|
||||
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
|
||||
## explicit
|
||||
github.com/modern-go/concurrent
|
||||
@ -1167,8 +1170,8 @@ k8s.io/kubernetes/pkg/volume/util/hostutil
|
||||
k8s.io/kubernetes/pkg/volume/util/recyclerclient
|
||||
k8s.io/kubernetes/pkg/volume/util/subpath
|
||||
k8s.io/kubernetes/pkg/volume/util/types
|
||||
# k8s.io/mount-utils v0.32.2 => k8s.io/mount-utils v0.29.3
|
||||
## explicit; go 1.21
|
||||
# k8s.io/mount-utils v0.32.2
|
||||
## explicit; go 1.23.0
|
||||
k8s.io/mount-utils
|
||||
# k8s.io/utils v0.0.0-20241210054802-24370beab758
|
||||
## explicit; go 1.18
|
||||
@ -1244,4 +1247,3 @@ sigs.k8s.io/yaml
|
||||
sigs.k8s.io/yaml/goyaml.v2
|
||||
# github.com/ceph/ceph-csi/api => ./api
|
||||
# k8s.io/client-go => k8s.io/client-go v0.32.2
|
||||
# k8s.io/mount-utils => k8s.io/mount-utils v0.29.3
|
||||
|
Loading…
Reference in New Issue
Block a user