Merge pull request #119968 from j4ckstraw/replace-stat-with-statx
Replace stat syscall with statx
This commit is contained in:
		@@ -33,6 +33,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/moby/sys/mountinfo"
 | 
						"github.com/moby/sys/mountinfo"
 | 
				
			||||||
 | 
						"golang.org/x/sys/unix"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
	utilexec "k8s.io/utils/exec"
 | 
						utilexec "k8s.io/utils/exec"
 | 
				
			||||||
@@ -55,6 +56,11 @@ const (
 | 
				
			|||||||
	errNotMounted = "not mounted"
 | 
						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
 | 
					// Mounter provides the default implementation of mount.Interface
 | 
				
			||||||
// for the linux platform.  This implementation assumes that the
 | 
					// for the linux platform.  This implementation assumes that the
 | 
				
			||||||
// kubelet is running in the host's root mount namespace.
 | 
					// kubelet is running in the host's root mount namespace.
 | 
				
			||||||
@@ -385,14 +391,20 @@ func (*Mounter) List() ([]MountPoint, error) {
 | 
				
			|||||||
	return ListProcMounts(procMountsPath)
 | 
						return ListProcMounts(procMountsPath)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
 | 
					func statx(file string) (unix.Statx_t, error) {
 | 
				
			||||||
// It is fast but not necessarily ALWAYS correct. If the path is in fact
 | 
						var stat unix.Statx_t
 | 
				
			||||||
// a bind mount from one part of a mount to another it will not be detected.
 | 
						if err := unix.Statx(0, file, unix.AT_STATX_DONT_SYNC, 0, &stat); err != nil {
 | 
				
			||||||
// It also can not distinguish between mountpoints and symbolic links.
 | 
							if err == unix.ENOSYS {
 | 
				
			||||||
// mkdir /tmp/a /tmp/b; mount --bind /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b")
 | 
								return stat, errStatxNotSupport
 | 
				
			||||||
// 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) {
 | 
							return stat, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stat, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (mounter *Mounter) isLikelyNotMountPointStat(file string) (bool, error) {
 | 
				
			||||||
	stat, err := os.Stat(file)
 | 
						stat, err := os.Stat(file)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return true, err
 | 
							return true, err
 | 
				
			||||||
@@ -409,6 +421,51 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
 | 
				
			|||||||
	return true, nil
 | 
						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.
 | 
					// CanSafelySkipMountPointCheck relies on the detected behavior of umount when given a target that is not a mount point.
 | 
				
			||||||
func (mounter *Mounter) CanSafelySkipMountPointCheck() bool {
 | 
					func (mounter *Mounter) CanSafelySkipMountPointCheck() bool {
 | 
				
			||||||
	return mounter.withSafeNotMountedBehavior
 | 
						return mounter.withSafeNotMountedBehavior
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user