MCPcopy Create free account
hub / github.com/cloud-hypervisor/cloud-hypervisor / process_queue_submit

Method process_queue_submit

virtio-devices/src/block.rs:216–389  ·  view source on GitHub ↗
(&mut self)

Source from the content-addressed store, hash-verified

214 }
215
216 fn process_queue_submit(&mut self) -> Result<()> {
217 let queue = &mut self.queue;
218 let queue_size = queue.size();
219 let mut batch_requests = Vec::new();
220 let mut batch_inflight_requests = Vec::new();
221 let mut processed = 0;
222
223 loop {
224 // Cap a single drain at the virtqueue size. A compliant driver won't submit more that
225 // queue_size, but a buggy or malicious one can keep adding as the VMM is reading.
226 if processed >= queue_size {
227 break;
228 }
229 processed += 1;
230 let mut desc_chain = match queue
231 .iter(self.mem.memory())
232 .map_err(Error::QueueIterator)?
233 .next()
234 {
235 Some(c) => c,
236 None => break,
237 };
238
239 let head = desc_chain.head_index();
240 if Self::is_head_in_flight(&self.inflight_requests, &batch_inflight_requests, head) {
241 warn!("Guest reused virtio-blk head_index {head} while the chain was used");
242 return Err(Error::QueueDuplicatedHeadIndex);
243 }
244
245 let mut request = Request::parse(&mut desc_chain, self.access_platform.as_deref())
246 .map_err(Error::RequestParsing)?;
247
248 // For virtio spec compliance
249 // "A device MUST set the status byte to VIRTIO_BLK_S_IOERR for a write request
250 // if the VIRTIO_BLK_F_RO feature if offered, and MUST NOT write any data."
251 // Also, if sector 0 writes are disabled, treat writes to sector 0 as read-only as well.
252 if let Err(e) =
253 Self::check_request(self.acked_features, &request, self.disable_sector0_writes)
254 {
255 warn!("Request check failed: {request:x?} {e:?}");
256 desc_chain
257 .memory()
258 .write_obj(VIRTIO_BLK_S_IOERR, request.status_addr())
259 .map_err(Error::RequestStatus)?;
260
261 // If no asynchronous operation has been submitted, we can
262 // simply return the used descriptor.
263 queue
264 .add_used(desc_chain.memory(), desc_chain.head_index(), 1)
265 .map_err(Error::QueueAddUsed)?;
266 queue
267 .enable_notification(self.mem.memory().deref())
268 .map_err(Error::QueueEnableNotification)?;
269 continue;
270 }
271
272 if let Some(rate_limiter) = &mut self.rate_limiter {
273 // If limiter.consume() fails it means there is no more TokenType::Ops

Callers 1

Calls 15

newFunction · 0.85
iterMethod · 0.80
memoryMethod · 0.80
status_addrMethod · 0.80
request_typeMethod · 0.80
data_descriptorsMethod · 0.80
execute_asyncMethod · 0.80
sizeMethod · 0.45
nextMethod · 0.45
derefMethod · 0.45
consumeMethod · 0.45
manual_replenishMethod · 0.45

Tested by

no test coverage detected