diff --git a/pkg/volume/util/hostutil/hostutil_linux.go b/pkg/volume/util/hostutil/hostutil_linux.go index 03748508ba6..3ef8d22be37 100644 --- a/pkg/volume/util/hostutil/hostutil_linux.go +++ b/pkg/volume/util/hostutil/hostutil_linux.go @@ -165,6 +165,28 @@ func (hu *HostUtil) FindMountInfo(path string) (mount.MountInfo, error) { return findMountInfo(path, procMountInfoPath) } +// FindExactMountInfo returns exact mount point that matches given path +func (hu *HostUtil) FindExactMountInfo(path string) (mount.MountInfo, error) { + infos, err := mount.ParseMountInfo(procMountInfoPath) + if err != nil { + return mount.MountInfo{}, err + } + + // process /proc/xxx/mountinfo in backward order and find the first mount + // point that is prefix of 'path' - that's the mount where path resides + var info *mount.MountInfo + for i := len(infos) - 1; i >= 0; i-- { + if path == infos[i].MountPoint { + info = &infos[i] + break + } + } + if info == nil { + return mount.MountInfo{}, fmt.Errorf("cannot find mount point for %q", path) + } + return *info, nil +} + // isShared returns true, if given path is on a mount point that has shared // mount propagation. func isShared(mount string, mountInfoPath string) (bool, error) { diff --git a/pkg/volume/util/subpath/subpath_linux.go b/pkg/volume/util/subpath/subpath_linux.go index 84661ac1c59..70a828db210 100644 --- a/pkg/volume/util/subpath/subpath_linux.go +++ b/pkg/volume/util/subpath/subpath_linux.go @@ -116,6 +116,13 @@ func prepareSubpathTarget(mounter mount.Interface, subpath Subpath) (bool, strin return false, "", fmt.Errorf("error calling findMountInfo for %s: %s", bindPathTarget, err) } if mntInfo.Root != subpath.Path { + volumeMountInfo, err := linuxHostUtil.FindExactMountInfo(subpath.VolumePath) + if err == nil && mount.PathWithinBase(subpath.Path, subpath.VolumePath) && + (volumeMountInfo.Major == mntInfo.Major && volumeMountInfo.Minor == mntInfo.Minor) { + klog.V(5).Infof("Skipping bind-mounting subpath %s, volumePath: %s, path: %s", bindPathTarget, subpath.VolumePath, subpath.Path) + return true, bindPathTarget, nil + } + // It's already mounted but not what we want, unmount it if err = mounter.Unmount(bindPathTarget); err != nil { return false, "", fmt.Errorf("error ummounting %s: %s", bindPathTarget, err)