Merge pull request #67097 from chakri-nelluri/EIO-Unmountfix

Automatic merge from submit-queue (batch tested with PRs 67396, 67097, 67395, 67365, 67099). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Ignore EIO error in unmount path

**What this PR does / why we need it**:
This PR ignores EIO in unmount path. XFS shuts down filesystem when the target is down and it returns EIO for the stat calls used in unmount path.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #66868

**Special notes for your reviewer**:
We already handle ESTALE & ENOTCONN errors in isCorruptedMnt Call. Adding EIO to that list covers the XFS shutdown case.

Also Flexvolume doesn't check for these errors in its current form. Updated Flexvolume code to handle it.

```release-note
NONE
```
pull/8/head
Kubernetes Submit Queue 2018-08-15 05:45:17 -07:00 committed by GitHub
commit 5aea00d885
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 12 deletions

View File

@ -49,17 +49,24 @@ func (d *flexVolumeDetacher) Detach(volumeName string, hostName types.NodeName)
// UnmountDevice is part of the volume.Detacher interface.
func (d *flexVolumeDetacher) UnmountDevice(deviceMountPath string) error {
if pathExists, pathErr := util.PathExists(deviceMountPath); pathErr != nil {
return fmt.Errorf("Error checking if path exists: %v", pathErr)
} else if !pathExists {
pathExists, pathErr := util.PathExists(deviceMountPath)
if !pathExists {
glog.Warningf("Warning: Unmount skipped because path does not exist: %v", deviceMountPath)
return nil
}
if pathErr != nil && !util.IsCorruptedMnt(pathErr) {
return fmt.Errorf("Error checking path: %v", pathErr)
}
notmnt, err := isNotMounted(d.plugin.host.GetMounter(d.plugin.GetPluginName()), deviceMountPath)
if err != nil {
return err
if util.IsCorruptedMnt(err) {
notmnt = false // Corrupted error is assumed to be mounted.
} else {
return err
}
}
if notmnt {
glog.Warningf("Warning: Path: %v already unmounted", deviceMountPath)
} else {

View File

@ -44,13 +44,16 @@ func (f *flexVolumeUnmounter) TearDown() error {
func (f *flexVolumeUnmounter) TearDownAt(dir string) error {
if pathExists, pathErr := util.PathExists(dir); pathErr != nil {
return fmt.Errorf("Error checking if path exists: %v", pathErr)
} else if !pathExists {
pathExists, pathErr := util.PathExists(dir)
if !pathExists {
glog.Warningf("Warning: Unmount skipped because path does not exist: %v", dir)
return nil
}
if pathErr != nil && !util.IsCorruptedMnt(pathErr) {
return fmt.Errorf("Error checking path: %v", pathErr)
}
call := f.plugin.NewDriverCall(unmountCmd)
call.Append(dir)
_, err := call.Run()

View File

@ -143,7 +143,7 @@ func UnmountMountPoint(mountPath string, mounter mount.Interface, extensiveMount
glog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath)
return nil
}
corruptedMnt := isCorruptedMnt(pathErr)
corruptedMnt := IsCorruptedMnt(pathErr)
if pathErr != nil && !corruptedMnt {
return fmt.Errorf("Error checking path: %v", pathErr)
}
@ -199,15 +199,15 @@ func PathExists(path string) (bool, error) {
return true, nil
} else if os.IsNotExist(err) {
return false, nil
} else if isCorruptedMnt(err) {
} else if IsCorruptedMnt(err) {
return true, err
} else {
return false, err
}
}
// isCorruptedMnt return true if err is about corrupted mount point
func isCorruptedMnt(err error) bool {
// IsCorruptedMnt return true if err is about corrupted mount point
func IsCorruptedMnt(err error) bool {
if err == nil {
return false
}
@ -222,7 +222,8 @@ func isCorruptedMnt(err error) bool {
case *os.SyscallError:
underlyingError = pe.Err
}
return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE
return underlyingError == syscall.ENOTCONN || underlyingError == syscall.ESTALE || underlyingError == syscall.EIO
}
// GetSecretForPod locates secret by name in the pod's namespace and returns secret map