mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
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:
parent
87f57f7c1e
commit
a4859ffe85
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
let queue = vring.get_queue_mut();
|
if vring
|
||||||
if queue.add_used(mem.deref(), *desc_head, *len).is_ok() {
|
.get_queue_mut()
|
||||||
if queue.needs_notification(mem.deref()).unwrap() {
|
.needs_notification(self.mem.memory().deref())
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
debug!("signalling queue");
|
debug!("signalling queue");
|
||||||
needs_signalling = true;
|
needs_signalling = true;
|
||||||
} else {
|
} else {
|
||||||
debug!("omitting signal (event_idx)");
|
debug!("omitting signal (event_idx)");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} 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;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if needs_signalling {
|
if needs_signalling {
|
||||||
vring.signal_used_queue().unwrap();
|
vring.signal_used_queue().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
!used_desc_heads.is_empty()
|
used_descs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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));
|
|
||||||
used_count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mem = self.mem.memory();
|
|
||||||
for &(desc_index, len) in used_desc_heads.iter() {
|
|
||||||
queue
|
queue
|
||||||
.add_used(mem.deref(), desc_index, len)
|
.add_used(desc_chain.memory(), desc_chain.head_index(), 0)
|
||||||
.map_err(Error::QueueAddUsed)?;
|
.map_err(Error::QueueAddUsed)?;
|
||||||
|
used_descs = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(used_count > 0)
|
Ok(used_descs)
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
||||||
|
@ -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> {
|
||||||
|
@ -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 {
|
||||||
|
@ -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(
|
||||||
|
@ -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> {
|
||||||
|
@ -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> {
|
||||||
|
@ -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(())
|
||||||
|
Loading…
Reference in New Issue
Block a user