@@ -48,6 +48,7 @@ use spdk_rs::{
48
48
spdk_nvmf_subsystem_state_change_done,
49
49
spdk_nvmf_subsystem_stop,
50
50
spdk_nvmf_tgt,
51
+ spdk_nvmf_tgt_get_transport,
51
52
SPDK_NVME_SCT_GENERIC ,
52
53
SPDK_NVME_SC_CAPACITY_EXCEEDED ,
53
54
SPDK_NVME_SC_RESERVATION_CONFLICT ,
@@ -68,8 +69,13 @@ use crate::{
68
69
ffihelper:: { cb_arg, done_cb, AsStr , FfiResult , IntoCString } ,
69
70
lvs:: Lvol ,
70
71
subsys:: {
72
+ config:: opts:: NvmfTgtTransport ,
71
73
make_subsystem_serial,
72
- nvmf:: { transport:: TransportId , Error , NVMF_TGT } ,
74
+ nvmf:: {
75
+ transport:: { TransportId , RDMA_TRANSPORT } ,
76
+ Error ,
77
+ NVMF_TGT ,
78
+ } ,
73
79
Config ,
74
80
} ,
75
81
} ;
@@ -798,7 +804,10 @@ impl NvmfSubsystem {
798
804
}
799
805
800
806
// we currently allow all listeners to the subsystem
801
- async fn add_listener ( & self ) -> Result < ( ) , Error > {
807
+ async fn add_listener (
808
+ & self ,
809
+ transport : NvmfTgtTransport ,
810
+ ) -> Result < ( ) , Error > {
802
811
extern "C" fn listen_cb ( arg : * mut c_void , status : i32 ) {
803
812
let s = unsafe { Box :: from_raw ( arg as * mut oneshot:: Sender < i32 > ) } ;
804
813
s. send ( status) . unwrap ( ) ;
@@ -807,8 +816,8 @@ impl NvmfSubsystem {
807
816
let cfg = Config :: get ( ) ;
808
817
809
818
// dont yet enable both ports, IOW just add one transportID now
810
-
811
- let trid_replica = TransportId :: new ( cfg. nexus_opts . nvmf_replica_port ) ;
819
+ let trid_replica =
820
+ TransportId :: new ( cfg. nexus_opts . nvmf_replica_port , transport ) ;
812
821
813
822
let ( s, r) = oneshot:: channel :: < i32 > ( ) ;
814
823
unsafe {
@@ -907,8 +916,23 @@ impl NvmfSubsystem {
907
916
/// start the subsystem previously created -- note that we destroy it on
908
917
/// failure to ensure the state is not in limbo and to avoid leaking
909
918
/// resources
910
- pub async fn start ( self ) -> Result < String , Error > {
911
- self . add_listener ( ) . await ?;
919
+ pub async fn start ( self , need_rdma : bool ) -> Result < String , Error > {
920
+ self . add_listener ( NvmfTgtTransport :: Tcp ) . await ?;
921
+ // Only attempt rdma listener addition for this subsystem after making
922
+ // sure the Mayastor nvmf tgt has rdma transport created.
923
+ if need_rdma && self . nvmf_tgt_has_rdma_xprt ( ) {
924
+ let _ =
925
+ self . add_listener ( NvmfTgtTransport :: Rdma )
926
+ . await
927
+ . map_err ( |e| {
928
+ warn ! (
929
+ "NvmfSubsystem RDMA listener add failed {}. \
930
+ Subsystem will be accessible over TCP only.\
931
+ {:?}",
932
+ e, self
933
+ ) ;
934
+ } ) ;
935
+ }
912
936
913
937
if let Err ( e) = self
914
938
. change_state ( "start" , |ss, cb, arg| unsafe {
@@ -958,9 +982,15 @@ impl NvmfSubsystem {
958
982
}
959
983
960
984
/// get ANA state
985
+ /// XXX: The SPDK NVME multipath is transport protocol independent. Should
986
+ /// we keep returning the ana state here by default using TCP transport
987
+ /// as today?
961
988
pub async fn get_ana_state ( & self ) -> Result < u32 , Error > {
962
989
let cfg = Config :: get ( ) ;
963
- let trid_replica = TransportId :: new ( cfg. nexus_opts . nvmf_replica_port ) ;
990
+ let trid_replica = TransportId :: new (
991
+ cfg. nexus_opts . nvmf_replica_port ,
992
+ NvmfTgtTransport :: Tcp ,
993
+ ) ;
964
994
let listener = unsafe {
965
995
nvmf_subsystem_find_listener ( self . 0 . as_ptr ( ) , trid_replica. as_ptr ( ) )
966
996
} ;
@@ -981,29 +1011,35 @@ impl NvmfSubsystem {
981
1011
let s = unsafe { Box :: from_raw ( arg as * mut oneshot:: Sender < i32 > ) } ;
982
1012
s. send ( status) . unwrap ( ) ;
983
1013
}
984
- let cfg = Config :: get ( ) ;
985
- let trid_replica = TransportId :: new ( cfg. nexus_opts . nvmf_replica_port ) ;
986
1014
987
- let ( s, r) = oneshot:: channel :: < i32 > ( ) ;
1015
+ // setting ANA state can only be done when subsystem is shared, meaning
1016
+ // it'll have listeners configured. So let's fetch transport ids
1017
+ // based on active listeners instead of reading static Config.
1018
+ let trids = self . listeners_to_vec ( ) . unwrap_or_default ( ) ;
988
1019
989
- unsafe {
990
- spdk_nvmf_subsystem_set_ana_state (
991
- self . 0 . as_ptr ( ) ,
992
- trid_replica. as_ptr ( ) ,
993
- ana_state,
994
- 0 ,
995
- Some ( set_ana_state_cb) ,
996
- cb_arg ( s) ,
997
- ) ;
1020
+ for trid in trids {
1021
+ debug ! ( "set_ana_state {ana_state}, {trid:?}" ) ;
1022
+ let ( s, r) = oneshot:: channel :: < i32 > ( ) ;
1023
+ unsafe {
1024
+ spdk_nvmf_subsystem_set_ana_state (
1025
+ self . 0 . as_ptr ( ) ,
1026
+ trid. as_ptr ( ) ,
1027
+ ana_state,
1028
+ 0 ,
1029
+ Some ( set_ana_state_cb) ,
1030
+ cb_arg ( s) ,
1031
+ ) ;
1032
+ }
1033
+ r. await
1034
+ . expect ( "Cancellation is not supported" )
1035
+ . to_result ( |e| Error :: Subsystem {
1036
+ source : Errno :: from_i32 ( -e) ,
1037
+ nqn : self . get_nqn ( ) ,
1038
+ msg : "failed to set_ana_state of the subsystem" . to_string ( ) ,
1039
+ } ) ?;
998
1040
}
999
1041
1000
- r. await
1001
- . expect ( "Cancellation is not supported" )
1002
- . to_result ( |e| Error :: Subsystem {
1003
- source : Errno :: from_i32 ( -e) ,
1004
- nqn : self . get_nqn ( ) ,
1005
- msg : "failed to set_ana_state of the subsystem" . to_string ( ) ,
1006
- } )
1042
+ Ok ( ( ) )
1007
1043
}
1008
1044
1009
1045
/// destroy all subsystems associated with our target, subsystems must be in
@@ -1073,6 +1109,18 @@ impl NvmfSubsystem {
1073
1109
Bdev :: checked_from_ptr ( unsafe { spdk_nvmf_ns_get_bdev ( ns) } )
1074
1110
}
1075
1111
1112
+ fn nvmf_tgt_has_rdma_xprt ( & self ) -> bool {
1113
+ NVMF_TGT . with ( |t| {
1114
+ let transport = unsafe {
1115
+ spdk_nvmf_tgt_get_transport (
1116
+ t. borrow ( ) . tgt . as_ptr ( ) ,
1117
+ RDMA_TRANSPORT . as_ptr ( ) ,
1118
+ )
1119
+ } ;
1120
+ !transport. is_null ( )
1121
+ } )
1122
+ }
1123
+
1076
1124
fn listeners_to_vec ( & self ) -> Option < Vec < TransportId > > {
1077
1125
unsafe {
1078
1126
let mut listener =
0 commit comments