@@ -23,6 +23,7 @@ import (
23
23
"path"
24
24
"path/filepath"
25
25
"strings"
26
+ "syscall"
26
27
27
28
"github.com/golang/glog"
28
29
"k8s.io/api/core/v1"
@@ -96,29 +97,42 @@ func UnmountPath(mountPath string, mounter mount.Interface) error {
96
97
// IsNotMountPoint will be called instead of IsLikelyNotMountPoint.
97
98
// IsNotMountPoint is more expensive but properly handles bind mounts.
98
99
func UnmountMountPoint (mountPath string , mounter mount.Interface , extensiveMountPointCheck bool ) error {
99
- if pathExists , pathErr := PathExists (mountPath ); pathErr != nil {
100
- return fmt .Errorf ("Error checking if path exists: %v" , pathErr )
101
- } else if ! pathExists {
100
+ pathExists , pathErr := PathExists (mountPath )
101
+ if ! pathExists {
102
102
glog .Warningf ("Warning: Unmount skipped because path does not exist: %v" , mountPath )
103
103
return nil
104
104
}
105
-
106
- var notMnt bool
107
- var err error
108
-
109
- if extensiveMountPointCheck {
110
- notMnt , err = mount .IsNotMountPoint (mounter , mountPath )
111
- } else {
112
- notMnt , err = mounter .IsLikelyNotMountPoint (mountPath )
105
+ corruptedMnt := isCorruptedMnt (pathErr )
106
+ if pathErr != nil && ! corruptedMnt {
107
+ return fmt .Errorf ("Error checking path: %v" , pathErr )
113
108
}
109
+ return doUnmountMountPoint (mountPath , mounter , extensiveMountPointCheck , corruptedMnt )
110
+ }
114
111
115
- if err != nil {
116
- return err
117
- }
112
+ // doUnmountMountPoint is a common unmount routine that unmounts the given path and
113
+ // deletes the remaining directory if successful.
114
+ // if extensiveMountPointCheck is true
115
+ // IsNotMountPoint will be called instead of IsLikelyNotMountPoint.
116
+ // IsNotMountPoint is more expensive but properly handles bind mounts.
117
+ // if corruptedMnt is true, it means that the mountPath is a corrupted mountpoint, Take it as an argument for convenience of testing
118
+ func doUnmountMountPoint (mountPath string , mounter mount.Interface , extensiveMountPointCheck bool , corruptedMnt bool ) error {
119
+ if ! corruptedMnt {
120
+ var notMnt bool
121
+ var err error
122
+ if extensiveMountPointCheck {
123
+ notMnt , err = mount .IsNotMountPoint (mounter , mountPath )
124
+ } else {
125
+ notMnt , err = mounter .IsLikelyNotMountPoint (mountPath )
126
+ }
118
127
119
- if notMnt {
120
- glog .Warningf ("Warning: %q is not a mountpoint, deleting" , mountPath )
121
- return os .Remove (mountPath )
128
+ if err != nil {
129
+ return err
130
+ }
131
+
132
+ if notMnt {
133
+ glog .Warningf ("Warning: %q is not a mountpoint, deleting" , mountPath )
134
+ return os .Remove (mountPath )
135
+ }
122
136
}
123
137
124
138
// Unmount the mount path
@@ -128,7 +142,7 @@ func UnmountMountPoint(mountPath string, mounter mount.Interface, extensiveMount
128
142
}
129
143
notMnt , mntErr := mounter .IsLikelyNotMountPoint (mountPath )
130
144
if mntErr != nil {
131
- return err
145
+ return mntErr
132
146
}
133
147
if notMnt {
134
148
glog .V (4 ).Infof ("%q is unmounted, deleting the directory" , mountPath )
@@ -144,11 +158,32 @@ func PathExists(path string) (bool, error) {
144
158
return true , nil
145
159
} else if os .IsNotExist (err ) {
146
160
return false , nil
161
+ } else if isCorruptedMnt (err ) {
162
+ return true , err
147
163
} else {
148
164
return false , err
149
165
}
150
166
}
151
167
168
+ // isCorruptedMnt return true if err is about corrupted mount point
169
+ func isCorruptedMnt (err error ) bool {
170
+ if err == nil {
171
+ return false
172
+ }
173
+ var underlyingError error
174
+ switch pe := err .(type ) {
175
+ case nil :
176
+ return false
177
+ case * os.PathError :
178
+ underlyingError = pe .Err
179
+ case * os.LinkError :
180
+ underlyingError = pe .Err
181
+ case * os.SyscallError :
182
+ underlyingError = pe .Err
183
+ }
184
+ return underlyingError == syscall .ENOTCONN || underlyingError == syscall .ESTALE
185
+ }
186
+
152
187
// GetSecretForPod locates secret by name in the pod's namespace and returns secret map
153
188
func GetSecretForPod (pod * v1.Pod , secretName string , kubeClient clientset.Interface ) (map [string ]string , error ) {
154
189
secret := make (map [string ]string )
0 commit comments