Skip to content

Commit fd6e0fe

Browse files
committed
disk: re-implement StagingTargetPath cleanup logic
We should unlink the file we created for volumeDevice. We should check targetPath is not mounted before we check for volumeDevice, in case the user has a file with the same name. And the overall complexity is greatly reduced. We do not call stat() on the mounted path now, so no need to worry about EIO or similar.
1 parent 884df97 commit fd6e0fe

File tree

2 files changed

+36
-72
lines changed

2 files changed

+36
-72
lines changed

pkg/disk/nodeserver.go

Lines changed: 36 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@ const (
9494
RundSocketDir = "/host/etc/kubernetes/volumes/rund/"
9595
// VolumeDirRemove volume dir remove
9696
VolumeDirRemove = "/host/etc/kubernetes/volumes/disk/remove"
97-
// InputOutputErr tag
98-
InputOutputErr = "input/output error"
9997
// CreateDiskARN ARN parameter of the CreateDisk interface
10098
CreateDiskARN = "alibabacloud.com/createdisk-arn"
10199
// PVC annotation key of KMS key ID, override the storage class parameter kmsKeyId
@@ -692,9 +690,20 @@ func addDiskXattr(diskID string) (err error) {
692690
return unix.Setxattr(device, DiskXattrName, []byte(diskID), 0)
693691
}
694692

695-
// target format: /var/lib/kubelet/plugins/kubernetes.io/csi/pv/pv-disk-1e7001e0-c54a-11e9-8f89-00163e0e78a0/globalmount
693+
func ensureUnmounted(mounter k8smount.Interface, target string) error {
694+
notmounted, err := mounter.IsLikelyNotMountPoint(target)
695+
if err != nil {
696+
return fmt.Errorf("failed to check if %s is not a mount point after unmount: %w", target, err)
697+
}
698+
if !notmounted {
699+
return fmt.Errorf("path %s is still mounted after unmount", target)
700+
}
701+
return nil
702+
}
703+
696704
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
697-
klog.Infof("NodeUnstageVolume:: Starting to Unmount volume, volumeId: %s, target: %v", req.VolumeId, req.StagingTargetPath)
705+
logger := klog.FromContext(ctx)
706+
logger.Info("Starting to Unmount volume", "target", req.StagingTargetPath)
698707

699708
if !ns.locks.TryAcquire(req.VolumeId) {
700709
return nil, status.Errorf(codes.Aborted, "There is already an operation for %s", req.VolumeId)
@@ -703,66 +712,35 @@ func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstag
703712

704713
// check block device mountpoint
705714
targetPath := req.GetStagingTargetPath()
706-
tmpPath := filepath.Join(req.GetStagingTargetPath(), req.VolumeId)
707-
if IsFileExisting(tmpPath) {
708-
fileInfo, err := os.Lstat(tmpPath)
709-
if err != nil {
710-
if strings.Contains(strings.ToLower(err.Error()), InputOutputErr) {
711-
if err = isPathAvailable(targetPath); err != nil {
712-
if err = ns.k8smounter.Unmount(targetPath); err != nil {
713-
klog.Errorf("NodeUnstageVolume: umount target %s(input/output error) with error: %v", targetPath, err)
714-
return nil, status.Errorf(codes.InvalidArgument, "NodeUnstageVolume umount target %s with error: %v", targetPath, err)
715-
}
716-
klog.Warningf("NodeUnstageVolume: target path %s show input/output error: %v, umount it.", targetPath, err)
717-
}
718-
} else {
719-
klog.Errorf("NodeUnstageVolume: lstat mountpoint: %s with error: %s", tmpPath, err.Error())
720-
return nil, status.Error(codes.InvalidArgument, "NodeUnstageVolume: stat mountpoint error: "+err.Error())
721-
}
722-
} else {
723-
if (fileInfo.Mode() & os.ModeDevice) != 0 {
724-
klog.Infof("NodeUnstageVolume: mountpoint %s, is block device", tmpPath)
715+
err := unix.Unmount(targetPath, 0)
716+
if err != nil {
717+
switch {
718+
case errors.Is(err, unix.ENOENT):
719+
logger.Info("targetPath not exist, continue to detach")
720+
case errors.Is(err, unix.EINVAL):
721+
// Maybe unmounted, lets check
722+
if errCheck := ensureUnmounted(ns.k8smounter, targetPath); errCheck != nil {
723+
return nil, status.Errorf(codes.Internal, "failed to unmount %s: %v. %v", targetPath, err, errCheck)
725724
}
726-
// if mountpoint not a block device, maybe something wrong happened in VolumeStageVolume.
727-
// when pod deleted, the volume should be detached
728-
targetPath = tmpPath
729-
}
730-
}
731725

732-
// Step 1: check folder exists and umount
733-
msgLog := ""
734-
if IsFileExisting(targetPath) {
735-
notmounted, err := ns.k8smounter.IsLikelyNotMountPoint(targetPath)
736-
if err != nil {
737-
klog.Errorf("NodeUnstageVolume: VolumeId: %s, check mountPoint: %s error: %v", req.VolumeId, targetPath, err)
738-
return nil, status.Error(codes.Internal, err.Error())
739-
}
740-
if !notmounted {
741-
err = ns.k8smounter.Unmount(targetPath)
742-
if err != nil {
743-
klog.Errorf("NodeUnstageVolume: VolumeId: %s, umount path: %s failed with: %v", req.VolumeId, targetPath, err)
744-
return nil, status.Error(codes.Internal, err.Error())
745-
}
746-
notmounted, err = ns.k8smounter.IsLikelyNotMountPoint(targetPath)
726+
// really umounted, check volumeDevice
727+
// Note: we remove the blockPath, but not targetPath, because the former is created by us, while the latter is created by CO.
728+
blockPath := filepath.Join(targetPath, req.VolumeId)
729+
logger.Info("targetPath may not be a mountpoint, checking volumeDevice")
730+
err := utils.CleanupSimpleMount(blockPath)
747731
if err != nil {
748-
return nil, status.Errorf(codes.Internal, "failed to check if %s is not a mount point after umount: %v", targetPath, err)
732+
return nil, status.Errorf(codes.Internal, "failed to cleanup volumeDevice path %s: %v", blockPath, err)
749733
}
750-
if !notmounted {
751-
klog.Errorf("NodeUnstageVolume: TargetPath mounted yet, volumeId: %s, Target: %s", req.VolumeId, targetPath)
752-
return nil, status.Error(codes.Internal, "NodeUnstageVolume: TargetPath mounted yet with target"+targetPath)
753-
}
754-
} else {
755-
msgLog = fmt.Sprintf("NodeUnstageVolume: VolumeId: %s, mountpoint: %s not mounted, skipping and continue to detach", req.VolumeId, targetPath)
734+
default:
735+
return nil, status.Errorf(codes.Internal, "failed to unmount %s: %v", targetPath, err)
756736
}
757737
} else {
758-
msgLog = fmt.Sprintf("NodeUnstageVolume: VolumeId: %s, Path %s doesn't exist, continue to detach", req.VolumeId, targetPath)
759-
}
760-
761-
if msgLog == "" {
762-
klog.Infof("NodeUnstageVolume: Unmount TargetPath successful, target %v, volumeId: %s", targetPath, req.VolumeId)
763-
} else {
764-
klog.Info(msgLog)
738+
err := ensureUnmounted(ns.k8smounter, targetPath)
739+
if err != nil {
740+
return nil, status.Error(codes.Internal, err.Error())
741+
}
765742
}
743+
logger.V(2).Info("targetPath cleaned up")
766744

767745
if IsVFNode() {
768746
if err := unbindBdfDisk(req.VolumeId); err != nil {
@@ -781,7 +759,7 @@ func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstag
781759
}
782760
}
783761

784-
err := addDiskXattr(req.VolumeId)
762+
err = addDiskXattr(req.VolumeId)
785763
if err != nil {
786764
klog.Errorf("NodeUnstageVolume: addDiskXattr %s failed: %v", req.VolumeId, err)
787765
}

pkg/disk/utils.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -792,20 +792,6 @@ func GetVolumeDeviceName(diskID string) (string, error) {
792792
return device, err
793793
}
794794

795-
// isPathAvailable
796-
func isPathAvailable(path string) error {
797-
f, err := os.Open(path)
798-
if err != nil {
799-
return fmt.Errorf("Open Path (%s) with error: %v ", path, err)
800-
}
801-
defer f.Close()
802-
_, err = f.Readdirnames(1)
803-
if err != nil && err != io.EOF {
804-
return fmt.Errorf("Read Path (%s) with error: %v ", path, err)
805-
}
806-
return nil
807-
}
808-
809795
func getBlockDeviceCapacity(devicePath string) int64 {
810796

811797
file, err := os.Open(devicePath)

0 commit comments

Comments
 (0)