@@ -92,8 +92,6 @@ const (
92
92
RundSocketDir = "/host/etc/kubernetes/volumes/rund/"
93
93
// VolumeDirRemove volume dir remove
94
94
VolumeDirRemove = "/host/etc/kubernetes/volumes/disk/remove"
95
- // InputOutputErr tag
96
- InputOutputErr = "input/output error"
97
95
// DiskMultiTenantEnable Enable disk multi-tenant mode
98
96
DiskMultiTenantEnable = "DISK_MULTI_TENANT_ENABLE"
99
97
// TenantUserUID tag
@@ -688,9 +686,44 @@ func addDiskXattr(diskID string) (err error) {
688
686
return unix .Setxattr (device , DiskXattrName , []byte (diskID ), 0 )
689
687
}
690
688
691
- // target format: /var/lib/kubelet/plugins/kubernetes.io/csi/pv/pv-disk-1e7001e0-c54a-11e9-8f89-00163e0e78a0/globalmount
689
+ func ensureUnmounted (mounter k8smount.Interface , target string ) error {
690
+ notmounted , err := mounter .IsLikelyNotMountPoint (target )
691
+ if err != nil {
692
+ return fmt .Errorf ("failed to check if %s is not a mount point after unmount: %w" , target , err )
693
+ }
694
+ if ! notmounted {
695
+ return fmt .Errorf ("path %s is still mounted after unmount" , target )
696
+ }
697
+ return nil
698
+ }
699
+
700
+ func cleanupVolumeDeviceMount (path string ) error {
701
+ err := unix .Unmount (path , 0 )
702
+ if err != nil {
703
+ switch {
704
+ case errors .Is (err , unix .ENOENT ):
705
+ return nil
706
+ case errors .Is (err , unix .EINVAL ):
707
+ // Maybe not mounted, proceed to remove it. If not, unlink will report error.
708
+ default :
709
+ return err
710
+ }
711
+ }
712
+
713
+ errUnlink := unix .Unlink (path )
714
+ if errUnlink == nil {
715
+ return nil
716
+ }
717
+ if err != nil {
718
+ return fmt .Errorf ("failed to unlink %s: %w" , path , errUnlink )
719
+ } else {
720
+ return fmt .Errorf ("failed to unmount %s: %w; then failed to unlink: %w" , path , err , errUnlink )
721
+ }
722
+ }
723
+
692
724
func (ns * nodeServer ) NodeUnstageVolume (ctx context.Context , req * csi.NodeUnstageVolumeRequest ) (* csi.NodeUnstageVolumeResponse , error ) {
693
- klog .Infof ("NodeUnstageVolume:: Starting to Unmount volume, volumeId: %s, target: %v" , req .VolumeId , req .StagingTargetPath )
725
+ logger := klog .FromContext (ctx )
726
+ logger .Info ("Starting to Unmount volume" , "target" , req .StagingTargetPath )
694
727
695
728
if ! ns .locks .TryAcquire (req .VolumeId ) {
696
729
return nil , status .Errorf (codes .Aborted , "There is already an operation for %s" , req .VolumeId )
@@ -699,66 +732,35 @@ func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstag
699
732
700
733
// check block device mountpoint
701
734
targetPath := req .GetStagingTargetPath ()
702
- tmpPath := filepath .Join (req .GetStagingTargetPath (), req .VolumeId )
703
- if IsFileExisting (tmpPath ) {
704
- fileInfo , err := os .Lstat (tmpPath )
705
- if err != nil {
706
- if strings .Contains (strings .ToLower (err .Error ()), InputOutputErr ) {
707
- if err = isPathAvailiable (targetPath ); err != nil {
708
- if err = ns .k8smounter .Unmount (targetPath ); err != nil {
709
- klog .Errorf ("NodeUnstageVolume: umount target %s(input/output error) with error: %v" , targetPath , err )
710
- return nil , status .Errorf (codes .InvalidArgument , "NodeUnstageVolume umount target %s with errror: %v" , targetPath , err )
711
- }
712
- klog .Warningf ("NodeUnstageVolume: target path %s show input/output error: %v, umount it." , targetPath , err )
713
- }
714
- } else {
715
- klog .Errorf ("NodeUnstageVolume: lstat mountpoint: %s with error: %s" , tmpPath , err .Error ())
716
- return nil , status .Error (codes .InvalidArgument , "NodeUnstageVolume: stat mountpoint error: " + err .Error ())
717
- }
718
- } else {
719
- if (fileInfo .Mode () & os .ModeDevice ) != 0 {
720
- klog .Infof ("NodeUnstageVolume: mountpoint %s, is block device" , tmpPath )
735
+ err := unix .Unmount (targetPath , 0 )
736
+ if err != nil {
737
+ switch {
738
+ case errors .Is (err , unix .ENOENT ):
739
+ logger .Info ("targetPath not exist, continue to detach" )
740
+ case errors .Is (err , unix .EINVAL ):
741
+ // Maybe unmounted, lets check
742
+ if errCheck := ensureUnmounted (ns .k8smounter , targetPath ); errCheck != nil {
743
+ return nil , status .Errorf (codes .Internal , "failed to unmount %s: %v. %v" , targetPath , err , errCheck )
721
744
}
722
- // if mountpoint not a block device, maybe something wrong happened in VolumeStageVolume.
723
- // when pod deleted, the volume should be detached
724
- targetPath = tmpPath
725
- }
726
- }
727
745
728
- // Step 1: check folder exists and umount
729
- msgLog := ""
730
- if IsFileExisting (targetPath ) {
731
- notmounted , err := ns .k8smounter .IsLikelyNotMountPoint (targetPath )
732
- if err != nil {
733
- klog .Errorf ("NodeUnstageVolume: VolumeId: %s, check mountPoint: %s error: %v" , req .VolumeId , targetPath , err )
734
- return nil , status .Error (codes .Internal , err .Error ())
735
- }
736
- if ! notmounted {
737
- err = ns .k8smounter .Unmount (targetPath )
746
+ // really umounted, check volumeDevice
747
+ // Note: we remove the blockPath, but not targetPath, because the former is created by us, while the latter is created by CO.
748
+ blockPath := filepath .Join (targetPath , req .VolumeId )
749
+ logger .Info ("targetPath may not be a mountpoint, checking volumeDevice" )
750
+ err := cleanupVolumeDeviceMount (blockPath )
738
751
if err != nil {
739
- klog .Errorf ("NodeUnstageVolume: VolumeId: %s, umount path: %s failed with: %v" , req .VolumeId , targetPath , err )
740
- return nil , status .Error (codes .Internal , err .Error ())
741
- }
742
- notmounted , err = ns .k8smounter .IsLikelyNotMountPoint (targetPath )
743
- if err != nil {
744
- return nil , status .Errorf (codes .Internal , "failed to check if %s is not a mount point after umount: %v" , targetPath , err )
752
+ return nil , status .Errorf (codes .Internal , "failed to cleanup volumeDevice path %s: %v" , blockPath , err )
745
753
}
746
- if ! notmounted {
747
- klog .Errorf ("NodeUnstageVolume: TargetPath mounted yet, volumeId: %s, Target: %s" , req .VolumeId , targetPath )
748
- return nil , status .Error (codes .Internal , "NodeUnstageVolume: TargetPath mounted yet with target" + targetPath )
749
- }
750
- } else {
751
- msgLog = fmt .Sprintf ("NodeUnstageVolume: VolumeId: %s, mountpoint: %s not mounted, skipping and continue to detach" , req .VolumeId , targetPath )
754
+ default :
755
+ return nil , status .Errorf (codes .Internal , "failed to unmount %s: %v" , targetPath , err )
752
756
}
753
757
} else {
754
- msgLog = fmt .Sprintf ("NodeUnstageVolume: VolumeId: %s, Path %s doesn't exist, continue to detach" , req .VolumeId , targetPath )
755
- }
756
-
757
- if msgLog == "" {
758
- klog .Infof ("NodeUnstageVolume: Unmount TargetPath successful, target %v, volumeId: %s" , targetPath , req .VolumeId )
759
- } else {
760
- klog .Infof (msgLog )
758
+ err := ensureUnmounted (ns .k8smounter , targetPath )
759
+ if err != nil {
760
+ return nil , status .Error (codes .Internal , err .Error ())
761
+ }
761
762
}
763
+ logger .V (2 ).Info ("targetPath cleaned up" )
762
764
763
765
if IsVFNode () {
764
766
if err := unbindBdfDisk (req .VolumeId ); err != nil {
@@ -777,7 +779,7 @@ func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstag
777
779
}
778
780
}
779
781
780
- err : = addDiskXattr (req .VolumeId )
782
+ err = addDiskXattr (req .VolumeId )
781
783
if err != nil {
782
784
klog .Errorf ("NodeUnstageVolume: addDiskXattr %s failed: %v" , req .VolumeId , err )
783
785
}
0 commit comments