123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- /*
- Copyright 2018 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package mount
- import (
- "fmt"
- "os"
- "k8s.io/klog"
- )
- // CleanupMountPoint unmounts the given path and
- // deletes the remaining directory if successful.
- // if extensiveMountPointCheck is true
- // IsNotMountPoint will be called instead of IsLikelyNotMountPoint.
- // IsNotMountPoint is more expensive but properly handles bind mounts within the same fs.
- func CleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool) error {
- // mounter.ExistsPath cannot be used because for containerized kubelet, we need to check
- // the path in the kubelet container, not on the host.
- pathExists, pathErr := PathExists(mountPath)
- if !pathExists {
- klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath)
- return nil
- }
- corruptedMnt := IsCorruptedMnt(pathErr)
- if pathErr != nil && !corruptedMnt {
- return fmt.Errorf("Error checking path: %v", pathErr)
- }
- return doCleanupMountPoint(mountPath, mounter, extensiveMountPointCheck, corruptedMnt)
- }
- // doCleanupMountPoint unmounts the given path and
- // deletes the remaining directory if successful.
- // if extensiveMountPointCheck is true
- // IsNotMountPoint will be called instead of IsLikelyNotMountPoint.
- // IsNotMountPoint is more expensive but properly handles bind mounts within the same fs.
- // if corruptedMnt is true, it means that the mountPath is a corrupted mountpoint, and the mount point check
- // will be skipped
- func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool, corruptedMnt bool) error {
- if !corruptedMnt {
- var notMnt bool
- var err error
- if extensiveMountPointCheck {
- notMnt, err = IsNotMountPoint(mounter, mountPath)
- } else {
- notMnt, err = mounter.IsLikelyNotMountPoint(mountPath)
- }
- if err != nil {
- return err
- }
- if notMnt {
- klog.Warningf("Warning: %q is not a mountpoint, deleting", mountPath)
- return os.Remove(mountPath)
- }
- }
- // Unmount the mount path
- klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath)
- if err := mounter.Unmount(mountPath); err != nil {
- return err
- }
- notMnt, mntErr := mounter.IsLikelyNotMountPoint(mountPath)
- if mntErr != nil {
- return mntErr
- }
- if notMnt {
- klog.V(4).Infof("%q is unmounted, deleting the directory", mountPath)
- return os.Remove(mountPath)
- }
- return fmt.Errorf("Failed to unmount path %v", mountPath)
- }
- // TODO: clean this up to use pkg/util/file/FileExists
- // PathExists returns true if the specified path exists.
- func PathExists(path string) (bool, error) {
- _, err := os.Stat(path)
- if err == nil {
- return true, nil
- } else if os.IsNotExist(err) {
- return false, nil
- } else if IsCorruptedMnt(err) {
- return true, err
- } else {
- return false, err
- }
- }
|