Skip to content

Commit 3971fb4

Browse files
j4ckstrawk8s-publishing-bot
authored andcommitted
Replace stat syscall with statx
statx with AT_STATX_DONT_SYNC will not stuck kubelet syncLoop. Signed-off-by: j4ckstraw <[email protected]> fix remove useless comment Signed-off-by: j4ckstraw <[email protected]> Kubernetes-commit: dbb6927ec229b5348f8712812a871ed9331eb0b5
1 parent 4cdb7e9 commit 3971fb4

File tree

1 file changed

+44
-17
lines changed

1 file changed

+44
-17
lines changed

mount_linux.go

+44-17
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ import (
2929
"path/filepath"
3030
"strconv"
3131
"strings"
32-
"syscall"
3332
"time"
3433

3534
"github.com/moby/sys/mountinfo"
35+
"golang.org/x/sys/unix"
3636

3737
"k8s.io/klog/v2"
3838
utilexec "k8s.io/utils/exec"
@@ -385,28 +385,55 @@ func (*Mounter) List() ([]MountPoint, error) {
385385
return ListProcMounts(procMountsPath)
386386
}
387387

388+
// statx support since Linux 4.11, glibc 2.28
389+
// refer: https://man7.org/linux/man-pages/man2/statx.2.html
390+
var errNotSupport = errors.New("The statx syscall is not supported. At least Linux kernel 4.11 is needed")
391+
392+
func statx(file string) (unix.Statx_t, error) {
393+
var stat unix.Statx_t
394+
if err := unix.Statx(0, file, unix.AT_STATX_DONT_SYNC, 0, &stat); err != nil {
395+
if err == unix.ENOSYS {
396+
return stat, errNotSupport
397+
}
398+
399+
return stat, err
400+
}
401+
402+
return stat, nil
403+
}
404+
388405
// 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.
406+
// If fast check failed, fall back to slow path. If the path is in fact
407+
// a bind mount from one part of a mount to another it will be detected.
408+
// It also can distinguish between mountpoints and symbolic links.
392409
// 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...
410+
// will return false. When in fact /tmp/b is a mount point.
411+
412+
// TODO(j4ckstraw) add test
395413
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
396-
stat, err := os.Stat(file)
397-
if err != nil {
398-
return true, err
399-
}
400-
rootStat, err := os.Stat(filepath.Dir(strings.TrimSuffix(file, "/")))
401-
if err != nil {
402-
return true, err
414+
var stat, rootStat unix.Statx_t
415+
var err error
416+
417+
if stat, err = statx(file); err != nil {
418+
if errors.Is(err, errNotSupport) {
419+
// not support statx, go slow path
420+
mnt, mntErr := mounter.IsMountPoint(file)
421+
return !mnt, mntErr
422+
}
423+
424+
return false, err
403425
}
404-
// If the directory has a different device as parent, then it is a mountpoint.
405-
if stat.Sys().(*syscall.Stat_t).Dev != rootStat.Sys().(*syscall.Stat_t).Dev {
406-
return false, nil
426+
427+
root := filepath.Dir(strings.TrimSuffix(file, "/"))
428+
if rootStat, err = statx(root); err != nil {
429+
return false, err
407430
}
408431

409-
return true, nil
432+
// TODO add STATX_ATTR_MOUNT_ROOT support, which can check mountpoint correctly.
433+
// Linux 5.8 commit 80340fe3605c0e78cfe496c3b3878be828cfdbfe
434+
// stat->attributes |= STATX_ATTR_MOUNT_ROOT;
435+
// stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
436+
return !(stat.Dev_major == rootStat.Dev_major && stat.Dev_minor == rootStat.Dev_minor), nil
410437
}
411438

412439
// CanSafelySkipMountPointCheck relies on the detected behavior of umount when given a target that is not a mount point.

0 commit comments

Comments
 (0)