@@ -31,10 +31,13 @@ import (
31
31
"k8s.io/utils/mount"
32
32
)
33
33
34
- const TopologyKeyNode = "topology.hostpath.csi/node"
34
+ const (
35
+ TopologyKeyNode = "topology.hostpath.csi/node"
35
36
36
- func (hp * hostPath ) NodePublishVolume (ctx context.Context , req * csi.NodePublishVolumeRequest ) (* csi.NodePublishVolumeResponse , error ) {
37
+ failedPreconditionAccessModeConflict = "volume uses SINGLE_NODE_SINGLE_WRITER access mode and is already mounted at a different target path"
38
+ )
37
39
40
+ func (hp * hostPath ) NodePublishVolume (ctx context.Context , req * csi.NodePublishVolumeRequest ) (* csi.NodePublishVolumeResponse , error ) {
38
41
// Check arguments
39
42
if req .GetVolumeCapability () == nil {
40
43
return nil , status .Error (codes .InvalidArgument , "Volume capability missing in request" )
@@ -82,6 +85,10 @@ func (hp *hostPath) NodePublishVolume(ctx context.Context, req *csi.NodePublishV
82
85
return nil , status .Error (codes .NotFound , err .Error ())
83
86
}
84
87
88
+ if hasSingleNodeSingleWriterAccessMode (req ) && isMountedElsewhere (req , vol ) {
89
+ return nil , status .Error (codes .FailedPrecondition , failedPreconditionAccessModeConflict )
90
+ }
91
+
85
92
if ! ephemeralVolume {
86
93
if vol .Staged .Empty () {
87
94
return nil , status .Errorf (codes .FailedPrecondition , "volume %q must be staged before publishing" , vol .VolID )
@@ -521,3 +528,21 @@ func makeFile(pathname string) error {
521
528
}
522
529
return nil
523
530
}
531
+
532
+ // hasSingleNodeSingleWriterAccessMode checks if the publish request uses the
533
+ // SINGLE_NODE_SINGLE_WRITER access mode.
534
+ func hasSingleNodeSingleWriterAccessMode (req * csi.NodePublishVolumeRequest ) bool {
535
+ accessMode := req .GetVolumeCapability ().GetAccessMode ()
536
+ return accessMode != nil && accessMode .GetMode () == csi .VolumeCapability_AccessMode_SINGLE_NODE_SINGLE_WRITER
537
+ }
538
+
539
+ // isMountedElsewhere checks if the volume to publish is mounted elsewhere on
540
+ // the node.
541
+ func isMountedElsewhere (req * csi.NodePublishVolumeRequest , vol state.Volume ) bool {
542
+ for _ , targetPath := range vol .Published {
543
+ if targetPath != req .GetTargetPath () {
544
+ return true
545
+ }
546
+ }
547
+ return false
548
+ }
0 commit comments