virtio-devices: Pass a list of tuples for virtqueues

Instead of passing separately a list of Queues and the equivalent list
of EventFds, we consolidate these two through a tuple along with the
queue index.

The queue index can be very useful if looking for the actual index
related to the queue, no matter if other queues have been enabled or
not.

It's also convenient to have the EventFd associated with the Queue so
that we don't have to carry two lists with the same amount of items.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2022-07-20 16:45:49 +02:00
parent 423c54eafe
commit 3f62a172b2
20 changed files with 154 additions and 145 deletions

View File

@ -84,9 +84,8 @@ fuzz_target!(|bytes| {
q.state.ready = true;
q.state.size = QUEUE_SIZE / 2;
let queue_evts: Vec<EventFd> = vec![EventFd::new(0).unwrap()];
let queue_fd = queue_evts[0].as_raw_fd();
let queue_evt = unsafe { EventFd::from_raw_fd(libc::dup(queue_fd)) };
let evt = EventFd::new(0).unwrap();
let queue_evt = unsafe { EventFd::from_raw_fd(libc::dup(evt.as_raw_fd())) };
let shm = memfd_create(&ffi::CString::new("fuzz").unwrap(), 0).unwrap();
let disk_file: File = unsafe { File::from_raw_fd(shm) };
@ -110,8 +109,7 @@ fuzz_target!(|bytes| {
.activate(
guest_memory,
Arc::new(NoopVirtioInterrupt {}),
vec![q],
queue_evts,
vec![(0, q, evt)],
)
.ok();

View File

@ -542,17 +542,23 @@ impl VirtioDevice for Balloon {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let inflate_queue_evt = queue_evts.remove(0);
let deflate_queue_evt = queue_evts.remove(0);
let mut virtqueues = Vec::new();
let (_, queue, queue_evt) = queues.remove(0);
virtqueues.push(queue);
let inflate_queue_evt = queue_evt;
let (_, queue, queue_evt) = queues.remove(0);
virtqueues.push(queue);
let deflate_queue_evt = queue_evt;
let reporting_queue_evt =
if self.common.feature_acked(VIRTIO_BALLOON_F_REPORTING) && !queue_evts.is_empty() {
Some(queue_evts.remove(0))
if self.common.feature_acked(VIRTIO_BALLOON_F_REPORTING) && !queues.is_empty() {
let (_, queue, queue_evt) = queues.remove(0);
virtqueues.push(queue);
Some(queue_evt)
} else {
None
};
@ -563,7 +569,7 @@ impl VirtioDevice for Balloon {
error!("failed to clone resize EventFd: {:?}", e);
ActivateError::BadActivate
})?,
queues,
queues: virtqueues,
interrupt_cb,
inflate_queue_evt,
deflate_queue_evt,

View File

@ -587,18 +587,16 @@ impl VirtioDevice for Block {
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let disk_image_id = build_disk_image_id(&self.disk_path);
self.update_writeback();
let mut epoll_threads = Vec::new();
for i in 0..queues.len() {
let queue_evt = queue_evts.remove(0);
let queue = queues.remove(0);
let (_, queue, queue_evt) = queues.remove(0);
let queue_size = queue.state.size;
let (kill_evt, pause_evt) = self.common.dup_eventfds();

View File

@ -490,10 +490,9 @@ impl VirtioDevice for Console {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
self.resizer
.acked_features
.store(self.common.acked_features, Ordering::Relaxed);
@ -507,13 +506,21 @@ impl VirtioDevice for Console {
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let input_evt = EventFd::new(EFD_NONBLOCK).unwrap();
let mut virtqueues = Vec::new();
let (_, queue, queue_evt) = queues.remove(0);
virtqueues.push(queue);
let input_queue_evt = queue_evt;
let (_, queue, queue_evt) = queues.remove(0);
virtqueues.push(queue);
let output_queue_evt = queue_evt;
let mut handler = ConsoleEpollHandler {
queues,
queues: virtqueues,
interrupt_cb,
in_buffer: self.in_buffer.clone(),
endpoint: self.endpoint.clone(),
input_queue_evt: queue_evts.remove(0),
output_queue_evt: queue_evts.remove(0),
input_queue_evt,
output_queue_evt,
input_evt,
config_evt: self.resizer.config_evt.try_clone().unwrap(),
resize_pipe: self.resize_pipe.as_ref().map(|p| p.try_clone().unwrap()),

View File

@ -107,8 +107,7 @@ pub trait VirtioDevice: Send {
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_evt: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult;
/// Optionally deactivates this device and returns ownership of the guest memory map, interrupt
@ -251,19 +250,9 @@ impl VirtioCommon {
pub fn activate(
&mut self,
queues: &[Queue<GuestMemoryAtomic<GuestMemoryMmap>>],
queue_evts: &[EventFd],
queues: &[(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)],
interrupt_cb: &Arc<dyn VirtioInterrupt>,
) -> ActivateResult {
if queues.len() != queue_evts.len() {
error!(
"Cannot activate: length mismatch: queue_evts={} queues={}",
queue_evts.len(),
queues.len()
);
return Err(ActivateError::BadActivate);
}
if queues.len() < self.min_queues.into() {
error!(
"Number of enabled queues lower than min: {} vs {}",
@ -290,7 +279,7 @@ impl VirtioCommon {
self.interrupt_cb = Some(interrupt_cb.clone());
let mut tmp_queue_evts: Vec<EventFd> = Vec::new();
for queue_evt in queue_evts.iter() {
for (_, _, queue_evt) in queues.iter() {
// Save the queue EventFD as we need to return it on reset
// but clone it to pass into the thread.
tmp_queue_evts.push(queue_evt.try_clone().map_err(|e| {

View File

@ -1052,13 +1052,20 @@ impl VirtioDevice for Iommu {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let mut virtqueues = Vec::new();
let mut queue_evts = Vec::new();
for (_, queue, queue_evt) in queues {
virtqueues.push(queue);
queue_evts.push(queue_evt);
}
let mut handler = IommuEpollHandler {
queues,
queues: virtqueues,
interrupt_cb,
queue_evts,
kill_evt,

View File

@ -1004,20 +1004,22 @@ impl VirtioDevice for Mem {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let (_, queue, queue_evt) = queues.remove(0);
let mut handler = MemEpollHandler {
host_addr: self.host_addr,
host_fd: self.host_fd,
blocks_state: Arc::clone(&self.blocks_state),
config: self.config.clone(),
resize: self.resize.clone(),
queue: queues.remove(0),
queue,
interrupt_cb,
queue_evt: queue_evts.remove(0),
queue_evt,
kill_evt,
pause_evt,
hugepages: self.hugepages,

View File

@ -585,17 +585,15 @@ impl VirtioDevice for Net {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let num_queues = queues.len();
let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
if self.common.feature_acked(VIRTIO_NET_F_CTRL_VQ.into()) && num_queues % 2 != 0 {
let ctrl_queue_index = num_queues - 1;
let mut ctrl_queue = queues.remove(ctrl_queue_index);
let ctrl_queue_evt = queue_evts.remove(ctrl_queue_index);
let (_, mut ctrl_queue, ctrl_queue_evt) = queues.remove(ctrl_queue_index);
ctrl_queue.set_event_idx(event_idx);
@ -641,11 +639,13 @@ impl VirtioDevice for Net {
let tx = TxVirtio::new();
let rx_tap_listening = false;
let mut queue_pair = vec![queues.remove(0), queues.remove(0)];
let (_, queue_0, queue_evt_0) = queues.remove(0);
let (_, queue_1, queue_evt_1) = queues.remove(0);
let mut queue_pair = vec![queue_0, queue_1];
queue_pair[0].set_event_idx(event_idx);
queue_pair[1].set_event_idx(event_idx);
let queue_evt_pair = vec![queue_evts.remove(0), queue_evts.remove(0)];
let queue_evt_pair = vec![queue_evt_0, queue_evt_1];
let (kill_evt, pause_evt) = self.common.dup_eventfds();

View File

@ -379,21 +379,23 @@ impl VirtioDevice for Pmem {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let (kill_evt, pause_evt) = self.common.dup_eventfds();
if let Some(disk) = self.disk.as_ref() {
let disk = disk.try_clone().map_err(|e| {
error!("failed cloning pmem disk: {}", e);
ActivateError::BadActivate
})?;
let (_, queue, queue_evt) = queues.remove(0);
let mut handler = PmemEpollHandler {
queue: queues.remove(0),
queue,
disk,
interrupt_cb,
queue_evt: queue_evts.remove(0),
queue_evt,
kill_evt,
pause_evt,
access_platform: self.common.access_platform.clone(),

View File

@ -35,7 +35,7 @@ const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE];
const QUEUE_AVAIL_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
struct RngEpollHandler {
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue: Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
random_file: File,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queue_evt: EventFd,
@ -46,7 +46,7 @@ struct RngEpollHandler {
impl RngEpollHandler {
fn process_queue(&mut self) -> bool {
let queue = &mut self.queues[0];
let queue = &mut self.queue;
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
let mut used_count = 0;
@ -219,10 +219,9 @@ impl VirtioDevice for Rng {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let (kill_evt, pause_evt) = self.common.dup_eventfds();
if let Some(file) = self.random_file.as_ref() {
@ -230,11 +229,14 @@ impl VirtioDevice for Rng {
error!("failed cloning rng source: {}", e);
ActivateError::BadActivate
})?;
let (_, queue, queue_evt) = queues.remove(0);
let mut handler = RngEpollHandler {
queues,
queue,
random_file,
interrupt_cb,
queue_evt: queue_evts.remove(0),
queue_evt,
kill_evt,
pause_evt,
access_platform: self.common.access_platform.clone(),

View File

@ -385,8 +385,7 @@ mod tests {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
_interrupt_evt: Arc<dyn VirtioInterrupt>,
_queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
_queue_evts: Vec<EventFd>,
_queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
Ok(())
}

View File

@ -292,8 +292,8 @@ pub struct VirtioPciDeviceActivator {
memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
device: Arc<Mutex<dyn VirtioDevice>>,
device_activated: Arc<AtomicBool>,
queues: Option<Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>>,
queue_evts: Option<Vec<EventFd>>,
#[allow(clippy::type_complexity)]
queues: Option<Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>>,
barrier: Option<Arc<Barrier>>,
id: String,
}
@ -304,7 +304,6 @@ impl VirtioPciDeviceActivator {
self.memory.take().unwrap(),
self.interrupt.take().unwrap(),
self.queues.take().unwrap(),
self.queue_evts.take().unwrap(),
)?;
self.device_activated.store(true, Ordering::SeqCst);
@ -700,7 +699,6 @@ impl VirtioPciDevice {
fn prepare_activator(&mut self, barrier: Option<Arc<Barrier>>) -> VirtioPciDeviceActivator {
let mut queues = Vec::new();
let mut queue_evts = Vec::new();
for (queue_index, queue) in self.queues.iter().enumerate() {
if !queue.state.ready {
@ -711,8 +709,11 @@ impl VirtioPciDevice {
error!("Queue {} is not valid", queue_index);
}
queues.push(vm_virtio::clone_queue(queue));
queue_evts.push(self.queue_evts[queue_index].try_clone().unwrap());
queues.push((
queue_index,
vm_virtio::clone_queue(queue),
self.queue_evts[queue_index].try_clone().unwrap(),
));
}
VirtioPciDeviceActivator {
@ -721,7 +722,6 @@ impl VirtioPciDevice {
device: self.device.clone(),
queues: Some(queues),
device_activated: self.device_activated.clone(),
queue_evts: Some(queue_evts),
barrier,
id: self.id.clone(),
}

View File

@ -145,8 +145,7 @@ impl Vdpa {
&mut self,
_mem: &GuestMemoryMmap,
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> Result<()> {
self.vhost
.set_features(self.common.acked_features)
@ -155,11 +154,11 @@ impl Vdpa {
.set_backend_features(self.backend_features)
.map_err(Error::SetBackendFeatures)?;
for (queue_index, queue) in queues.iter().enumerate() {
for (queue_index, queue, queue_evt) in queues.iter() {
let queue_max_size = queue.max_size();
let queue_size = queue.state.size;
self.vhost
.set_vring_num(queue_index, queue_size)
.set_vring_num(*queue_index, queue_size)
.map_err(Error::SetVringNum)?;
let config_data = VringConfigData {
@ -194,11 +193,11 @@ impl Vdpa {
};
self.vhost
.set_vring_addr(queue_index, &config_data)
.set_vring_addr(*queue_index, &config_data)
.map_err(Error::SetVringAddr)?;
self.vhost
.set_vring_base(
queue_index,
*queue_index,
queue
.avail_idx(Ordering::Acquire)
.map_err(Error::GetAvailableIndex)?
@ -207,15 +206,15 @@ impl Vdpa {
.map_err(Error::SetVringBase)?;
if let Some(eventfd) =
virtio_interrupt.notifier(VirtioInterruptType::Queue(queue_index as u16))
virtio_interrupt.notifier(VirtioInterruptType::Queue(*queue_index as u16))
{
self.vhost
.set_vring_call(queue_index, &eventfd)
.set_vring_call(*queue_index, &eventfd)
.map_err(Error::SetVringCall)?;
}
self.vhost
.set_vring_kick(queue_index, &queue_evts[queue_index])
.set_vring_kick(*queue_index, queue_evt)
.map_err(Error::SetVringKick)?;
}
@ -297,10 +296,9 @@ impl VirtioDevice for Vdpa {
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
virtio_interrupt: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.activate_vdpa(&mem.memory(), &virtio_interrupt, queues, queue_evts)
self.activate_vdpa(&mem.memory(), &virtio_interrupt, queues)
.map_err(ActivateError::ActivateVdpa)?;
// Store the virtio interrupt handler as we need to return it on reset

View File

@ -292,10 +292,9 @@ impl VirtioDevice for Blk {
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
self.guest_memory = Some(mem.clone());
let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
@ -307,7 +306,6 @@ impl VirtioDevice for Blk {
let mut handler = self.vu_common.activate(
mem,
queues,
queue_evts,
interrupt_cb,
self.common.acked_features,
slave_req_handler,

View File

@ -504,10 +504,9 @@ impl VirtioDevice for Fs {
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
self.guest_memory = Some(mem.clone());
// Initialize slave communication.
@ -547,7 +546,6 @@ impl VirtioDevice for Fs {
let mut handler = self.vu_common.activate(
mem,
queues,
queue_evts,
interrupt_cb,
self.common.acked_features,
slave_req_handler,

View File

@ -167,8 +167,7 @@ pub struct VhostUserEpollHandler<S: VhostUserMasterReqHandler> {
pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
pub kill_evt: EventFd,
pub pause_evt: EventFd,
pub queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
pub queue_evts: Vec<EventFd>,
pub queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
pub virtio_interrupt: Arc<dyn VirtioInterrupt>,
pub acked_features: u64,
pub acked_protocol_features: u64,
@ -224,10 +223,9 @@ impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
vhost_user
.reinitialize_vhost_user(
self.mem.memory().deref(),
self.queues.iter().map(vm_virtio::clone_queue).collect(),
self.queue_evts
self.queues
.iter()
.map(|q| q.try_clone().unwrap())
.map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap()))
.collect(),
&self.virtio_interrupt,
self.acked_features,
@ -299,8 +297,7 @@ impl VhostUserCommon {
pub fn activate<T: VhostUserMasterReqHandler>(
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
acked_features: u64,
slave_req_handler: Option<MasterReqHandler<T>>,
@ -324,8 +321,10 @@ impl VhostUserCommon {
.unwrap()
.setup_vhost_user(
&mem.memory(),
queues.iter().map(vm_virtio::clone_queue).collect(),
queue_evts.iter().map(|q| q.try_clone().unwrap()).collect(),
queues
.iter()
.map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap()))
.collect(),
&interrupt_cb,
acked_features,
&slave_req_handler,
@ -339,7 +338,6 @@ impl VhostUserCommon {
kill_evt,
pause_evt,
queues,
queue_evts,
virtio_interrupt: interrupt_cb,
acked_features,
acked_protocol_features: self.acked_protocol_features,

View File

@ -272,18 +272,16 @@ impl VirtioDevice for Net {
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
self.guest_memory = Some(mem.clone());
let num_queues = queues.len();
let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
if self.common.feature_acked(VIRTIO_NET_F_CTRL_VQ.into()) && num_queues % 2 != 0 {
let ctrl_queue_index = num_queues - 1;
let mut ctrl_queue = queues.remove(ctrl_queue_index);
let ctrl_queue_evt = queue_evts.remove(ctrl_queue_index);
let (_, mut ctrl_queue, ctrl_queue_evt) = queues.remove(ctrl_queue_index);
ctrl_queue.set_event_idx(event_idx);
@ -336,7 +334,6 @@ impl VirtioDevice for Net {
let mut handler = self.vu_common.activate(
mem,
queues,
queue_evts,
interrupt_cb,
backend_acked_features,
slave_req_handler,

View File

@ -151,8 +151,7 @@ impl VhostUserHandle {
pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
&mut self,
mem: &GuestMemoryMmap,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
acked_features: u64,
slave_req_handler: &Option<MasterReqHandler<S>>,
@ -171,9 +170,9 @@ impl VhostUserHandle {
// Send set_vring_num here, since it could tell backends, like SPDK,
// how many virt queues to be handled, which backend required to know
// at early stage.
for (queue_index, queue) in queues.iter().enumerate() {
for (queue_index, queue, _) in queues.iter() {
self.vu
.set_vring_num(queue_index, queue.state.size)
.set_vring_num(*queue_index, queue.state.size)
.map_err(Error::VhostUserSetVringNum)?;
}
@ -184,7 +183,7 @@ impl VhostUserHandle {
mmap_size: 0,
mmap_offset: 0,
num_queues: queues.len() as u16,
queue_size: queues[0].state.size,
queue_size: queues[0].1.state.size,
};
let (info, fd) = self
.vu
@ -202,7 +201,7 @@ impl VhostUserHandle {
let num_queues = queues.len() as usize;
let mut vrings_info = Vec::new();
for (queue_index, queue) in queues.into_iter().enumerate() {
for (queue_index, queue, queue_evt) in queues.iter() {
let actual_size: usize = queue.state.size.try_into().unwrap();
let config_data = VringConfigData {
@ -240,11 +239,11 @@ impl VhostUserHandle {
});
self.vu
.set_vring_addr(queue_index, &config_data)
.set_vring_addr(*queue_index, &config_data)
.map_err(Error::VhostUserSetVringAddr)?;
self.vu
.set_vring_base(
queue_index,
*queue_index,
queue
.avail_idx(Ordering::Acquire)
.map_err(Error::GetAvailableIndex)?
@ -253,15 +252,15 @@ impl VhostUserHandle {
.map_err(Error::VhostUserSetVringBase)?;
if let Some(eventfd) =
virtio_interrupt.notifier(VirtioInterruptType::Queue(queue_index as u16))
virtio_interrupt.notifier(VirtioInterruptType::Queue(*queue_index as u16))
{
self.vu
.set_vring_call(queue_index, &eventfd)
.set_vring_call(*queue_index, &eventfd)
.map_err(Error::VhostUserSetVringCall)?;
}
self.vu
.set_vring_kick(queue_index, &queue_evts[queue_index])
.set_vring_kick(*queue_index, queue_evt)
.map_err(Error::VhostUserSetVringKick)?;
}
@ -326,8 +325,7 @@ impl VhostUserHandle {
pub fn reinitialize_vhost_user<S: VhostUserMasterReqHandler>(
&mut self,
mem: &GuestMemoryMmap,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
acked_features: u64,
acked_protocol_features: u64,
@ -339,7 +337,6 @@ impl VhostUserHandle {
self.setup_vhost_user(
mem,
queues,
queue_evts,
virtio_interrupt,
acked_features,
slave_req_handler,

View File

@ -432,15 +432,21 @@ where
&mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue_evts: Vec<EventFd>,
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let mut virtqueues = Vec::new();
let mut queue_evts = Vec::new();
for (_, queue, queue_evt) in queues {
virtqueues.push(queue);
queue_evts.push(queue_evt);
}
let mut handler = VsockEpollHandler {
mem,
queues,
queues: virtqueues,
queue_evts,
kill_evt,
pause_evt,
@ -591,7 +597,6 @@ mod tests {
GuestMemoryAtomic::new(ctx.mem.clone()),
Arc::new(NoopVirtioInterrupt {}),
Vec::new(),
Vec::new(),
);
match bad_activate {
Err(ActivateError::BadActivate) => (),
@ -606,14 +611,21 @@ mod tests {
memory.clone(),
Arc::new(NoopVirtioInterrupt {}),
vec![
Queue::new(memory.clone(), 256),
Queue::new(memory.clone(), 256),
Queue::new(memory, 256),
],
vec![
EventFd::new(EFD_NONBLOCK).unwrap(),
EventFd::new(EFD_NONBLOCK).unwrap(),
EventFd::new(EFD_NONBLOCK).unwrap(),
(
0,
Queue::new(memory.clone(), 256),
EventFd::new(EFD_NONBLOCK).unwrap(),
),
(
1,
Queue::new(memory.clone(), 256),
EventFd::new(EFD_NONBLOCK).unwrap(),
),
(
2,
Queue::new(memory, 256),
EventFd::new(EFD_NONBLOCK).unwrap(),
),
],
)
.unwrap();

View File

@ -47,7 +47,7 @@ const WATCHDOG_TIMER_INTERVAL: i64 = 15;
const WATCHDOG_TIMEOUT: u64 = WATCHDOG_TIMER_INTERVAL as u64 + 5;
struct WatchdogEpollHandler {
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
queue: Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queue_evt: EventFd,
kill_evt: EventFd,
@ -61,7 +61,7 @@ impl WatchdogEpollHandler {
// The main queue is very simple - the driver "pings" the device by passing it a (write-only)
// descriptor. In response the device writes a 1 into the descriptor and returns it to the driver
fn process_queue(&mut self) -> bool {
let queue = &mut self.queues[0];
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().unwrap() {
@ -291,10 +291,9 @@ impl VirtioDevice for Watchdog {
&mut self,
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
interrupt_cb: Arc<dyn VirtioInterrupt>,
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
mut queue_evts: Vec<EventFd>,
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
) -> ActivateResult {
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
self.common.activate(&queues, &interrupt_cb)?;
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let reset_evt = self.reset_evt.try_clone().map_err(|e| {
@ -307,10 +306,12 @@ impl VirtioDevice for Watchdog {
ActivateError::BadActivate
})?;
let (_, queue, queue_evt) = queues.remove(0);
let mut handler = WatchdogEpollHandler {
queues,
queue,
interrupt_cb,
queue_evt: queue_evts.remove(0),
queue_evt,
kill_evt,
pause_evt,
timer,