@@ -10,7 +10,7 @@ use mctp::{AsyncRespChannel, MsgIC};
1010
1111use crate :: {
1212 CommandEffect , CommandEffectError , Controller , ControllerError , ControllerType , Discriminant ,
13- MAX_CONTROLLERS , MAX_NAMESPACES , NamespaceId , SubsystemError ,
13+ MAX_CONTROLLERS , MAX_NAMESPACES , NamespaceId , NamespaceIdDisposition , SubsystemError ,
1414 nvme:: {
1515 AdminFormatNvmConfiguration , AdminGetLogPageLidRequestType ,
1616 AdminGetLogPageSupportedLogPagesResponse , AdminIdentifyActiveNamespaceIdListResponse ,
@@ -1242,59 +1242,43 @@ impl RequestHandler for AdminIdentifyRequest {
12421242
12431243 match & self . req {
12441244 AdminIdentifyCnsRequestType :: NvmIdentifyNamespace => {
1245- assert ! ( subsys. nss. len( ) <= u32 :: MAX . try_into( ) . unwrap( ) ) ;
1246-
1247- if self . nsid == u32:: MAX {
1248- let ainvminr = AdminIdentifyNvmIdentifyNamespaceResponse {
1249- lbaf0_lbads : 9 , // TODO: Tie to controller model
1250- ..Default :: default ( )
1245+ let ainvminr = match NamespaceId ( self . nsid ) . disposition ( subsys) {
1246+ NamespaceIdDisposition :: Invalid => {
1247+ debug ! ( "Invalid NSID: {}" , self . nsid) ;
1248+ Err ( ResponseStatus :: InvalidParameter )
12511249 }
1252- . encode ( ) ?;
1253-
1254- return admin_send_response_body (
1255- resp,
1256- admin_constrain_body ( self . dofst , self . dlen , & ainvminr. 0 ) ?,
1257- )
1258- . await ;
1259- }
1260-
1261- if self . nsid == 0 || self . nsid > subsys. nss . capacity ( ) as u32 {
1262- debug ! ( "Invalid NSID: {}" , self . nsid) ;
1263- return Err ( ResponseStatus :: InvalidParameter ) ;
1264- }
1265-
1266- let Some ( ns) = subsys. nss . get ( self . nsid as usize - 1 ) else {
1267- debug ! ( "Unallocated NSID: {}" , self . nsid) ;
1268- return Err ( ResponseStatus :: InvalidParameter ) ;
1269- } ;
1270-
1271- // 4.1.5.1 NVM Command Set Spec, v1.0c
1272- // TODO: Ensure the associated controller is an IO controller
1273- // FIXME: Improve determination algo
1274- let active = subsys
1275- . ctlrs
1276- . iter ( )
1277- . flat_map ( |c| c. active_ns . iter ( ) )
1278- . any ( |& nsid| nsid. 0 == self . nsid ) ;
1279- let ainvminr = if active {
1280- AdminIdentifyNvmIdentifyNamespaceResponse {
1281- nsze : ns. size ,
1282- ncap : ns. capacity ,
1283- nuse : ns. used ,
1284- nsfeat : ( ( ns. size == ns. capacity ) as u8 ) ,
1285- nlbaf : 0 ,
1286- flbas : 0 ,
1287- mc : 0 ,
1288- dpc : 0 ,
1289- dps : 0 ,
1290- nvmcap : 2_u128 . pow ( ns. block_order as u32 ) * ns. size as u128 ,
1291- lbaf0 : 0 ,
1292- lbaf0_lbads : ns. block_order ,
1293- lbaf0_rp : 0 ,
1250+ NamespaceIdDisposition :: Broadcast => {
1251+ Ok ( AdminIdentifyNvmIdentifyNamespaceResponse {
1252+ lbaf0_lbads : 9 , // TODO: Tie to controller model
1253+ ..Default :: default ( )
1254+ } )
12941255 }
1295- } else {
1296- AdminIdentifyNvmIdentifyNamespaceResponse :: default ( )
1297- }
1256+ NamespaceIdDisposition :: Unallocated => {
1257+ debug ! ( "Unallocated NSID: {}" , self . nsid) ;
1258+ Err ( ResponseStatus :: InvalidParameter )
1259+ }
1260+ NamespaceIdDisposition :: Inactive ( _) => {
1261+ Ok ( AdminIdentifyNvmIdentifyNamespaceResponse :: default ( ) )
1262+ }
1263+ // 4.1.5.1 NVM Command Set Spec, v1.0c
1264+ NamespaceIdDisposition :: Active ( ns) => {
1265+ Ok ( AdminIdentifyNvmIdentifyNamespaceResponse {
1266+ nsze : ns. size ,
1267+ ncap : ns. capacity ,
1268+ nuse : ns. used ,
1269+ nsfeat : ( ( ns. size == ns. capacity ) as u8 ) ,
1270+ nlbaf : 0 ,
1271+ flbas : 0 ,
1272+ mc : 0 ,
1273+ dpc : 0 ,
1274+ dps : 0 ,
1275+ nvmcap : 2_u128 . pow ( ns. block_order as u32 ) * ns. size as u128 ,
1276+ lbaf0 : 0 ,
1277+ lbaf0_lbads : ns. block_order ,
1278+ lbaf0_rp : 0 ,
1279+ } )
1280+ }
1281+ } ?
12981282 . encode ( ) ?;
12991283
13001284 admin_send_response_body (
@@ -1358,11 +1342,7 @@ impl RequestHandler for AdminIdentifyRequest {
13581342 sqes : 0 ,
13591343 cqes : 0 ,
13601344 maxcmd : 0 ,
1361- nn : subsys
1362- . nss
1363- . capacity ( )
1364- . try_into ( )
1365- . expect ( "Too many namespaces" ) ,
1345+ nn : NamespaceId :: max ( subsys) ,
13661346 oncs : 0 ,
13671347 fuses : 0 ,
13681348 fna : ctlr. fna . into ( ) ,
@@ -1420,36 +1400,43 @@ impl RequestHandler for AdminIdentifyRequest {
14201400 }
14211401 AdminIdentifyCnsRequestType :: NamespaceIdentificationDescriptorList => {
14221402 // 5.1.13.2.3, Base v2.1
1423- if self . nsid >= u32:: MAX - 1 {
1424- debug ! ( "Unacceptable NSID for Namespace Identification Descriptor List" ) ;
1425- return Err ( ResponseStatus :: InvalidParameter ) ;
1426- }
1427-
1428- if self . nsid == 0 || self . nsid > subsys. nss . capacity ( ) as u32 {
1429- debug ! ( "Invalid NSID: {}" , self . nsid) ;
1430- return Err ( ResponseStatus :: InvalidParameter ) ;
1431- }
1432-
1433- let Some ( ns) = subsys. nss . get ( self . nsid as usize - 1 ) else {
1434- debug ! ( "Unallocated NSID: {}" , self . nsid) ;
1435- return Err ( ResponseStatus :: InvalidParameter ) ;
1436- } ;
1437-
1438- let ainsidlr = AdminIdentifyNamespaceIdentificationDescriptorListResponse {
1439- nids : {
1440- let mut vec = WireVec :: new ( ) ;
1441- for nid in & ns. nids {
1442- if vec
1443- . push ( Into :: < NamespaceIdentifierType > :: into ( * nid) )
1444- . is_err ( )
1445- {
1446- debug ! ( "Failed to push NID {nid:?}" ) ;
1447- return Err ( ResponseStatus :: InternalError ) ;
1448- }
1403+ let ainsidlr = match NamespaceId ( self . nsid ) . disposition ( subsys) {
1404+ NamespaceIdDisposition :: Invalid => {
1405+ if self . nsid == u32:: MAX - 1 {
1406+ debug ! (
1407+ "Unacceptable NSID for Namespace Identification Descriptor List"
1408+ ) ;
1409+ } else {
1410+ debug ! ( "Invalid NSID: {}" , self . nsid) ;
14491411 }
1450- vec
1451- } ,
1452- }
1412+ Err ( ResponseStatus :: InvalidParameter )
1413+ }
1414+ NamespaceIdDisposition :: Broadcast => {
1415+ debug ! ( "Invalid NSID: {}" , self . nsid) ;
1416+ Err ( ResponseStatus :: InvalidParameter )
1417+ }
1418+ NamespaceIdDisposition :: Unallocated => {
1419+ debug ! ( "Unallocated NSID: {}" , self . nsid) ;
1420+ Err ( ResponseStatus :: InvalidParameter )
1421+ }
1422+ NamespaceIdDisposition :: Inactive ( ns) | NamespaceIdDisposition :: Active ( ns) => {
1423+ Ok ( AdminIdentifyNamespaceIdentificationDescriptorListResponse {
1424+ nids : {
1425+ let mut vec = WireVec :: new ( ) ;
1426+ for nid in & ns. nids {
1427+ if vec
1428+ . push ( Into :: < NamespaceIdentifierType > :: into ( * nid) )
1429+ . is_err ( )
1430+ {
1431+ debug ! ( "Failed to push NID {nid:?}" ) ;
1432+ return Err ( ResponseStatus :: InternalError ) ;
1433+ }
1434+ }
1435+ vec
1436+ } ,
1437+ } )
1438+ }
1439+ } ?
14531440 . encode ( ) ?;
14541441
14551442 admin_send_response_body (
@@ -1465,13 +1452,18 @@ impl RequestHandler for AdminIdentifyRequest {
14651452 return Err ( ResponseStatus :: InvalidParameter ) ;
14661453 }
14671454
1468- assert ! ( subsys . nss . len ( ) < 4096 / core:: mem:: size_of:: <u32 >( ) ) ;
1455+ assert ! ( NamespaceId :: max ( subsys ) < ( 4096 / core:: mem:: size_of:: <u32 >( ) ) as u32 ) ;
14691456 let aiansidl = AdminIdentifyAllocatedNamespaceIdListResponse {
14701457 nsid : {
1471- let start = self . nsid + 1 ;
1472- let end = subsys. nss . len ( ) as u32 ;
1458+ let mut allocated: heapless:: Vec < u32 , MAX_NAMESPACES > = subsys
1459+ . nss
1460+ . iter ( )
1461+ . map ( |ns| ns. id . 0 )
1462+ . filter ( |nsid| * nsid > self . nsid )
1463+ . collect ( ) ;
1464+ allocated. sort_unstable ( ) ;
14731465 let mut vec = WireVec :: new ( ) ;
1474- for nsid in start..=end {
1466+ for nsid in allocated {
14751467 if vec. push ( nsid) . is_err ( ) {
14761468 debug ! ( "Failed to insert NSID {nsid}" ) ;
14771469 return Err ( ResponseStatus :: InternalError ) ;
0 commit comments