diff --git a/src/bin/vhost_user_fs.rs b/src/bin/vhost_user_fs.rs index ce4c41fba..40bec209c 100644 --- a/src/bin/vhost_user_fs.rs +++ b/src/bin/vhost_user_fs.rs @@ -163,8 +163,9 @@ impl VhostUserFsThread { let mut vring = vring_lock.write().unwrap(); if event_idx { - if let Some(used_idx) = vring.mut_queue().add_used(&mem, head_index, 0) { - if vring.needs_notification(&mem, Wrapping(used_idx)) { + let queue = vring.mut_queue(); + if let Some(used_idx) = queue.add_used(&mem, head_index, 0) { + if queue.needs_notification(&mem, Wrapping(used_idx)) { vring.signal_used_queue().unwrap(); } } diff --git a/vhost_user_backend/src/lib.rs b/vhost_user_backend/src/lib.rs index 9cb3f63da..fb2d6fcc5 100644 --- a/vhost_user_backend/src/lib.rs +++ b/vhost_user_backend/src/lib.rs @@ -210,8 +210,6 @@ pub struct Vring { call: Option, err: Option, enabled: bool, - event_idx: bool, - signalled_used: Option>, } impl Vring { @@ -222,8 +220,6 @@ impl Vring { call: None, err: None, enabled: false, - event_idx: false, - signalled_used: None, } } @@ -231,31 +227,6 @@ impl Vring { &mut self.queue } - pub fn set_event_idx(&mut self, enabled: bool) { - /* Also reset the last signalled event */ - self.signalled_used = None; - self.event_idx = enabled; - } - - pub fn needs_notification(&mut self, mem: &GuestMemoryMmap, used_idx: Wrapping) -> bool { - if !self.event_idx { - return true; - } - - let mut notify = true; - - if let Some(old_idx) = self.signalled_used { - if let Some(used_event) = self.mut_queue().get_used_event(&mem) { - if (used_idx - used_event - Wrapping(1u16)) >= (used_idx - old_idx) { - notify = false; - } - } - } - - self.signalled_used = Some(used_idx); - notify - } - pub fn signal_used_queue(&mut self) -> result::Result<(), io::Error> { if let Some(call) = self.call.as_ref() { call.write(1) @@ -724,6 +695,7 @@ impl VhostUserSlaveReqHandler for VhostUserHandler { self.vrings[index as usize] .write() .unwrap() + .mut_queue() .set_event_idx(event_idx); self.backend.write().unwrap().set_event_idx(event_idx); Ok(()) diff --git a/vhost_user_block/src/lib.rs b/vhost_user_block/src/lib.rs index ba1753301..57490ec53 100644 --- a/vhost_user_block/src/lib.rs +++ b/vhost_user_block/src/lib.rs @@ -153,8 +153,9 @@ impl VhostUserBlkThread { } if self.event_idx { - if let Some(used_idx) = vring.mut_queue().add_used(mem, head.index, len) { - if vring.needs_notification(&mem, Wrapping(used_idx)) { + let queue = vring.mut_queue(); + if let Some(used_idx) = queue.add_used(mem, head.index, len) { + if queue.needs_notification(&mem, Wrapping(used_idx)) { debug!("signalling queue"); vring.signal_used_queue().unwrap(); } else { diff --git a/vm-virtio/src/block.rs b/vm-virtio/src/block.rs index 7b4faacbf..95a05fa12 100755 --- a/vm-virtio/src/block.rs +++ b/vm-virtio/src/block.rs @@ -23,7 +23,6 @@ use std::cmp; use std::convert::TryInto; use std::fs::{File, Metadata}; use std::io::{self, Read, Seek, SeekFrom, Write}; -use std::num::Wrapping; use std::ops::DerefMut; use std::os::linux::fs::MetadataExt; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; @@ -607,7 +606,6 @@ struct BlockEpollHandler { kill_evt: EventFd, pause_evt: EventFd, event_idx: bool, - signalled_used: Option>, } impl BlockEpollHandler { @@ -682,25 +680,6 @@ impl BlockEpollHandler { Ok(()) } - fn needs_notification(&mut self, mem: &GuestMemoryMmap, used_idx: Wrapping) -> bool { - if !self.event_idx { - return true; - } - - let mut notify = true; - - if let Some(old_idx) = self.signalled_used { - if let Some(used_event) = self.queue.get_used_event(&mem) { - if (used_idx - used_event - Wrapping(1u16)) >= (used_idx - old_idx) { - notify = false; - } - } - } - - self.signalled_used = Some(used_idx); - notify - } - fn run( &mut self, queue_evt: EventFd, @@ -772,7 +751,7 @@ impl BlockEpollHandler { if self.process_queue() { self.queue.update_avail_event(&self.mem.memory()); - if self.needs_notification( + if self.queue.needs_notification( &self.mem.memory(), self.queue.next_used, ) { @@ -1176,9 +1155,10 @@ impl VirtioDevice for Block { kill_evt: kill_evt.try_clone().unwrap(), pause_evt: pause_evt.try_clone().unwrap(), event_idx, - signalled_used: None, }; + handler.queue.set_event_idx(event_idx); + let queue_evt = queue_evts.remove(0); let paused = self.paused.clone(); thread::Builder::new() diff --git a/vm-virtio/src/queue.rs b/vm-virtio/src/queue.rs index 1201273cc..8560dc7e5 100644 --- a/vm-virtio/src/queue.rs +++ b/vm-virtio/src/queue.rs @@ -401,7 +401,7 @@ pub struct Queue { /// The queue size in elements the driver selected pub size: u16, - /// Inidcates if the queue is finished with configuration + /// Indicates if the queue is finished with configuration pub ready: bool, /// Interrupt vector index of the queue @@ -424,6 +424,12 @@ pub struct Queue { #[serde(skip)] pub iommu_mapping_cb: Option>, + + /// VIRTIO_F_RING_EVENT_IDX negotiated + event_idx: bool, + + /// The last used value when using EVENT_IDX + signalled_used: Option>, } impl Queue { @@ -440,6 +446,8 @@ impl Queue { next_avail: Wrapping(0), next_used: Wrapping(0), iommu_mapping_cb: None, + event_idx: false, + signalled_used: None, } } @@ -678,6 +686,31 @@ impl Queue { pub fn available_descriptors(&self, mem: &GuestMemoryMmap) -> Result { Ok(self.used_index_from_memory(mem)? < self.avail_index_from_memory(mem)?) } + + pub fn set_event_idx(&mut self, enabled: bool) { + /* Also reset the last signalled event */ + self.signalled_used = None; + self.event_idx = enabled; + } + + pub fn needs_notification(&mut self, mem: &GuestMemoryMmap, used_idx: Wrapping) -> bool { + if !self.event_idx { + return true; + } + + let mut notify = true; + + if let Some(old_idx) = self.signalled_used { + if let Some(used_event) = self.get_used_event(&mem) { + if (used_idx - used_event - Wrapping(1u16)) >= (used_idx - old_idx) { + notify = false; + } + } + } + + self.signalled_used = Some(used_idx); + notify + } } #[cfg(test)]