@@ -9,7 +9,7 @@ use log::debug;
99use mctp:: { AsyncRespChannel , MsgIC } ;
1010
1111use crate :: {
12- CommandEffect , CommandEffectError , ControllerError , ControllerType , Discriminant ,
12+ CommandEffect , CommandEffectError , Controller , ControllerError , ControllerType , Discriminant ,
1313 MAX_CONTROLLERS , MAX_NAMESPACES , NamespaceId , SubsystemError ,
1414 nvme:: {
1515 AdminGetLogPageLidRequestType , AdminGetLogPageSupportedLogPagesResponse ,
@@ -1586,6 +1586,7 @@ impl RequestHandler for AdminNamespaceAttachmentRequest {
15861586 #[ repr( u8 ) ]
15871587 enum CommandSpecificStatus {
15881588 NamespaceAlreadyAttached = 0x18 ,
1589+ NamespaceNotAttached = 0x1a ,
15891590 ControllerListInvalid = 0x1c ,
15901591 NamespaceAttachmentLimitExceeded = 0x27 ,
15911592 }
@@ -1598,96 +1599,102 @@ impl RequestHandler for AdminNamespaceAttachmentRequest {
15981599 ControllerError :: NamespaceAttachmentLimitExceeded => {
15991600 Self :: NamespaceAttachmentLimitExceeded
16001601 }
1602+ ControllerError :: NamespaceNotAttached => Self :: NamespaceNotAttached ,
16011603 }
16021604 }
16031605 }
16041606
1605- match & self . req {
1606- crate :: nvme:: AdminNamespaceAttachmentSelect :: ControllerAttach ( req) => {
1607- // SAFETY: Protected in parsing by DekuError::InvalidParam
1608- debug_assert ! ( req. numids <= 2047 ) ;
1607+ // SAFETY: Protected in parsing by DekuError::InvalidParam
1608+ debug_assert ! ( self . body. numids <= 2047 ) ;
16091609
1610- let expected = ( 2047 - ( req. numids as usize ) ) * core:: mem:: size_of :: < u16 > ( ) ;
1611- if rest. len ( ) != expected {
1612- debug ! (
1613- "Invalid request size for Admin Namespace Attachment: Found {}, expected {expected}" ,
1614- rest. len( )
1615- ) ;
1616- return Err ( ResponseStatus :: InvalidCommandSize ) ;
1617- }
1618-
1619- if self . nsid == u32:: MAX {
1620- debug ! ( "Refusing to attach broadcast NSID" ) ;
1621- return Err ( ResponseStatus :: InvalidParameter ) ;
1622- }
1623-
1624- // TODO: Handle MAXCNA
1610+ let expected = ( 2047 - ( self . body . numids as usize ) ) * core:: mem:: size_of :: < u16 > ( ) ;
1611+ if rest. len ( ) != expected {
1612+ debug ! (
1613+ "Invalid request size for Admin Namespace Attachment: Found {}, expected {expected}" ,
1614+ rest. len( )
1615+ ) ;
1616+ return Err ( ResponseStatus :: InvalidCommandSize ) ;
1617+ }
16251618
1626- let mut status = AdminIoCqeStatusType :: GenericCommandStatus (
1627- AdminIoCqeGenericCommandStatus :: SuccessfulCompletion ,
1628- ) ;
1619+ if self . nsid == u32:: MAX {
1620+ debug ! ( "Refusing to perform {:?} for broadcast NSID" , self . sel) ;
1621+ return Err ( ResponseStatus :: InvalidParameter ) ;
1622+ }
16291623
1630- for cid in & req. ids . 0 {
1631- let Some ( ctlr) = subsys. ctlrs . get_mut ( * cid as usize ) else {
1632- debug ! ( "Unrecognised controller ID: {cid}" ) ;
1633- status = AdminIoCqeStatusType :: CommandSpecificStatus (
1634- CommandSpecificStatus :: ControllerListInvalid . id ( ) ,
1635- ) ;
1636- break ;
1637- } ;
1624+ // TODO: Handle MAXCNA
16381625
1639- // TODO: Allow addition of non-IO controllers
1640- if ctlr. cntrltype != ControllerType :: Io {
1641- debug ! (
1642- "Require {:?} controller type, have {:?}" ,
1643- ControllerType :: Io ,
1644- ctlr. cntrltype
1645- ) ;
1646- status = AdminIoCqeStatusType :: CommandSpecificStatus (
1647- CommandSpecificStatus :: ControllerListInvalid . id ( ) ,
1648- ) ;
1649- break ;
1650- }
1626+ let mut status = AdminIoCqeStatusType :: GenericCommandStatus (
1627+ AdminIoCqeGenericCommandStatus :: SuccessfulCompletion ,
1628+ ) ;
16511629
1652- // TODO: Handle Namespace Is Private
1653- // TODO: Handle I/O Command Set Not Supported
1654- // TODO: Handle I/O Command Set Not Enabled
1630+ let action = match & self . sel {
1631+ crate :: nvme:: AdminNamespaceAttachmentSelect :: ControllerAttach => {
1632+ |ctlr : & mut Controller , ns : NamespaceId | ctlr. attach_namespace ( ns)
1633+ }
1634+ crate :: nvme:: AdminNamespaceAttachmentSelect :: ControllerDetach => {
1635+ |ctlr : & mut Controller , ns : NamespaceId | ctlr. detach_namespace ( ns)
1636+ }
1637+ } ;
16551638
1656- // XXX: Should this be transactional? Two loops?
1657- if let Err ( err) = ctlr. attach_namespace ( NamespaceId ( self . nsid ) ) {
1658- let err: CommandSpecificStatus = err. into ( ) ;
1659- status = AdminIoCqeStatusType :: CommandSpecificStatus ( err. id ( ) ) ;
1660- break ;
1661- }
1662- }
1639+ for cid in & self . body . ids . 0 {
1640+ let Some ( ctlr) = subsys. ctlrs . get_mut ( * cid as usize ) else {
1641+ debug ! ( "Unrecognised controller ID: {cid}" ) ;
1642+ status = AdminIoCqeStatusType :: CommandSpecificStatus (
1643+ CommandSpecificStatus :: ControllerListInvalid . id ( ) ,
1644+ ) ;
1645+ break ;
1646+ } ;
16631647
1664- let mh = MessageHeader :: respond ( MessageType :: NvmeAdminCommand ) . encode ( ) ?;
1648+ // TODO: Allow addition of non-IO controllers
1649+ if ctlr. cntrltype != ControllerType :: Io {
1650+ debug ! (
1651+ "Require {:?} controller type, have {:?}" ,
1652+ ControllerType :: Io ,
1653+ ctlr. cntrltype
1654+ ) ;
1655+ status = AdminIoCqeStatusType :: CommandSpecificStatus (
1656+ CommandSpecificStatus :: ControllerListInvalid . id ( ) ,
1657+ ) ;
1658+ break ;
1659+ }
16651660
1666- let acrh = AdminCommandResponseHeader {
1667- status : ResponseStatus :: Success ,
1668- cqedw0 : self . nsid ,
1669- cqedw1 : 0 ,
1670- cqedw3 : AdminIoCqeStatus {
1671- cid : 0 ,
1672- p : true ,
1673- status,
1674- crd : crate :: nvme:: CommandRetryDelay :: None ,
1675- m : false ,
1676- dnr : {
1677- AdminIoCqeStatusType :: GenericCommandStatus (
1678- AdminIoCqeGenericCommandStatus :: SuccessfulCompletion ,
1679- ) != status
1680- } ,
1681- }
1682- . into ( ) ,
1683- }
1684- . encode ( ) ?;
1661+ // TODO: Handle Namespace Is Private
1662+ // TODO: Handle I/O Command Set Not Supported
1663+ // TODO: Handle I/O Command Set Not Enabled
16851664
1686- send_response ( resp, & [ & mh. 0 , & acrh. 0 ] ) . await ;
1665+ // XXX: Should this be transactional? Two loops?
1666+ if let Err ( err) = action ( ctlr, NamespaceId ( self . nsid ) ) {
1667+ let err: CommandSpecificStatus = err. into ( ) ;
1668+ status = AdminIoCqeStatusType :: CommandSpecificStatus ( err. id ( ) ) ;
1669+ break ;
1670+ }
1671+ }
16871672
1688- Ok ( ( ) )
1673+ let mh = MessageHeader :: respond ( MessageType :: NvmeAdminCommand ) . encode ( ) ?;
1674+
1675+ let acrh = AdminCommandResponseHeader {
1676+ status : ResponseStatus :: Success ,
1677+ cqedw0 : self . nsid ,
1678+ cqedw1 : 0 ,
1679+ cqedw3 : AdminIoCqeStatus {
1680+ cid : 0 ,
1681+ p : true ,
1682+ status,
1683+ crd : crate :: nvme:: CommandRetryDelay :: None ,
1684+ m : false ,
1685+ dnr : {
1686+ AdminIoCqeStatusType :: GenericCommandStatus (
1687+ AdminIoCqeGenericCommandStatus :: SuccessfulCompletion ,
1688+ ) != status
1689+ } ,
16891690 }
1691+ . into ( ) ,
16901692 }
1693+ . encode ( ) ?;
1694+
1695+ send_response ( resp, & [ & mh. 0 , & acrh. 0 ] ) . await ;
1696+
1697+ Ok ( ( ) )
16911698 }
16921699}
16931700
0 commit comments