@@ -36,8 +36,10 @@ type GCENodeServer struct {
36
36
Mounter * mount.SafeFormatAndMount
37
37
DeviceUtils mountmanager.DeviceUtils
38
38
MetadataService metadataservice.MetadataService
39
- // TODO: Only lock mutually exclusive calls and make locking more fine grained
40
- mux sync.Mutex
39
+
40
+ // A map storing all volumes with ongoing operations so that additional operations
41
+ // for that same volume (as defined by VolumeID) return an Aborted error
42
+ volumes sync.Map
41
43
}
42
44
43
45
var _ csi.NodeServer = & GCENodeServer {}
@@ -51,8 +53,6 @@ const (
51
53
)
52
54
53
55
func (ns * GCENodeServer ) NodePublishVolume (ctx context.Context , req * csi.NodePublishVolumeRequest ) (* csi.NodePublishVolumeResponse , error ) {
54
- ns .mux .Lock ()
55
- defer ns .mux .Unlock ()
56
56
klog .V (4 ).Infof ("NodePublishVolume called with req: %#v" , req )
57
57
58
58
// Validate Arguments
@@ -74,6 +74,11 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
74
74
return nil , status .Error (codes .InvalidArgument , "NodePublishVolume Volume Capability must be provided" )
75
75
}
76
76
77
+ if _ , alreadyExists := ns .volumes .LoadOrStore (volumeID , true ); alreadyExists {
78
+ return nil , status .Error (codes .Aborted , fmt .Sprintf ("An operation with the given Volume ID %s already exists" , volumeID ))
79
+ }
80
+ defer ns .volumes .Delete (volumeID )
81
+
77
82
if err := validateVolumeCapability (volumeCapability ); err != nil {
78
83
return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("VolumeCapability is invalid: %v" , err ))
79
84
}
@@ -180,9 +185,8 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
180
185
}
181
186
182
187
func (ns * GCENodeServer ) NodeUnpublishVolume (ctx context.Context , req * csi.NodeUnpublishVolumeRequest ) (* csi.NodeUnpublishVolumeResponse , error ) {
183
- ns .mux .Lock ()
184
- defer ns .mux .Unlock ()
185
188
klog .V (4 ).Infof ("NodeUnpublishVolume called with args: %v" , req )
189
+
186
190
// Validate Arguments
187
191
targetPath := req .GetTargetPath ()
188
192
volID := req .GetVolumeId ()
@@ -193,6 +197,11 @@ func (ns *GCENodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeU
193
197
return nil , status .Error (codes .InvalidArgument , "NodeUnpublishVolume Target Path must be provided" )
194
198
}
195
199
200
+ if _ , alreadyExists := ns .volumes .LoadOrStore (volID , true ); alreadyExists {
201
+ return nil , status .Error (codes .Aborted , fmt .Sprintf ("An operation with the given Volume ID %s already exists" , volID ))
202
+ }
203
+ defer ns .volumes .Delete (volID )
204
+
196
205
err := mount .CleanupMountPoint (targetPath , ns .Mounter .Interface , false /* bind mount */ )
197
206
if err != nil {
198
207
return nil , status .Error (codes .Internal , fmt .Sprintf ("Unmount failed: %v\n Unmounting arguments: %s\n " , err , targetPath ))
@@ -202,8 +211,6 @@ func (ns *GCENodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeU
202
211
}
203
212
204
213
func (ns * GCENodeServer ) NodeStageVolume (ctx context.Context , req * csi.NodeStageVolumeRequest ) (* csi.NodeStageVolumeResponse , error ) {
205
- ns .mux .Lock ()
206
- defer ns .mux .Unlock ()
207
214
klog .V (4 ).Infof ("NodeStageVolume called with req: %#v" , req )
208
215
209
216
// Validate Arguments
@@ -220,6 +227,11 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
220
227
return nil , status .Error (codes .InvalidArgument , "NodeStageVolume Volume Capability must be provided" )
221
228
}
222
229
230
+ if _ , alreadyExists := ns .volumes .LoadOrStore (volumeID , true ); alreadyExists {
231
+ return nil , status .Error (codes .Aborted , fmt .Sprintf ("An operation with the given Volume ID %s already exists" , volumeID ))
232
+ }
233
+ defer ns .volumes .Delete (volumeID )
234
+
223
235
if err := validateVolumeCapability (volumeCapability ); err != nil {
224
236
return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("VolumeCapability is invalid: %v" , err ))
225
237
}
@@ -297,9 +309,8 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
297
309
}
298
310
299
311
func (ns * GCENodeServer ) NodeUnstageVolume (ctx context.Context , req * csi.NodeUnstageVolumeRequest ) (* csi.NodeUnstageVolumeResponse , error ) {
300
- ns .mux .Lock ()
301
- defer ns .mux .Unlock ()
302
312
klog .V (4 ).Infof ("NodeUnstageVolume called with req: %#v" , req )
313
+
303
314
// Validate arguments
304
315
volumeID := req .GetVolumeId ()
305
316
stagingTargetPath := req .GetStagingTargetPath ()
@@ -310,6 +321,11 @@ func (ns *GCENodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUns
310
321
return nil , status .Error (codes .InvalidArgument , "NodeUnstageVolume Staging Target Path must be provided" )
311
322
}
312
323
324
+ if _ , alreadyExists := ns .volumes .LoadOrStore (volumeID , true ); alreadyExists {
325
+ return nil , status .Error (codes .Aborted , fmt .Sprintf ("An operation with the given Volume ID %s already exists" , volumeID ))
326
+ }
327
+ defer ns .volumes .Delete (volumeID )
328
+
313
329
err := mount .CleanupMountPoint (stagingTargetPath , ns .Mounter .Interface , false /* bind mount */ )
314
330
if err != nil {
315
331
return nil , status .Error (codes .Internal , fmt .Sprintf ("NodeUnstageVolume failed to unmount at path %s: %v" , stagingTargetPath , err ))
0 commit comments