virtio-devices: Optimize add_used() usage

Now that we rely on pop_descriptor_chain() rather than iter() to iterate
over a queue, there's no more borrow on the queue itself, meaning we can
invoke add_used() directly for the iteration loop. This simplifies the
processing of the queues for each virtio device, and bring some possible
performance improvement given we don't have to iterate twice over the
list of descriptors to invoke add_used().

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2022-07-25 14:26:17 +02:00 committed by Rob Bradford
parent 87f57f7c1e
commit a4859ffe85
11 changed files with 111 additions and 179 deletions

View File

@ -62,7 +62,6 @@ impl CtrlQueue {
queue: &mut Queue, queue: &mut Queue,
access_platform: Option<&Arc<dyn AccessPlatform>>, access_platform: Option<&Arc<dyn AccessPlatform>>,
) -> Result<()> { ) -> Result<()> {
let mut used_desc_heads = Vec::new();
while let Some(mut desc_chain) = queue.pop_descriptor_chain(mem) { while let Some(mut desc_chain) = queue.pop_descriptor_chain(mem) {
let ctrl_desc = desc_chain.next().ok_or(Error::NoControlHeaderDescriptor)?; let ctrl_desc = desc_chain.next().ok_or(Error::NoControlHeaderDescriptor)?;
@ -139,7 +138,10 @@ impl CtrlQueue {
) )
.map_err(Error::GuestMemory)?; .map_err(Error::GuestMemory)?;
let len = ctrl_desc.len() + data_desc.len() + status_desc.len(); let len = ctrl_desc.len() + data_desc.len() + status_desc.len();
used_desc_heads.push((desc_chain.head_index(), len));
queue
.add_used(desc_chain.memory(), desc_chain.head_index(), len)
.map_err(Error::QueueAddUsed)?;
if !queue if !queue
.enable_notification(mem) .enable_notification(mem)
@ -149,12 +151,6 @@ impl CtrlQueue {
} }
} }
for (desc_index, len) in used_desc_heads.iter() {
queue
.add_used(mem, *desc_index, *len)
.map_err(Error::QueueAddUsed)?;
}
Ok(()) Ok(())
} }
} }

View File

@ -120,7 +120,7 @@ impl TxVirtio {
} }
queue queue
.add_used(mem, desc_chain.head_index(), len) .add_used(desc_chain.memory(), desc_chain.head_index(), len)
.map_err(NetQueuePairError::QueueAddUsed)?; .map_err(NetQueuePairError::QueueAddUsed)?;
if !queue if !queue
@ -262,7 +262,7 @@ impl RxVirtio {
} }
queue queue
.add_used(mem, desc_chain.head_index(), len) .add_used(desc_chain.memory(), desc_chain.head_index(), len)
.map_err(NetQueuePairError::QueueAddUsed)?; .map_err(NetQueuePairError::QueueAddUsed)?;
if !queue if !queue

View File

@ -124,7 +124,7 @@ impl VhostUserBlkThread {
&mut self, &mut self,
vring: &mut RwLockWriteGuard<VringState<GuestMemoryAtomic<GuestMemoryMmap>>>, vring: &mut RwLockWriteGuard<VringState<GuestMemoryAtomic<GuestMemoryMmap>>>,
) -> bool { ) -> bool {
let mut used_desc_heads = Vec::new(); let mut used_descs = false;
while let Some(mut desc_chain) = vring while let Some(mut desc_chain) = vring
.get_queue_mut() .get_queue_mut()
@ -162,37 +162,35 @@ impl VhostUserBlkThread {
} }
} }
used_desc_heads.push((desc_chain.head_index(), len)); vring
.get_queue_mut()
.add_used(desc_chain.memory(), desc_chain.head_index(), len)
.unwrap();
used_descs = true;
} }
let mem = self.mem.memory();
let mut needs_signalling = false; let mut needs_signalling = false;
for (desc_head, len) in used_desc_heads.iter() { if self.event_idx {
if self.event_idx { if vring
let queue = vring.get_queue_mut(); .get_queue_mut()
if queue.add_used(mem.deref(), *desc_head, *len).is_ok() { .needs_notification(self.mem.memory().deref())
if queue.needs_notification(mem.deref()).unwrap() { .unwrap()
debug!("signalling queue"); {
needs_signalling = true;
} else {
debug!("omitting signal (event_idx)");
}
}
} else {
debug!("signalling queue"); debug!("signalling queue");
vring
.get_queue_mut()
.add_used(mem.deref(), *desc_head, *len)
.unwrap();
needs_signalling = true; needs_signalling = true;
} else {
debug!("omitting signal (event_idx)");
} }
} else {
debug!("signalling queue");
needs_signalling = true;
} }
if needs_signalling { if needs_signalling {
vring.signal_used_queue().unwrap(); vring.signal_used_queue().unwrap();
} }
!used_desc_heads.is_empty() used_descs
} }
} }

View File

@ -22,7 +22,6 @@ use libc::EFD_NONBLOCK;
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::io; use std::io;
use std::mem::size_of; use std::mem::size_of;
use std::ops::Deref;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::{ use std::sync::{
@ -31,7 +30,7 @@ use std::sync::{
}; };
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueOwnedT, QueueT}; use virtio_queue::{Queue, QueueT};
use vm_memory::{ use vm_memory::{
Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
GuestMemoryError, GuestMemoryRegion, GuestMemoryError, GuestMemoryRegion,
@ -227,34 +226,13 @@ impl BalloonEpollHandler {
Self::advise_memory_range(memory, range_base, range_len, libc::MADV_DONTNEED) Self::advise_memory_range(memory, range_base, range_len, libc::MADV_DONTNEED)
} }
fn notify_queue(
&mut self,
queue_index: usize,
used_descs: Vec<(u16, u32)>,
) -> result::Result<(), Error> {
let mem = self.mem.memory();
for (desc_index, len) in used_descs.iter() {
self.queues[queue_index]
.add_used(mem.deref(), *desc_index, *len)
.map_err(Error::QueueAddUsed)?;
}
if !used_descs.is_empty() {
self.signal(VirtioInterruptType::Queue(queue_index as u16))?;
}
Ok(())
}
fn process_queue(&mut self, queue_index: usize) -> result::Result<(), Error> { fn process_queue(&mut self, queue_index: usize) -> result::Result<(), Error> {
let mut used_descs = Vec::new(); let mut used_descs = false;
while let Some(mut desc_chain) = while let Some(mut desc_chain) =
self.queues[queue_index].pop_descriptor_chain(self.mem.memory()) self.queues[queue_index].pop_descriptor_chain(self.mem.memory())
{ {
let desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?; let desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
used_descs.push((desc_chain.head_index(), desc.len()));
let data_chunk_size = size_of::<u32>(); let data_chunk_size = size_of::<u32>();
// The head contains the request type which MUST be readable. // The head contains the request type which MUST be readable.
@ -294,18 +272,24 @@ impl BalloonEpollHandler {
_ => return Err(Error::InvalidQueueIndex(queue_index)), _ => return Err(Error::InvalidQueueIndex(queue_index)),
} }
} }
self.queues[queue_index]
.add_used(desc_chain.memory(), desc_chain.head_index(), desc.len())
.map_err(Error::QueueAddUsed)?;
used_descs = true;
} }
self.notify_queue(queue_index, used_descs) if used_descs {
self.signal(VirtioInterruptType::Queue(queue_index as u16))
} else {
Ok(())
}
} }
fn process_reporting_queue(&mut self, queue_index: usize) -> result::Result<(), Error> { fn process_reporting_queue(&mut self, queue_index: usize) -> result::Result<(), Error> {
let mem = self.mem.memory(); let mut used_descs = false;
let mut used_descs = Vec::new(); while let Some(mut desc_chain) =
self.queues[queue_index].pop_descriptor_chain(self.mem.memory())
for mut desc_chain in self.queues[queue_index]
.iter(mem)
.map_err(Error::QueueIterator)?
{ {
let mut descs_len = 0; let mut descs_len = 0;
while let Some(desc) = desc_chain.next() { while let Some(desc) = desc_chain.next() {
@ -313,10 +297,17 @@ impl BalloonEpollHandler {
Self::release_memory_range(desc_chain.memory(), desc.addr(), desc.len() as usize)?; Self::release_memory_range(desc_chain.memory(), desc.addr(), desc.len() as usize)?;
} }
used_descs.push((desc_chain.head_index(), descs_len)); self.queues[queue_index]
.add_used(desc_chain.memory(), desc_chain.head_index(), descs_len)
.map_err(Error::QueueAddUsed)?;
used_descs = true;
} }
self.notify_queue(queue_index, used_descs) if used_descs {
self.signal(VirtioInterruptType::Queue(queue_index as u16))
} else {
Ok(())
}
} }
fn run( fn run(

View File

@ -105,8 +105,7 @@ impl BlockEpollHandler {
fn process_queue_submit(&mut self) -> Result<bool> { fn process_queue_submit(&mut self) -> Result<bool> {
let queue = &mut self.queue; let queue = &mut self.queue;
let mut used_desc_heads = Vec::new(); let mut used_descs = false;
let mut used_count = 0;
while let Some(mut desc_chain) = queue.pop_descriptor_chain(self.mem.memory()) { 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()) let mut request = Request::parse(&mut desc_chain, self.access_platform.as_ref())
@ -166,26 +165,20 @@ impl BlockEpollHandler {
// If no asynchronous operation has been submitted, we can // If no asynchronous operation has been submitted, we can
// simply return the used descriptor. // simply return the used descriptor.
used_desc_heads.push((desc_chain.head_index(), 0)); queue
used_count += 1; .add_used(desc_chain.memory(), desc_chain.head_index(), 0)
.map_err(Error::QueueAddUsed)?;
used_descs = true;
} }
} }
let mem = self.mem.memory(); Ok(used_descs)
for &(desc_index, len) in used_desc_heads.iter() {
queue
.add_used(mem.deref(), desc_index, len)
.map_err(Error::QueueAddUsed)?;
}
Ok(used_count > 0)
} }
fn process_queue_complete(&mut self) -> Result<bool> { fn process_queue_complete(&mut self) -> Result<bool> {
let queue = &mut self.queue; let queue = &mut self.queue;
let mut used_desc_heads = Vec::new(); let mut used_descs = false;
let mut used_count = 0;
let mem = self.mem.memory(); let mem = self.mem.memory();
let mut read_bytes = Wrapping(0); let mut read_bytes = Wrapping(0);
let mut write_bytes = Wrapping(0); let mut write_bytes = Wrapping(0);
@ -234,14 +227,10 @@ impl BlockEpollHandler {
// checked that the status_addr was valid. // checked that the status_addr was valid.
mem.write_obj(status, request.status_addr).unwrap(); mem.write_obj(status, request.status_addr).unwrap();
used_desc_heads.push((desc_index as u16, len));
used_count += 1;
}
for &(desc_index, len) in used_desc_heads.iter() {
queue queue
.add_used(mem.deref(), desc_index, len) .add_used(mem.deref(), desc_index as u16, len)
.map_err(Error::QueueAddUsed)?; .map_err(Error::QueueAddUsed)?;
used_descs = true;
} }
self.counters self.counters
@ -258,7 +247,7 @@ impl BlockEpollHandler {
.read_ops .read_ops
.fetch_add(read_ops.0, Ordering::AcqRel); .fetch_add(read_ops.0, Ordering::AcqRel);
Ok(used_count > 0) Ok(used_descs)
} }
fn signal_used_queue(&self) -> result::Result<(), DeviceError> { fn signal_used_queue(&self) -> result::Result<(), DeviceError> {

View File

@ -18,7 +18,6 @@ use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::ops::Deref;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
@ -137,8 +136,7 @@ impl ConsoleEpollHandler {
fn process_input_queue(&mut self) -> bool { fn process_input_queue(&mut self) -> bool {
let mut in_buffer = self.in_buffer.lock().unwrap(); let mut in_buffer = self.in_buffer.lock().unwrap();
let recv_queue = &mut self.queues[0]; //receiveq let recv_queue = &mut self.queues[0]; //receiveq
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize]; let mut used_descs = false;
let mut used_count = 0;
if in_buffer.is_empty() { if in_buffer.is_empty() {
return false; return false;
@ -159,20 +157,17 @@ impl ConsoleEpollHandler {
break; break;
} }
used_desc_heads[used_count] = (desc_chain.head_index(), len); recv_queue
used_count += 1; .add_used(desc_chain.memory(), desc_chain.head_index(), len)
.unwrap();
used_descs = true;
if in_buffer.is_empty() { if in_buffer.is_empty() {
break; break;
} }
} }
let mem = self.mem.memory(); used_descs
for &(desc_index, len) in &used_desc_heads[..used_count] {
recv_queue.add_used(mem.deref(), desc_index, len).unwrap();
}
used_count > 0
} }
/* /*
@ -184,8 +179,7 @@ impl ConsoleEpollHandler {
*/ */
fn process_output_queue(&mut self) -> bool { fn process_output_queue(&mut self) -> bool {
let trans_queue = &mut self.queues[1]; //transmitq let trans_queue = &mut self.queues[1]; //transmitq
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize]; let mut used_descs = false;
let mut used_count = 0;
while let Some(mut desc_chain) = trans_queue.pop_descriptor_chain(self.mem.memory()) { while let Some(mut desc_chain) = trans_queue.pop_descriptor_chain(self.mem.memory()) {
let desc = desc_chain.next().unwrap(); let desc = desc_chain.next().unwrap();
@ -198,15 +192,13 @@ impl ConsoleEpollHandler {
); );
let _ = out.flush(); let _ = out.flush();
} }
used_desc_heads[used_count] = (desc_chain.head_index(), desc.len()); trans_queue
used_count += 1; .add_used(desc_chain.memory(), desc_chain.head_index(), desc.len())
.unwrap();
used_descs = true;
} }
let mem = self.mem.memory(); used_descs
for &(desc_index, len) in &used_desc_heads[..used_count] {
trans_queue.add_used(mem.deref(), desc_index, len).unwrap();
}
used_count > 0
} }
fn signal_used_queue(&self, queue_index: u16) -> result::Result<(), DeviceError> { fn signal_used_queue(&self, queue_index: u16) -> result::Result<(), DeviceError> {

View File

@ -17,7 +17,6 @@ use std::fmt::{self, Display};
use std::io; use std::io;
use std::mem::size_of; use std::mem::size_of;
use std::ops::Bound::Included; use std::ops::Bound::Included;
use std::ops::Deref;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
@ -674,8 +673,7 @@ struct IommuEpollHandler {
impl IommuEpollHandler { impl IommuEpollHandler {
fn request_queue(&mut self) -> bool { fn request_queue(&mut self) -> bool {
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize]; let mut used_descs = false;
let mut used_count = 0;
while let Some(mut desc_chain) = self.queues[0].pop_descriptor_chain(self.mem.memory()) { while let Some(mut desc_chain) = self.queues[0].pop_descriptor_chain(self.mem.memory()) {
let len = match Request::parse( let len = match Request::parse(
&mut desc_chain, &mut desc_chain,
@ -690,17 +688,13 @@ impl IommuEpollHandler {
} }
}; };
used_desc_heads[used_count] = (desc_chain.head_index(), len); self.queues[0]
used_count += 1; .add_used(desc_chain.memory(), desc_chain.head_index(), len)
.unwrap();
used_descs = true;
} }
let mem = self.mem.memory(); used_descs
for &(desc_index, len) in &used_desc_heads[..used_count] {
self.queues[0]
.add_used(mem.deref(), desc_index, len)
.unwrap();
}
used_count > 0
} }
fn event_queue(&mut self) -> bool { fn event_queue(&mut self) -> bool {

View File

@ -27,7 +27,6 @@ use seccompiler::SeccompAction;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::io; use std::io;
use std::mem::size_of; use std::mem::size_of;
use std::ops::Deref;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use std::result; use std::result;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
@ -665,20 +664,10 @@ impl MemEpollHandler {
} }
fn process_queue(&mut self) -> bool { fn process_queue(&mut self) -> bool {
let mut request_list = Vec::new(); let mut used_descs = false;
let mut used_count = 0;
while let Some(mut desc_chain) = self.queue.pop_descriptor_chain(self.mem.memory()) { while let Some(mut desc_chain) = self.queue.pop_descriptor_chain(self.mem.memory()) {
request_list.push(( let len = match Request::parse(&mut desc_chain) {
desc_chain.head_index(),
Request::parse(&mut desc_chain),
desc_chain.memory().clone(),
));
}
let mem = self.mem.memory();
for (head_index, request, memory) in request_list {
let len = match request {
Err(e) => { Err(e) => {
error!("failed parse VirtioMemReq: {:?}", e); error!("failed parse VirtioMemReq: {:?}", e);
0 0
@ -687,21 +676,21 @@ impl MemEpollHandler {
VIRTIO_MEM_REQ_PLUG => { VIRTIO_MEM_REQ_PLUG => {
let resp_type = let resp_type =
self.state_change_request(r.req.addr, r.req.nb_blocks, true); self.state_change_request(r.req.addr, r.req.nb_blocks, true);
r.send_response(&memory, resp_type, 0u16) r.send_response(desc_chain.memory(), resp_type, 0u16)
} }
VIRTIO_MEM_REQ_UNPLUG => { VIRTIO_MEM_REQ_UNPLUG => {
let resp_type = let resp_type =
self.state_change_request(r.req.addr, r.req.nb_blocks, false); self.state_change_request(r.req.addr, r.req.nb_blocks, false);
r.send_response(&memory, resp_type, 0u16) r.send_response(desc_chain.memory(), resp_type, 0u16)
} }
VIRTIO_MEM_REQ_UNPLUG_ALL => { VIRTIO_MEM_REQ_UNPLUG_ALL => {
let resp_type = self.unplug_all(); let resp_type = self.unplug_all();
r.send_response(&memory, resp_type, 0u16) r.send_response(desc_chain.memory(), resp_type, 0u16)
} }
VIRTIO_MEM_REQ_STATE => { VIRTIO_MEM_REQ_STATE => {
let (resp_type, resp_state) = let (resp_type, resp_state) =
self.state_request(r.req.addr, r.req.nb_blocks); self.state_request(r.req.addr, r.req.nb_blocks);
r.send_response(&memory, resp_type, resp_state) r.send_response(desc_chain.memory(), resp_type, resp_state)
} }
_ => { _ => {
error!("VirtioMemReq unknown request type {:?}", r.req.req_type); error!("VirtioMemReq unknown request type {:?}", r.req.req_type);
@ -710,11 +699,13 @@ impl MemEpollHandler {
}, },
}; };
self.queue.add_used(mem.deref(), head_index, len).unwrap(); self.queue
used_count += 1; .add_used(desc_chain.memory(), desc_chain.head_index(), len)
.unwrap();
used_descs = true;
} }
used_count > 0 used_descs
} }
fn run( fn run(

View File

@ -21,7 +21,6 @@ use std::fmt::{self, Display};
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::mem::size_of; use std::mem::size_of;
use std::ops::Deref;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
@ -178,8 +177,7 @@ struct PmemEpollHandler {
impl PmemEpollHandler { impl PmemEpollHandler {
fn process_queue(&mut self) -> bool { fn process_queue(&mut self) -> bool {
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize]; let mut used_descs = false;
let mut used_count = 0;
while let Some(mut desc_chain) = self.queue.pop_descriptor_chain(self.mem.memory()) { 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()) { let len = match Request::parse(&mut desc_chain, self.access_platform.as_ref()) {
Ok(ref req) if (req.type_ == RequestType::Flush) => { Ok(ref req) if (req.type_ == RequestType::Flush) => {
@ -211,15 +209,13 @@ impl PmemEpollHandler {
} }
}; };
used_desc_heads[used_count] = (desc_chain.head_index(), len); self.queue
used_count += 1; .add_used(desc_chain.memory(), desc_chain.head_index(), len)
.unwrap();
used_descs = true;
} }
let mem = self.mem.memory(); used_descs
for &(desc_index, len) in &used_desc_heads[..used_count] {
self.queue.add_used(mem.deref(), desc_index, len).unwrap();
}
used_count > 0
} }
fn signal_used_queue(&self) -> result::Result<(), DeviceError> { fn signal_used_queue(&self) -> result::Result<(), DeviceError> {

View File

@ -15,7 +15,6 @@ use crate::{VirtioInterrupt, VirtioInterruptType};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::ops::Deref;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::result; use std::result;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
@ -50,8 +49,7 @@ impl RngEpollHandler {
fn process_queue(&mut self) -> bool { fn process_queue(&mut self) -> bool {
let queue = &mut self.queue; let queue = &mut self.queue;
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize]; let mut used_descs = false;
let mut used_count = 0;
while let Some(mut desc_chain) = queue.pop_descriptor_chain(self.mem.memory()) { while let Some(mut desc_chain) = queue.pop_descriptor_chain(self.mem.memory()) {
let desc = desc_chain.next().unwrap(); let desc = desc_chain.next().unwrap();
let mut len = 0; let mut len = 0;
@ -73,15 +71,13 @@ impl RngEpollHandler {
} }
} }
used_desc_heads[used_count] = (desc_chain.head_index(), len); queue
used_count += 1; .add_used(desc_chain.memory(), desc_chain.head_index(), len)
.unwrap();
used_descs = true;
} }
let mem = self.mem.memory(); used_descs
for &(desc_index, len) in &used_desc_heads[..used_count] {
queue.add_used(mem.deref(), desc_index, len).unwrap();
}
used_count > 0
} }
fn signal_used_queue(&self) -> result::Result<(), DeviceError> { fn signal_used_queue(&self) -> result::Result<(), DeviceError> {

View File

@ -40,7 +40,6 @@ use crate::{
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::io; use std::io;
use std::ops::Deref;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::path::PathBuf; use std::path::PathBuf;
use std::result; use std::result;
@ -125,8 +124,7 @@ where
fn process_rx(&mut self) -> result::Result<(), DeviceError> { fn process_rx(&mut self) -> result::Result<(), DeviceError> {
debug!("vsock: epoll_handler::process_rx()"); debug!("vsock: epoll_handler::process_rx()");
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize]; let mut used_descs = false;
let mut used_count = 0;
while let Some(mut desc_chain) = self.queues[0].pop_descriptor_chain(self.mem.memory()) { while let Some(mut desc_chain) = self.queues[0].pop_descriptor_chain(self.mem.memory()) {
let used_len = match VsockPacket::from_rx_virtq_head( let used_len = match VsockPacket::from_rx_virtq_head(
@ -149,18 +147,13 @@ where
} }
}; };
used_desc_heads[used_count] = (desc_chain.head_index(), used_len);
used_count += 1;
}
let mem = self.mem.memory();
for &(desc_index, len) in &used_desc_heads[..used_count] {
self.queues[0] self.queues[0]
.add_used(mem.deref(), desc_index, len) .add_used(desc_chain.memory(), desc_chain.head_index(), used_len)
.map_err(DeviceError::QueueAddUsed)?; .map_err(DeviceError::QueueAddUsed)?;
used_descs = true;
} }
if used_count > 0 { if used_descs {
self.signal_used_queue(0) self.signal_used_queue(0)
} else { } else {
Ok(()) Ok(())
@ -173,8 +166,7 @@ where
fn process_tx(&mut self) -> result::Result<(), DeviceError> { fn process_tx(&mut self) -> result::Result<(), DeviceError> {
debug!("vsock: epoll_handler::process_tx()"); debug!("vsock: epoll_handler::process_tx()");
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize]; let mut used_descs = false;
let mut used_count = 0;
while let Some(mut desc_chain) = self.queues[1].pop_descriptor_chain(self.mem.memory()) { while let Some(mut desc_chain) = self.queues[1].pop_descriptor_chain(self.mem.memory()) {
let pkt = match VsockPacket::from_tx_virtq_head( let pkt = match VsockPacket::from_tx_virtq_head(
@ -184,8 +176,10 @@ where
Ok(pkt) => pkt, Ok(pkt) => pkt,
Err(e) => { Err(e) => {
error!("vsock: error reading TX packet: {:?}", e); error!("vsock: error reading TX packet: {:?}", e);
used_desc_heads[used_count] = (desc_chain.head_index(), 0); self.queues[1]
used_count += 1; .add_used(desc_chain.memory(), desc_chain.head_index(), 0)
.map_err(DeviceError::QueueAddUsed)?;
used_descs = true;
continue; continue;
} }
}; };
@ -195,18 +189,13 @@ where
break; break;
} }
used_desc_heads[used_count] = (desc_chain.head_index(), 0);
used_count += 1;
}
let mem = self.mem.memory();
for &(desc_index, len) in &used_desc_heads[..used_count] {
self.queues[1] self.queues[1]
.add_used(mem.deref(), desc_index, len) .add_used(desc_chain.memory(), desc_chain.head_index(), 0)
.map_err(DeviceError::QueueAddUsed)?; .map_err(DeviceError::QueueAddUsed)?;
used_descs = true;
} }
if used_count > 0 { if used_descs {
self.signal_used_queue(1) self.signal_used_queue(1)
} else { } else {
Ok(()) Ok(())