@@ -17,6 +17,7 @@ limitations under the License.
1717package smb
1818
1919import (
20+ "bufio"
2021 "encoding/base64"
2122 "fmt"
2223 "os"
@@ -40,7 +41,6 @@ import (
4041 azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
4142)
4243
43- // NodePublishVolume mount the volume from staging to target path
4444func (d * Driver ) NodePublishVolume (ctx context.Context , req * csi.NodePublishVolumeRequest ) (* csi.NodePublishVolumeResponse , error ) {
4545 volCap := req .GetVolumeCapability ()
4646 if volCap == nil {
@@ -51,27 +51,31 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
5151 return nil , status .Error (codes .InvalidArgument , "Volume ID missing in request" )
5252 }
5353
54- target := req .GetTargetPath ()
55- if len (target ) == 0 {
54+ // Strip cred hash suffix if present
55+ cleanID := strings .SplitN (volumeID , "#cred=" , 2 )[0 ]
56+
57+ targetPath := req .GetTargetPath ()
58+ if len (targetPath ) == 0 {
5659 return nil , status .Error (codes .InvalidArgument , "Target path not provided" )
5760 }
5861
5962 context := req .GetVolumeContext ()
6063 if context != nil && strings .EqualFold (context [ephemeralField ], trueValue ) {
6164 // ephemeral volume
6265 util .SetKeyValueInMap (context , secretNamespaceField , context [podNamespaceField ])
63- klog .V (2 ).Infof ("NodePublishVolume: ephemeral volume(%s) mount on %s" , volumeID , target )
66+ klog .V (2 ).Infof ("NodePublishVolume: ephemeral volume(%s) mount on %s" , volumeID , targetPath )
6467 _ , err := d .NodeStageVolume (ctx , & csi.NodeStageVolumeRequest {
65- StagingTargetPath : target ,
68+ StagingTargetPath : targetPath ,
6669 VolumeContext : context ,
6770 VolumeCapability : volCap ,
68- VolumeId : volumeID ,
71+ VolumeId : cleanID ,
6972 })
7073 return & csi.NodePublishVolumeResponse {}, err
7174 }
7275
73- source := req .GetStagingTargetPath ()
74- if len (source ) == 0 {
76+ // Get staging path
77+ stagingPath := req .GetStagingTargetPath ()
78+ if len (stagingPath ) == 0 {
7579 return nil , status .Error (codes .InvalidArgument , "Staging target not provided" )
7680 }
7781
@@ -80,31 +84,31 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
8084 mountOptions = append (mountOptions , "ro" )
8185 }
8286
83- mnt , err := d .ensureMountPoint (target )
87+ mnt , err := d .ensureMountPoint (targetPath )
8488 if err != nil {
85- return nil , status .Errorf (codes .Internal , "Could not mount target %q: %v" , target , err )
89+ return nil , status .Errorf (codes .Internal , "Could not mount target %q: %v" , targetPath , err )
8690 }
8791 if mnt {
88- klog .V (2 ).Infof ("NodePublishVolume: %s is already mounted" , target )
92+ klog .V (2 ).Infof ("NodePublishVolume: %s is already mounted" , targetPath )
8993 return & csi.NodePublishVolumeResponse {}, nil
9094 }
9195
92- if err = preparePublishPath (target , d .mounter ); err != nil {
93- return nil , fmt .Errorf ("prepare publish failed for %s with error: %v" , target , err )
96+ if err = preparePublishPath (targetPath , d .mounter ); err != nil {
97+ return nil , fmt .Errorf ("prepare publish failed for %s with error: %v" , targetPath , err )
9498 }
9599
96- klog .V (2 ).Infof ("NodePublishVolume: mounting %s at %s with mountOptions : %v volumeID(%s) " , source , target , mountOptions , volumeID )
97- if err := d .mounter .Mount (source , target , "" , mountOptions ); err != nil {
98- if removeErr := os .Remove (target ); removeErr != nil {
99- return nil , status .Errorf (codes .Internal , "Could not remove mount target %q: %v" , target , removeErr )
100+ klog .V (2 ).Infof ("NodePublishVolume: bind mounting %s to %s with options : %v" , stagingPath , targetPath , mountOptions )
101+ if err := d .mounter .Mount (stagingPath , targetPath , "" , mountOptions ); err != nil {
102+ if removeErr := os .Remove (targetPath ); removeErr != nil {
103+ return nil , status .Errorf (codes .Internal , "Could not remove mount target %q: %v" , targetPath , removeErr )
100104 }
101- return nil , status .Errorf (codes .Internal , "Could not mount %q at %q: %v" , source , target , err )
105+ return nil , status .Errorf (codes .Internal , "Could not mount %q at %q: %v" , stagingPath , targetPath , err )
102106 }
103- klog .V (2 ).Infof ("NodePublishVolume: mount %s at %s volumeID(%s) successfully" , source , target , volumeID )
107+
108+ klog .V (2 ).Infof ("NodePublishVolume: mount %s at %s volumeID(%s) successfully" , stagingPath , targetPath , volumeID )
104109 return & csi.NodePublishVolumeResponse {}, nil
105110}
106111
107- // NodeUnpublishVolume unmount the volume from the target path
108112func (d * Driver ) NodeUnpublishVolume (_ context.Context , req * csi.NodeUnpublishVolumeRequest ) (* csi.NodeUnpublishVolumeResponse , error ) {
109113 volumeID := req .GetVolumeId ()
110114 if len (volumeID ) == 0 {
@@ -115,12 +119,28 @@ func (d *Driver) NodeUnpublishVolume(_ context.Context, req *csi.NodeUnpublishVo
115119 return nil , status .Error (codes .InvalidArgument , "Target path missing in request" )
116120 }
117121
118- klog .V (2 ).Infof ("NodeUnpublishVolume: unmounting volume %s on %s" , volumeID , targetPath )
119- err := CleanupMountPoint (d .mounter , targetPath , true /*extensiveMountPointCheck*/ )
120- if err != nil {
122+ klog .V (2 ).Infof ("NodeUnpublishVolume: unmounting volume %s from %s" , volumeID , targetPath )
123+
124+ notMnt , err := d .mounter .IsLikelyNotMountPoint (targetPath )
125+ if err != nil && ! os .IsNotExist (err ) {
126+ return nil , status .Errorf (codes .Internal , "failed to check mount point %q: %v" , targetPath , err )
127+ }
128+ if notMnt {
129+ klog .V (2 ).Infof ("NodeUnpublishVolume: target %s is already unmounted" , targetPath )
130+ if err := os .Remove (targetPath ); err != nil && ! os .IsNotExist (err ) {
131+ return nil , status .Errorf (codes .Internal , "failed to remove target path %q: %v" , targetPath , err )
132+ }
133+ return & csi.NodeUnpublishVolumeResponse {}, nil
134+ }
135+
136+ if err := d .mounter .Unmount (targetPath ); err != nil {
121137 return nil , status .Errorf (codes .Internal , "failed to unmount target %q: %v" , targetPath , err )
122138 }
123- klog .V (2 ).Infof ("NodeUnpublishVolume: unmount volume %s on %s successfully" , volumeID , targetPath )
139+ if err := os .Remove (targetPath ); err != nil && ! os .IsNotExist (err ) {
140+ return nil , status .Errorf (codes .Internal , "failed to remove target path %q after unmount: %v" , targetPath , err )
141+ }
142+
143+ klog .V (2 ).Infof ("NodeUnpublishVolume: successfully unmounted and removed %s for volume %s" , targetPath , volumeID )
124144 return & csi.NodeUnpublishVolumeResponse {}, nil
125145}
126146
@@ -142,8 +162,8 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
142162 }
143163
144164 context := req .GetVolumeContext ()
145- mountFlags := req . GetVolumeCapability () .GetMount ().GetMountFlags ()
146- volumeMountGroup := req . GetVolumeCapability () .GetMount ().GetVolumeMountGroup ()
165+ mountFlags := volumeCapability .GetMount ().GetMountFlags ()
166+ volumeMountGroup := volumeCapability .GetMount ().GetVolumeMountGroup ()
147167 secrets := req .GetSecrets ()
148168 gidPresent := checkGidPresentInMountFlags (mountFlags )
149169
@@ -199,7 +219,6 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
199219 mountFlags = strings .Split (ephemeralVolMountOptions , "," )
200220 }
201221
202- // in guest login, username and password options are not needed
203222 requireUsernamePwdOption := ! hasGuestMountOptions (mountFlags )
204223 if ephemeralVol && requireUsernamePwdOption {
205224 klog .V (2 ).Infof ("NodeStageVolume: getting username and password from secret %s in namespace %s" , secretName , secretNamespace )
@@ -264,7 +283,6 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
264283 if subDir != "" {
265284 // replace pv/pvc name namespace metadata in subDir
266285 subDir = replaceWithMap (subDir , subDirReplaceMap )
267-
268286 source = strings .TrimRight (source , "/" )
269287 source = fmt .Sprintf ("%s/%s" , source , subDir )
270288 }
@@ -281,7 +299,7 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
281299 return & csi.NodeStageVolumeResponse {}, nil
282300}
283301
284- // NodeUnstageVolume unmount the volume from the staging path
302+ // NodeUnstageVolume unmounts the volume from the staging path
285303func (d * Driver ) NodeUnstageVolume (_ context.Context , req * csi.NodeUnstageVolumeRequest ) (* csi.NodeUnstageVolumeResponse , error ) {
286304 volumeID := req .GetVolumeId ()
287305 if len (volumeID ) == 0 {
@@ -298,16 +316,51 @@ func (d *Driver) NodeUnstageVolume(_ context.Context, req *csi.NodeUnstageVolume
298316 }
299317 defer d .volumeLocks .Release (lockKey )
300318
301- klog .V (2 ).Infof ("NodeUnstageVolume: CleanupMountPoint on %s with volume %s" , stagingTargetPath , volumeID )
302- if err := CleanupSMBMountPoint (d .mounter , stagingTargetPath , true /*extensiveMountPointCheck*/ , volumeID ); err != nil {
303- return nil , status .Errorf (codes .Internal , "failed to unmount staging target %q: %v" , stagingTargetPath , err )
319+ // Check if any other mounts still reference the staging path
320+ f , err := os .Open ("/proc/mounts" )
321+ if err != nil {
322+ return nil , status .Errorf (codes .Internal , "failed to open /proc/mounts: %v" , err )
323+ }
324+ defer f .Close ()
325+
326+ scanner := bufio .NewScanner (f )
327+ refCount := 0
328+ for scanner .Scan () {
329+ line := scanner .Text ()
330+ fields := strings .Fields (line )
331+ if len (fields ) >= 2 {
332+ mountPoint := fields [1 ]
333+ if strings .HasPrefix (mountPoint , stagingTargetPath ) && mountPoint != stagingTargetPath {
334+ refCount ++
335+ }
336+ }
337+ }
338+ if refCount > 0 {
339+ klog .V (2 ).Infof ("NodeUnstageVolume: staging path %s is still in use by %d other mounts" , stagingTargetPath , refCount )
340+ return & csi.NodeUnstageVolumeResponse {}, nil
341+ }
342+
343+ notMnt , err := d .mounter .IsLikelyNotMountPoint (stagingTargetPath )
344+ if err != nil && ! os .IsNotExist (err ) {
345+ return nil , status .Errorf (codes .Internal , "failed to check mount point %q: %v" , stagingTargetPath , err )
346+ }
347+ if notMnt {
348+ klog .V (2 ).Infof ("NodeUnstageVolume: staging path %s is already unmounted" , stagingTargetPath )
349+ if err := os .Remove (stagingTargetPath ); err != nil && ! os .IsNotExist (err ) {
350+ return nil , status .Errorf (codes .Internal , "failed to remove staging path %q: %v" , stagingTargetPath , err )
351+ }
352+ return & csi.NodeUnstageVolumeResponse {}, nil
304353 }
305354
306- if err := deleteKerberosCache (d .krb5CacheDirectory , volumeID ); err != nil {
307- return nil , status .Errorf (codes .Internal , "failed to delete kerberos cache: %v" , err )
355+ klog .V (2 ).Infof ("NodeUnstageVolume: unmounting %s for volume %s" , stagingTargetPath , volumeID )
356+ if err := d .mounter .Unmount (stagingTargetPath ); err != nil {
357+ return nil , status .Errorf (codes .Internal , "failed to unmount staging path %q: %v" , stagingTargetPath , err )
358+ }
359+ if err := os .Remove (stagingTargetPath ); err != nil && ! os .IsNotExist (err ) {
360+ return nil , status .Errorf (codes .Internal , "failed to remove staging path %q after unmount: %v" , stagingTargetPath , err )
308361 }
309362
310- klog .V (2 ).Infof ("NodeUnstageVolume: unmount volume %s on %s successfully " , volumeID , stagingTargetPath )
363+ klog .V (2 ).Infof ("NodeUnstageVolume: successfully unmounted and cleaned up %s for volume %s " , stagingTargetPath , volumeID )
311364 return & csi.NodeUnstageVolumeResponse {}, nil
312365}
313366
0 commit comments