@@ -31,6 +31,10 @@ pub enum ParseErr {
3131 /// An invalid value was specified in the FUSE bits of `CDW0`.
3232 #[ error( "reserved FUSE value specified" ) ]
3333 ReservedFuse ,
34+
35+ /// A reserved field was set to a non-zero value.
36+ #[ error( "reserved field value specified" ) ]
37+ Reserved ,
3438}
3539
3640/// A parsed Admin Command
@@ -715,14 +719,19 @@ impl NvmCmd {
715719 prp2 : raw. prp2 ,
716720 } ) ,
717721 bits:: NVM_OPC_DATASET_MANAGEMENT => {
722+ if ( raw. cdw11 & !0b111 ) != 0 {
723+ // Only the lowest 3 bits of CDW11 are used for Dataset
724+ // Management, so reject if any other bits are set.
725+ return Err ( ParseErr :: Reserved ) ;
726+ }
718727 NvmCmd :: DatasetManagement ( DatasetManagementCmd {
719728 prp1 : raw. prp1 ,
720729 prp2 : raw. prp2 ,
721730 // Convert from 0's based value
722731 nr : ( raw. cdw10 & 0xFF ) as u16 + 1 ,
723732 ad : raw. cdw11 & ( 1 << 2 ) != 0 ,
724- idw : raw. cdw11 & ( 1 << 1 ) != 0 ,
725- idr : raw. cdw11 & ( 1 << 0 ) != 0 ,
733+ _idw : raw. cdw11 & ( 1 << 1 ) != 0 ,
734+ _idr : raw. cdw11 & ( 1 << 0 ) != 0 ,
726735 } )
727736 }
728737 _ => NvmCmd :: Unknown ( raw) ,
@@ -797,7 +806,6 @@ impl ReadCmd {
797806
798807/// Dataset Management Command Parameters
799808#[ derive( Debug ) ]
800- #[ allow( dead_code) ]
801809pub struct DatasetManagementCmd {
802810 /// PRP Entry 1 (PRP1)
803811 ///
@@ -806,14 +814,13 @@ pub struct DatasetManagementCmd {
806814
807815 /// PRP Entry 2 (PRP2)
808816 ///
809- /// This field contains the second PRP entry that specifies the location where data should be
810- /// transferred from (if there is a physical discontinuity) .
817+ /// Indicates a second data buffer that contains LBA range information. It may not be a PRP
818+ /// List .
811819 prp2 : u64 ,
812820
813821 /// Number of Ranges (NR)
814822 ///
815- /// Indicates the number of 16 byte range sets that are specified in the command. This is a
816- /// 0’s based value.
823+ /// Indicates the number of 16 byte range sets that are specified in the command.
817824 pub nr : u16 ,
818825
819826 /// Attribute – Deallocate (AD)
@@ -832,15 +839,19 @@ pub struct DatasetManagementCmd {
832839 /// The host expects to perform operations on all ranges provided as an integral unit for
833840 /// writes, indicating that if a portion of the dataset is written it is expected that all of
834841 /// the ranges in the dataset are going to be written.
835- idw : bool ,
842+ ///
843+ /// Note: this field is advisory, and we ignore it.
844+ _idw : bool ,
836845
837846 /// Attribute – Integral Dataset for Read (IDR)
838847 ///
839848 /// If set to ‘1’ then the dataset should be optimized for read access as an integral unit.
840849 /// The host expects to perform operations on all ranges provided as an integral unit for
841850 /// reads, indicating that if a portion of the dataset is read it is expected that all of the
842851 /// ranges in the dataset are going to be read.
843- idr : bool ,
852+ ///
853+ /// Note: this field is advisory, and we ignore it.
854+ _idr : bool ,
844855}
845856
846857impl DatasetManagementCmd {
@@ -855,27 +866,23 @@ impl DatasetManagementCmd {
855866 )
856867 }
857868
858- /// Returns an Iterator that yields the LBA ranges specified in this command. Note that if
859- /// some of the ranges couldn't be read from guest memory, this will yield fewer than
860- /// `Self.nr` ranges.
869+ /// Returns an Iterator that yields the LBA ranges specified in this command. If any of the
870+ /// ranges cannot be read from guest memory, yields an error for that range instead.
861871 pub fn ranges < ' a > (
862872 & self ,
863873 mem : & ' a MemCtx ,
864- ) -> impl Iterator < Item = DatasetManagementRangeDefinition > + ' a {
874+ ) -> impl Iterator <
875+ Item = Result < DatasetManagementRangeDefinition , & ' static str > ,
876+ > + ' a {
865877 self . data ( mem) . flat_map ( |region| {
866- let mut ranges = Vec :: new ( ) ;
867- if let Some ( mapping) = mem. readable_region ( & region) {
868- ranges. resize_with (
869- mapping. len ( )
870- / size_of :: < DatasetManagementRangeDefinition > ( ) ,
871- Default :: default,
872- ) ;
873- if mapping. read_many ( & mut ranges) . is_err ( ) {
874- ranges. clear ( ) ;
875- }
876- } ;
877-
878- ranges. into_iter ( )
878+ if let Some ( Ok ( defs) ) = mem
879+ . readable_region ( & region)
880+ . map ( |mapping| mapping. read_many_owned ( ) )
881+ {
882+ defs. into_iter ( ) . map ( Ok ) . collect :: < Vec < _ > > ( ) . into_iter ( )
883+ } else {
884+ vec ! [ Err ( "Failed to read LBA range" ) ] . into_iter ( )
885+ }
879886 } )
880887 }
881888
0 commit comments