(
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<vm_memory::GuestMemoryMmap<B>>>,
access_platform: Option<&dyn AccessPlatform>,
)
| 83 | |
| 84 | impl Request { |
| 85 | pub fn parse<B: Bitmap + 'static>( |
| 86 | desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<vm_memory::GuestMemoryMmap<B>>>, |
| 87 | access_platform: Option<&dyn AccessPlatform>, |
| 88 | ) -> Result<Request, Error> { |
| 89 | let hdr_desc = desc_chain |
| 90 | .next() |
| 91 | .ok_or(Error::DescriptorChainTooShort) |
| 92 | .inspect_err(|_| { |
| 93 | error!("Missing head descriptor"); |
| 94 | })?; |
| 95 | |
| 96 | // The head contains the request type which MUST be readable. |
| 97 | if hdr_desc.is_write_only() { |
| 98 | return Err(Error::UnexpectedWriteOnlyDescriptor); |
| 99 | } |
| 100 | |
| 101 | let hdr_desc_addr = hdr_desc |
| 102 | .addr() |
| 103 | .translate_gva(access_platform, hdr_desc.len() as usize) |
| 104 | .map_err(|e| Error::GuestMemory(GuestMemoryError::IOError(e)))?; |
| 105 | |
| 106 | let mut req = Request { |
| 107 | request_type: request_type(desc_chain.memory(), hdr_desc_addr)?, |
| 108 | sector: sector(desc_chain.memory(), hdr_desc_addr)?, |
| 109 | data_descriptors: SmallVec::with_capacity(DEFAULT_DESCRIPTOR_VEC_SIZE), |
| 110 | status_addr: GuestAddress(0), |
| 111 | writeback: true, |
| 112 | aligned_operations: SmallVec::with_capacity(DEFAULT_DESCRIPTOR_VEC_SIZE), |
| 113 | start: Instant::now(), |
| 114 | }; |
| 115 | |
| 116 | let status_desc; |
| 117 | let mut desc = desc_chain |
| 118 | .next() |
| 119 | .ok_or(Error::DescriptorChainTooShort) |
| 120 | .inspect_err(|_| { |
| 121 | error!("Only head descriptor present: request = {req:?}"); |
| 122 | })?; |
| 123 | |
| 124 | if desc.has_next() { |
| 125 | req.data_descriptors.reserve_exact(1); |
| 126 | while desc.has_next() { |
| 127 | if desc.is_write_only() && req.request_type == RequestType::Out { |
| 128 | return Err(Error::UnexpectedWriteOnlyDescriptor); |
| 129 | } |
| 130 | if desc.is_write_only() && req.request_type == RequestType::Discard { |
| 131 | return Err(Error::UnexpectedWriteOnlyDescriptor); |
| 132 | } |
| 133 | if desc.is_write_only() && req.request_type == RequestType::WriteZeroes { |
| 134 | return Err(Error::UnexpectedWriteOnlyDescriptor); |
| 135 | } |
| 136 | if !desc.is_write_only() && req.request_type == RequestType::In { |
| 137 | return Err(Error::UnexpectedReadOnlyDescriptor); |
| 138 | } |
| 139 | if !desc.is_write_only() && req.request_type == RequestType::GetDeviceId { |
| 140 | return Err(Error::UnexpectedReadOnlyDescriptor); |
| 141 | } |
| 142 |
no test coverage detected