@@ -690,6 +690,10 @@ func (d *NVMeStorageDriver) Import(ctx context.Context, volConfig *storage.Volum
690690 return fmt .Errorf ("nvme namespace not found in volume %s" , originalName )
691691 }
692692
693+ // Lock the namespace until import is done.
694+ namespaceMutex .Lock (nsInfo .UUID )
695+ defer namespaceMutex .Unlock (nsInfo .UUID )
696+
693697 // The Namespace should be online
694698 if nsInfo .State != "online" {
695699 return fmt .Errorf ("Namespace %s is not online" , nsInfo .Name )
@@ -888,6 +892,7 @@ func (d *NVMeStorageDriver) Publish(
888892
889893 nsPath := volConfig .InternalID
890894 nsUUID := volConfig .AccessInfo .NVMeNamespaceUUID
895+
891896 // For docker context, some of the attributes like fsType, luks needs to be
892897 // fetched from namespace where they were stored while creating the namespace.
893898 if d .Config .DriverContext == tridentconfig .ContextDocker {
@@ -929,17 +934,20 @@ func (d *NVMeStorageDriver) Publish(
929934 }
930935 }
931936
932- // Checks if subsystem exists and creates a new one if not
933- subsystem , err := d .API .NVMeSubsystemCreate (ctx , ssName , ssName )
937+ // If 2 concurrent requests try to create the same subsystem, one will succeed and ONTAP is guaranteed to return
938+ // "already exists" error code for the other. So no need for locking around subsystem creation.
939+ subsystem , err := d .createOrGetSubsystem (ctx , ssName )
934940 if err != nil {
935- Logc (ctx ).Errorf ("subsystem create failed, %v" , err )
936941 return err
937942 }
938943
939944 if subsystem == nil {
940945 return fmt .Errorf ("No subsystem returned after subsystem create" )
941946 }
942947
948+ unlock := lockNamespaceAndSubsystem (nsUUID , subsystem .UUID )
949+ defer unlock ()
950+
943951 // Fill important info in publishInfo
944952 publishInfo .NVMeSubsystemNQN = subsystem .NQN
945953 publishInfo .NVMeSubsystemUUID = subsystem .UUID
@@ -989,6 +997,9 @@ func (d *NVMeStorageDriver) Unpublish(
989997 subsystemUUID := volConfig .AccessInfo .NVMeSubsystemUUID
990998 namespaceUUID := volConfig .AccessInfo .NVMeNamespaceUUID
991999
1000+ unlock := lockNamespaceAndSubsystem (namespaceUUID , subsystemUUID )
1001+ defer unlock ()
1002+
9921003 removePublishInfo , err := d .API .NVMeEnsureNamespaceUnmapped (ctx , publishInfo .HostNQN , subsystemUUID , namespaceUUID )
9931004 if removePublishInfo {
9941005 volConfig .AccessInfo .NVMeTargetIPs = []string {}
@@ -1165,6 +1176,16 @@ func (d *NVMeStorageDriver) getStoragePoolAttributes(ctx context.Context) map[st
11651176 }
11661177}
11671178
1179+ func (d * NVMeStorageDriver ) createOrGetSubsystem (ctx context.Context , ssName string ) (* api.NVMeSubsystem , error ) {
1180+ // This checks if subsystem exists and creates it if not.
1181+ ss , err := d .API .NVMeSubsystemCreate (ctx , ssName , ssName )
1182+ if err != nil {
1183+ Logc (ctx ).Errorf ("subsystem create failed, %v" , err )
1184+ return nil , err
1185+ }
1186+ return ss , nil
1187+ }
1188+
11681189// GetVolumeOpts populates the volume properties required in volume create.
11691190func (d * NVMeStorageDriver ) GetVolumeOpts (
11701191 ctx context.Context , volConfig * storage.VolumeConfig , requests map [string ]sa.Request ,
0 commit comments