From 45d21ee36b1a49e3b86d99810a7875b7496da30a Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Mon, 8 Jan 2018 14:01:33 +0100 Subject: [PATCH] Fixed TearDown of NFS with root squash. NFS plugin should not use IsLikelyNotMountPoint(), as it uses lstat() / stat() to determine if the NFS volume is still mounted - NFS server may use root_squash and kubelet may not be allowed to do lstat() / stat() there. It must use slower IsNotMountPoint() instead, including TearDown() function. --- pkg/util/mount/mount.go | 7 +++++++ pkg/volume/nfs/nfs.go | 11 +++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/pkg/util/mount/mount.go b/pkg/util/mount/mount.go index 953b571900a79..d2069ec7861b7 100644 --- a/pkg/util/mount/mount.go +++ b/pkg/util/mount/mount.go @@ -19,6 +19,7 @@ limitations under the License. package mount import ( + "os" "path/filepath" ) @@ -208,6 +209,12 @@ func IsNotMountPoint(mounter Interface, file string) (bool, error) { // IsLikelyNotMountPoint provides a quick check // to determine whether file IS A mountpoint notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file) + if notMntErr != nil && os.IsPermission(notMntErr) { + // We were not allowed to do the simple stat() check, e.g. on NFS with + // root_squash. Fall back to /proc/mounts check below. + notMnt = true + notMntErr = nil + } if notMntErr != nil { return notMnt, notMntErr } diff --git a/pkg/volume/nfs/nfs.go b/pkg/volume/nfs/nfs.go index f61fbd259444b..26db61d729ad8 100644 --- a/pkg/volume/nfs/nfs.go +++ b/pkg/volume/nfs/nfs.go @@ -233,7 +233,7 @@ func (b *nfsMounter) SetUp(fsGroup *int64) error { } func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { - notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) + notMnt, err := b.mounter.IsNotMountPoint(dir) glog.V(4).Infof("NFS mount set up: %s %v %v", dir, !notMnt, err) if err != nil && !os.IsNotExist(err) { return err @@ -252,7 +252,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { mountOptions := volume.JoinMountOptions(b.mountOptions, options) err = b.mounter.Mount(source, dir, "nfs", mountOptions) if err != nil { - notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir) + notMnt, mntErr := b.mounter.IsNotMountPoint(dir) if mntErr != nil { glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) return err @@ -262,7 +262,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Failed to unmount: %v", mntErr) return err } - notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir) + notMnt, mntErr := b.mounter.IsNotMountPoint(dir) if mntErr != nil { glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) return err @@ -290,7 +290,10 @@ func (c *nfsUnmounter) TearDown() error { } func (c *nfsUnmounter) TearDownAt(dir string) error { - return util.UnmountPath(dir, c.mounter) + // Use extensiveMountPointCheck to consult /proc/mounts. We can't use faster + // IsLikelyNotMountPoint (lstat()), since there may be root_squash on the + // NFS server and kubelet may not be able to do lstat/stat() there. + return util.UnmountMountPoint(dir, c.mounter, true /* extensiveMountPointCheck */) } func getVolumeSource(spec *volume.Spec) (*v1.NFSVolumeSource, bool, error) {