Skip to content

Commit cb89fc5

Browse files
Merge pull request #119968 from j4ckstraw/replace-stat-with-statx
Replace stat syscall with statx Kubernetes-commit: 9e0eccabb47d9044b8ec72ff27df848692b88823
2 parents 4cdb7e9 + e157130 commit cb89fc5

File tree

1 file changed

+65
-8
lines changed

1 file changed

+65
-8
lines changed

mount_linux.go

+65-8
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"time"
3434

3535
"github.com/moby/sys/mountinfo"
36+
"golang.org/x/sys/unix"
3637

3738
"k8s.io/klog/v2"
3839
utilexec "k8s.io/utils/exec"
@@ -55,6 +56,11 @@ const (
5556
errNotMounted = "not mounted"
5657
)
5758

59+
var (
60+
// Error statx support since Linux 4.11, https://man7.org/linux/man-pages/man2/statx.2.html
61+
errStatxNotSupport = errors.New("the statx syscall is not supported. At least Linux kernel 4.11 is needed")
62+
)
63+
5864
// Mounter provides the default implementation of mount.Interface
5965
// for the linux platform. This implementation assumes that the
6066
// kubelet is running in the host's root mount namespace.
@@ -385,14 +391,20 @@ func (*Mounter) List() ([]MountPoint, error) {
385391
return ListProcMounts(procMountsPath)
386392
}
387393

388-
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
389-
// It is fast but not necessarily ALWAYS correct. If the path is in fact
390-
// a bind mount from one part of a mount to another it will not be detected.
391-
// It also can not distinguish between mountpoints and symbolic links.
392-
// mkdir /tmp/a /tmp/b; mount --bind /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
393-
// will return true. When in fact /tmp/b is a mount point. If this situation
394-
// is of interest to you, don't use this function...
395-
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
394+
func statx(file string) (unix.Statx_t, error) {
395+
var stat unix.Statx_t
396+
if err := unix.Statx(0, file, unix.AT_STATX_DONT_SYNC, 0, &stat); err != nil {
397+
if err == unix.ENOSYS {
398+
return stat, errStatxNotSupport
399+
}
400+
401+
return stat, err
402+
}
403+
404+
return stat, nil
405+
}
406+
407+
func (mounter *Mounter) isLikelyNotMountPointStat(file string) (bool, error) {
396408
stat, err := os.Stat(file)
397409
if err != nil {
398410
return true, err
@@ -409,6 +421,51 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
409421
return true, nil
410422
}
411423

424+
func (mounter *Mounter) isLikelyNotMountPointStatx(file string) (bool, error) {
425+
var stat, rootStat unix.Statx_t
426+
var err error
427+
428+
if stat, err = statx(file); err != nil {
429+
return true, err
430+
}
431+
432+
if stat.Attributes_mask != 0 {
433+
if stat.Attributes_mask&unix.STATX_ATTR_MOUNT_ROOT != 0 {
434+
if stat.Attributes&unix.STATX_ATTR_MOUNT_ROOT != 0 {
435+
// file is a mountpoint
436+
return false, nil
437+
} else {
438+
// no need to check rootStat if unix.STATX_ATTR_MOUNT_ROOT supported
439+
return true, nil
440+
}
441+
}
442+
}
443+
444+
root := filepath.Dir(strings.TrimSuffix(file, "/"))
445+
if rootStat, err = statx(root); err != nil {
446+
return true, err
447+
}
448+
449+
return (stat.Dev_major == rootStat.Dev_major && stat.Dev_minor == rootStat.Dev_minor), nil
450+
}
451+
452+
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
453+
// It is fast but not necessarily ALWAYS correct. If the path is in fact
454+
// a bind mount from one part of a mount to another it will not be detected.
455+
// It also can not distinguish between mountpoints and symbolic links.
456+
// mkdir /tmp/a /tmp/b; mount --bind /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
457+
// will return true. When in fact /tmp/b is a mount point. If this situation
458+
// is of interest to you, don't use this function...
459+
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
460+
notMountPoint, err := mounter.isLikelyNotMountPointStatx(file)
461+
if errors.Is(err, errStatxNotSupport) {
462+
// fall back to isLikelyNotMountPointStat
463+
return mounter.isLikelyNotMountPointStat(file)
464+
}
465+
466+
return notMountPoint, err
467+
}
468+
412469
// CanSafelySkipMountPointCheck relies on the detected behavior of umount when given a target that is not a mount point.
413470
func (mounter *Mounter) CanSafelySkipMountPointCheck() bool {
414471
return mounter.withSafeNotMountedBehavior

0 commit comments

Comments
 (0)