virtio-devices: Improve queue handling with pop_descriptor_chain()

Using pop_descriptor_chain() is much more appropriate than iter() since
it recreates the iterator every time, avoiding the queue to be borrowed
and allowing the virtio-net implementation to match all the other ones.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2022-07-08 14:30:50 +02:00
committed by Rob Bradford
parent a423bf13ad
commit 87f57f7c1e
12 changed files with 271 additions and 302 deletions
+2 -4
View File
@@ -247,11 +247,9 @@ impl BalloonEpollHandler {
}
fn process_queue(&mut self, queue_index: usize) -> result::Result<(), Error> {
let mem = self.mem.memory();
let mut used_descs = Vec::new();
for mut desc_chain in self.queues[queue_index]
.iter(mem)
.map_err(Error::QueueIterator)?
while let Some(mut desc_chain) =
self.queues[queue_index].pop_descriptor_chain(self.mem.memory())
{
let desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
+3 -6
View File
@@ -108,10 +108,7 @@ impl BlockEpollHandler {
let mut used_desc_heads = Vec::new();
let mut used_count = 0;
let mut avail_iter = queue
.iter(self.mem.memory())
.map_err(Error::QueueIterator)?;
for mut desc_chain in &mut avail_iter {
while let Some(mut desc_chain) = queue.pop_descriptor_chain(self.mem.memory()) {
let mut request = Request::parse(&mut desc_chain, self.access_platform.as_ref())
.map_err(Error::RequestParsing)?;
@@ -121,7 +118,7 @@ impl BlockEpollHandler {
if !rate_limiter.consume(1, TokenType::Ops) {
// Stop processing the queue and return this descriptor chain to the
// avail ring, for later processing.
avail_iter.go_to_previous_position();
queue.go_to_previous_position();
break;
}
// Exercise the rate limiter only if this request is of data transfer type.
@@ -140,7 +137,7 @@ impl BlockEpollHandler {
rate_limiter.manual_replenish(1, TokenType::Ops);
// Stop processing the queue and return this descriptor chain to the
// avail ring, for later processing.
avail_iter.go_to_previous_position();
queue.go_to_previous_position();
break;
}
};
+3 -4
View File
@@ -144,8 +144,7 @@ impl ConsoleEpollHandler {
return false;
}
let mut avail_iter = recv_queue.iter(self.mem.memory()).unwrap();
for mut desc_chain in &mut avail_iter {
while let Some(mut desc_chain) = recv_queue.pop_descriptor_chain(self.mem.memory()) {
let desc = desc_chain.next().unwrap();
let len = cmp::min(desc.len() as u32, in_buffer.len() as u32);
let source_slice = in_buffer.drain(..len as usize).collect::<Vec<u8>>();
@@ -156,7 +155,7 @@ impl ConsoleEpollHandler {
.translate_gva(self.access_platform.as_ref(), desc.len() as usize),
) {
error!("Failed to write slice: {:?}", e);
avail_iter.go_to_previous_position();
recv_queue.go_to_previous_position();
break;
}
@@ -188,7 +187,7 @@ impl ConsoleEpollHandler {
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
let mut used_count = 0;
for mut desc_chain in trans_queue.iter(self.mem.memory()).unwrap() {
while let Some(mut desc_chain) = trans_queue.pop_descriptor_chain(self.mem.memory()) {
let desc = desc_chain.next().unwrap();
if let Some(ref mut out) = self.endpoint.out_file() {
let _ = desc_chain.memory().write_to(
+2 -2
View File
@@ -24,7 +24,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Barrier, Mutex, RwLock};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{DescriptorChain, Queue, QueueOwnedT, QueueT};
use virtio_queue::{DescriptorChain, Queue, QueueT};
use vm_device::dma_mapping::ExternalDmaMapping;
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
@@ -676,7 +676,7 @@ impl IommuEpollHandler {
fn request_queue(&mut self) -> bool {
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
let mut used_count = 0;
for mut desc_chain in self.queues[0].iter(self.mem.memory()).unwrap() {
while let Some(mut desc_chain) = self.queues[0].pop_descriptor_chain(self.mem.memory()) {
let len = match Request::parse(
&mut desc_chain,
&self.mapping,
+2 -2
View File
@@ -35,7 +35,7 @@ use std::sync::mpsc;
use std::sync::{Arc, Barrier, Mutex};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{DescriptorChain, Queue, QueueOwnedT, QueueT};
use virtio_queue::{DescriptorChain, Queue, QueueT};
use vm_device::dma_mapping::ExternalDmaMapping;
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
@@ -668,7 +668,7 @@ impl MemEpollHandler {
let mut request_list = Vec::new();
let mut used_count = 0;
for mut desc_chain in self.queue.iter(self.mem.memory()).unwrap() {
while let Some(mut desc_chain) = self.queue.pop_descriptor_chain(self.mem.memory()) {
request_list.push((
desc_chain.head_index(),
Request::parse(&mut desc_chain),
+2 -2
View File
@@ -28,7 +28,7 @@ use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{DescriptorChain, Queue, QueueOwnedT, QueueT};
use virtio_queue::{DescriptorChain, Queue, QueueT};
use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemoryAtomic,
GuestMemoryError, GuestMemoryLoadGuard,
@@ -180,7 +180,7 @@ impl PmemEpollHandler {
fn process_queue(&mut self) -> bool {
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
let mut used_count = 0;
for mut desc_chain in self.queue.iter(self.mem.memory()).unwrap() {
while let Some(mut desc_chain) = self.queue.pop_descriptor_chain(self.mem.memory()) {
let len = match Request::parse(&mut desc_chain, self.access_platform.as_ref()) {
Ok(ref req) if (req.type_ == RequestType::Flush) => {
let status_code = match self.disk.sync_all() {
+2 -2
View File
@@ -22,7 +22,7 @@ use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Barrier};
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueOwnedT, QueueT};
use virtio_queue::{Queue, QueueT};
use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
@@ -52,7 +52,7 @@ impl RngEpollHandler {
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
let mut used_count = 0;
for mut desc_chain in queue.iter(self.mem.memory()).unwrap() {
while let Some(mut desc_chain) = queue.pop_descriptor_chain(self.mem.memory()) {
let desc = desc_chain.next().unwrap();
let mut len = 0;
+4 -10
View File
@@ -128,10 +128,7 @@ where
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
let mut used_count = 0;
let mut avail_iter = self.queues[0]
.iter(self.mem.memory())
.map_err(DeviceError::QueueIterator)?;
for mut desc_chain in &mut avail_iter {
while let Some(mut desc_chain) = self.queues[0].pop_descriptor_chain(self.mem.memory()) {
let used_len = match VsockPacket::from_rx_virtq_head(
&mut desc_chain,
self.access_platform.as_ref(),
@@ -142,7 +139,7 @@ where
} else {
// We are using a consuming iterator over the virtio buffers, so, if we can't
// fill in this buffer, we'll need to undo the last iterator step.
avail_iter.go_to_previous_position();
self.queues[0].go_to_previous_position();
break;
}
}
@@ -179,10 +176,7 @@ where
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
let mut used_count = 0;
let mut avail_iter = self.queues[1]
.iter(self.mem.memory())
.map_err(DeviceError::QueueIterator)?;
for mut desc_chain in &mut avail_iter {
while let Some(mut desc_chain) = self.queues[1].pop_descriptor_chain(self.mem.memory()) {
let pkt = match VsockPacket::from_tx_virtq_head(
&mut desc_chain,
self.access_platform.as_ref(),
@@ -197,7 +191,7 @@ where
};
if self.backend.write().unwrap().send_pkt(&pkt).is_err() {
avail_iter.go_to_previous_position();
self.queues[1].go_to_previous_position();
break;
}
+2 -2
View File
@@ -26,7 +26,7 @@ use std::sync::{Arc, Barrier, Mutex};
use std::time::Instant;
use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueOwnedT, QueueT};
use virtio_queue::{Queue, QueueT};
use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
@@ -66,7 +66,7 @@ impl WatchdogEpollHandler {
let queue = &mut self.queue;
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
let mut used_count = 0;
for mut desc_chain in queue.iter(self.mem.memory()).unwrap() {
while let Some(mut desc_chain) = queue.pop_descriptor_chain(self.mem.memory()) {
let desc = desc_chain.next().unwrap();
let mut len = 0;