From 3f62a172b2c0eecd39c9efa56eb609724d2c7a01 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Wed, 20 Jul 2022 16:45:49 +0200 Subject: [PATCH] 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 --- fuzz/fuzz_targets/block.rs | 8 ++-- virtio-devices/src/balloon.rs | 22 +++++++---- virtio-devices/src/block.rs | 8 ++-- virtio-devices/src/console.rs | 19 +++++++--- virtio-devices/src/device.rs | 17 ++------- virtio-devices/src/iommu.rs | 15 ++++++-- virtio-devices/src/mem.rs | 12 +++--- virtio-devices/src/net.rs | 14 +++---- virtio-devices/src/pmem.rs | 12 +++--- virtio-devices/src/rng.rs | 16 ++++---- .../src/transport/pci_common_config.rs | 3 +- virtio-devices/src/transport/pci_device.rs | 14 +++---- virtio-devices/src/vdpa.rs | 22 +++++------ virtio-devices/src/vhost_user/blk.rs | 6 +-- virtio-devices/src/vhost_user/fs.rs | 6 +-- virtio-devices/src/vhost_user/mod.rs | 18 ++++----- virtio-devices/src/vhost_user/net.rs | 9 ++--- .../src/vhost_user/vu_common_ctrl.rs | 25 ++++++------ virtio-devices/src/vsock/device.rs | 38 ++++++++++++------- virtio-devices/src/watchdog.rs | 15 ++++---- 20 files changed, 154 insertions(+), 145 deletions(-) diff --git a/fuzz/fuzz_targets/block.rs b/fuzz/fuzz_targets/block.rs index 2d8b235a6..8ac1a93a0 100644 --- a/fuzz/fuzz_targets/block.rs +++ b/fuzz/fuzz_targets/block.rs @@ -84,9 +84,8 @@ fuzz_target!(|bytes| { q.state.ready = true; q.state.size = QUEUE_SIZE / 2; - let queue_evts: Vec = 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(); diff --git a/virtio-devices/src/balloon.rs b/virtio-devices/src/balloon.rs index 0c523920b..d8b7c013f 100644 --- a/virtio-devices/src/balloon.rs +++ b/virtio-devices/src/balloon.rs @@ -542,17 +542,23 @@ impl VirtioDevice for Balloon { &mut self, _mem: GuestMemoryAtomic, interrupt_cb: Arc, - queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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, diff --git a/virtio-devices/src/block.rs b/virtio-devices/src/block.rs index 00619ff07..408a40504 100644 --- a/virtio-devices/src/block.rs +++ b/virtio-devices/src/block.rs @@ -587,18 +587,16 @@ impl VirtioDevice for Block { &mut self, mem: GuestMemoryAtomic, interrupt_cb: Arc, - mut queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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(); diff --git a/virtio-devices/src/console.rs b/virtio-devices/src/console.rs index 98954db83..ea0a7cf2c 100644 --- a/virtio-devices/src/console.rs +++ b/virtio-devices/src/console.rs @@ -490,10 +490,9 @@ impl VirtioDevice for Console { &mut self, _mem: GuestMemoryAtomic, interrupt_cb: Arc, - queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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()), diff --git a/virtio-devices/src/device.rs b/virtio-devices/src/device.rs index 2cf54ba56..688bf2058 100644 --- a/virtio-devices/src/device.rs +++ b/virtio-devices/src/device.rs @@ -107,8 +107,7 @@ pub trait VirtioDevice: Send { &mut self, mem: GuestMemoryAtomic, interrupt_evt: Arc, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, 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>], - queue_evts: &[EventFd], + queues: &[(usize, Queue>, EventFd)], interrupt_cb: &Arc, ) -> 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 = 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| { diff --git a/virtio-devices/src/iommu.rs b/virtio-devices/src/iommu.rs index 8f86e0cce..6223fffe4 100644 --- a/virtio-devices/src/iommu.rs +++ b/virtio-devices/src/iommu.rs @@ -1052,13 +1052,20 @@ impl VirtioDevice for Iommu { &mut self, _mem: GuestMemoryAtomic, interrupt_cb: Arc, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, 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, diff --git a/virtio-devices/src/mem.rs b/virtio-devices/src/mem.rs index 3f5e6d7db..555906e0a 100644 --- a/virtio-devices/src/mem.rs +++ b/virtio-devices/src/mem.rs @@ -1004,20 +1004,22 @@ impl VirtioDevice for Mem { &mut self, _mem: GuestMemoryAtomic, interrupt_cb: Arc, - mut queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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, diff --git a/virtio-devices/src/net.rs b/virtio-devices/src/net.rs index d162e0cbb..3475a5cb4 100644 --- a/virtio-devices/src/net.rs +++ b/virtio-devices/src/net.rs @@ -585,17 +585,15 @@ impl VirtioDevice for Net { &mut self, _mem: GuestMemoryAtomic, interrupt_cb: Arc, - mut queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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(); diff --git a/virtio-devices/src/pmem.rs b/virtio-devices/src/pmem.rs index 0cb7b0282..b623fef6e 100644 --- a/virtio-devices/src/pmem.rs +++ b/virtio-devices/src/pmem.rs @@ -379,21 +379,23 @@ impl VirtioDevice for Pmem { &mut self, _mem: GuestMemoryAtomic, interrupt_cb: Arc, - mut queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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(), diff --git a/virtio-devices/src/rng.rs b/virtio-devices/src/rng.rs index a3a5c6e51..f8048047c 100644 --- a/virtio-devices/src/rng.rs +++ b/virtio-devices/src/rng.rs @@ -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: Queue>, random_file: File, interrupt_cb: Arc, 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, interrupt_cb: Arc, - queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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(), diff --git a/virtio-devices/src/transport/pci_common_config.rs b/virtio-devices/src/transport/pci_common_config.rs index 889778582..ef30ee777 100644 --- a/virtio-devices/src/transport/pci_common_config.rs +++ b/virtio-devices/src/transport/pci_common_config.rs @@ -385,8 +385,7 @@ mod tests { &mut self, _mem: GuestMemoryAtomic, _interrupt_evt: Arc, - _queues: Vec>>, - _queue_evts: Vec, + _queues: Vec<(usize, Queue>, EventFd)>, ) -> ActivateResult { Ok(()) } diff --git a/virtio-devices/src/transport/pci_device.rs b/virtio-devices/src/transport/pci_device.rs index 8d460dd7a..744bf8f49 100644 --- a/virtio-devices/src/transport/pci_device.rs +++ b/virtio-devices/src/transport/pci_device.rs @@ -292,8 +292,8 @@ pub struct VirtioPciDeviceActivator { memory: Option>, device: Arc>, device_activated: Arc, - queues: Option>>>, - queue_evts: Option>, + #[allow(clippy::type_complexity)] + queues: Option>, EventFd)>>, barrier: Option>, 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>) -> 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(), } diff --git a/virtio-devices/src/vdpa.rs b/virtio-devices/src/vdpa.rs index 58e78ba6f..47046b364 100644 --- a/virtio-devices/src/vdpa.rs +++ b/virtio-devices/src/vdpa.rs @@ -145,8 +145,7 @@ impl Vdpa { &mut self, _mem: &GuestMemoryMmap, virtio_interrupt: &Arc, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, 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, virtio_interrupt: Arc, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, 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 diff --git a/virtio-devices/src/vhost_user/blk.rs b/virtio-devices/src/vhost_user/blk.rs index f24b2ff9c..5a0798a99 100644 --- a/virtio-devices/src/vhost_user/blk.rs +++ b/virtio-devices/src/vhost_user/blk.rs @@ -292,10 +292,9 @@ impl VirtioDevice for Blk { &mut self, mem: GuestMemoryAtomic, interrupt_cb: Arc, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, 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> = 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, diff --git a/virtio-devices/src/vhost_user/fs.rs b/virtio-devices/src/vhost_user/fs.rs index 2ceddaddb..9cd0e3a83 100644 --- a/virtio-devices/src/vhost_user/fs.rs +++ b/virtio-devices/src/vhost_user/fs.rs @@ -504,10 +504,9 @@ impl VirtioDevice for Fs { &mut self, mem: GuestMemoryAtomic, interrupt_cb: Arc, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, 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, diff --git a/virtio-devices/src/vhost_user/mod.rs b/virtio-devices/src/vhost_user/mod.rs index e3aac2dd1..5c29369ba 100644 --- a/virtio-devices/src/vhost_user/mod.rs +++ b/virtio-devices/src/vhost_user/mod.rs @@ -167,8 +167,7 @@ pub struct VhostUserEpollHandler { pub mem: GuestMemoryAtomic, pub kill_evt: EventFd, pub pause_evt: EventFd, - pub queues: Vec>>, - pub queue_evts: Vec, + pub queues: Vec<(usize, Queue>, EventFd)>, pub virtio_interrupt: Arc, pub acked_features: u64, pub acked_protocol_features: u64, @@ -224,10 +223,9 @@ impl VhostUserEpollHandler { 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( &mut self, mem: GuestMemoryAtomic, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, EventFd)>, interrupt_cb: Arc, acked_features: u64, slave_req_handler: Option>, @@ -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, diff --git a/virtio-devices/src/vhost_user/net.rs b/virtio-devices/src/vhost_user/net.rs index fb90edda1..1619c7bfe 100644 --- a/virtio-devices/src/vhost_user/net.rs +++ b/virtio-devices/src/vhost_user/net.rs @@ -272,18 +272,16 @@ impl VirtioDevice for Net { &mut self, mem: GuestMemoryAtomic, interrupt_cb: Arc, - mut queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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, diff --git a/virtio-devices/src/vhost_user/vu_common_ctrl.rs b/virtio-devices/src/vhost_user/vu_common_ctrl.rs index 53d273c67..491a33a46 100644 --- a/virtio-devices/src/vhost_user/vu_common_ctrl.rs +++ b/virtio-devices/src/vhost_user/vu_common_ctrl.rs @@ -151,8 +151,7 @@ impl VhostUserHandle { pub fn setup_vhost_user( &mut self, mem: &GuestMemoryMmap, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, EventFd)>, virtio_interrupt: &Arc, acked_features: u64, slave_req_handler: &Option>, @@ -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( &mut self, mem: &GuestMemoryMmap, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, EventFd)>, virtio_interrupt: &Arc, 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, diff --git a/virtio-devices/src/vsock/device.rs b/virtio-devices/src/vsock/device.rs index 16d863d88..4156fad64 100644 --- a/virtio-devices/src/vsock/device.rs +++ b/virtio-devices/src/vsock/device.rs @@ -432,15 +432,21 @@ where &mut self, mem: GuestMemoryAtomic, interrupt_cb: Arc, - queues: Vec>>, - queue_evts: Vec, + queues: Vec<(usize, Queue>, 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(); diff --git a/virtio-devices/src/watchdog.rs b/virtio-devices/src/watchdog.rs index fa6bbc115..6627b31d4 100644 --- a/virtio-devices/src/watchdog.rs +++ b/virtio-devices/src/watchdog.rs @@ -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: Queue>, interrupt_cb: Arc, 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, interrupt_cb: Arc, - queues: Vec>>, - mut queue_evts: Vec, + mut queues: Vec<(usize, Queue>, 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,