mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-20 23:11:16 +00:00
vm-virtio, vhost_user_{fs,block,backend}: Move EVENT_IDX handling
Move the method that is used to decide whether the guest should be signalled into the Queue implementation from vm-virtio. This removes duplicated code between vhost_user_backend and the vm-virtio block implementation. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
8ae7a38da5
commit
a813b57f59
@ -163,8 +163,9 @@ impl<F: FileSystem + Send + Sync + 'static> VhostUserFsThread<F> {
|
|||||||
let mut vring = vring_lock.write().unwrap();
|
let mut vring = vring_lock.write().unwrap();
|
||||||
|
|
||||||
if event_idx {
|
if event_idx {
|
||||||
if let Some(used_idx) = vring.mut_queue().add_used(&mem, head_index, 0) {
|
let queue = vring.mut_queue();
|
||||||
if vring.needs_notification(&mem, Wrapping(used_idx)) {
|
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();
|
vring.signal_used_queue().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,8 +210,6 @@ pub struct Vring {
|
|||||||
call: Option<EventFd>,
|
call: Option<EventFd>,
|
||||||
err: Option<EventFd>,
|
err: Option<EventFd>,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
event_idx: bool,
|
|
||||||
signalled_used: Option<Wrapping<u16>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vring {
|
impl Vring {
|
||||||
@ -222,8 +220,6 @@ impl Vring {
|
|||||||
call: None,
|
call: None,
|
||||||
err: None,
|
err: None,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
event_idx: false,
|
|
||||||
signalled_used: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,31 +227,6 @@ impl Vring {
|
|||||||
&mut self.queue
|
&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<u16>) -> 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> {
|
pub fn signal_used_queue(&mut self) -> result::Result<(), io::Error> {
|
||||||
if let Some(call) = self.call.as_ref() {
|
if let Some(call) = self.call.as_ref() {
|
||||||
call.write(1)
|
call.write(1)
|
||||||
@ -724,6 +695,7 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandler for VhostUserHandler<S> {
|
|||||||
self.vrings[index as usize]
|
self.vrings[index as usize]
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.mut_queue()
|
||||||
.set_event_idx(event_idx);
|
.set_event_idx(event_idx);
|
||||||
self.backend.write().unwrap().set_event_idx(event_idx);
|
self.backend.write().unwrap().set_event_idx(event_idx);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -153,8 +153,9 @@ impl VhostUserBlkThread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.event_idx {
|
if self.event_idx {
|
||||||
if let Some(used_idx) = vring.mut_queue().add_used(mem, head.index, len) {
|
let queue = vring.mut_queue();
|
||||||
if vring.needs_notification(&mem, Wrapping(used_idx)) {
|
if let Some(used_idx) = queue.add_used(mem, head.index, len) {
|
||||||
|
if queue.needs_notification(&mem, Wrapping(used_idx)) {
|
||||||
debug!("signalling queue");
|
debug!("signalling queue");
|
||||||
vring.signal_used_queue().unwrap();
|
vring.signal_used_queue().unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
@ -23,7 +23,6 @@ use std::cmp;
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fs::{File, Metadata};
|
use std::fs::{File, Metadata};
|
||||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||||
use std::num::Wrapping;
|
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use std::os::linux::fs::MetadataExt;
|
use std::os::linux::fs::MetadataExt;
|
||||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||||
@ -607,7 +606,6 @@ struct BlockEpollHandler<T: DiskFile> {
|
|||||||
kill_evt: EventFd,
|
kill_evt: EventFd,
|
||||||
pause_evt: EventFd,
|
pause_evt: EventFd,
|
||||||
event_idx: bool,
|
event_idx: bool,
|
||||||
signalled_used: Option<Wrapping<u16>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DiskFile> BlockEpollHandler<T> {
|
impl<T: DiskFile> BlockEpollHandler<T> {
|
||||||
@ -682,25 +680,6 @@ impl<T: DiskFile> BlockEpollHandler<T> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn needs_notification(&mut self, mem: &GuestMemoryMmap, used_idx: Wrapping<u16>) -> 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(
|
fn run(
|
||||||
&mut self,
|
&mut self,
|
||||||
queue_evt: EventFd,
|
queue_evt: EventFd,
|
||||||
@ -772,7 +751,7 @@ impl<T: DiskFile> BlockEpollHandler<T> {
|
|||||||
if self.process_queue() {
|
if self.process_queue() {
|
||||||
self.queue.update_avail_event(&self.mem.memory());
|
self.queue.update_avail_event(&self.mem.memory());
|
||||||
|
|
||||||
if self.needs_notification(
|
if self.queue.needs_notification(
|
||||||
&self.mem.memory(),
|
&self.mem.memory(),
|
||||||
self.queue.next_used,
|
self.queue.next_used,
|
||||||
) {
|
) {
|
||||||
@ -1176,9 +1155,10 @@ impl<T: 'static + DiskFile + Send> VirtioDevice for Block<T> {
|
|||||||
kill_evt: kill_evt.try_clone().unwrap(),
|
kill_evt: kill_evt.try_clone().unwrap(),
|
||||||
pause_evt: pause_evt.try_clone().unwrap(),
|
pause_evt: pause_evt.try_clone().unwrap(),
|
||||||
event_idx,
|
event_idx,
|
||||||
signalled_used: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handler.queue.set_event_idx(event_idx);
|
||||||
|
|
||||||
let queue_evt = queue_evts.remove(0);
|
let queue_evt = queue_evts.remove(0);
|
||||||
let paused = self.paused.clone();
|
let paused = self.paused.clone();
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
|
@ -401,7 +401,7 @@ pub struct Queue {
|
|||||||
/// The queue size in elements the driver selected
|
/// The queue size in elements the driver selected
|
||||||
pub size: u16,
|
pub size: u16,
|
||||||
|
|
||||||
/// Inidcates if the queue is finished with configuration
|
/// Indicates if the queue is finished with configuration
|
||||||
pub ready: bool,
|
pub ready: bool,
|
||||||
|
|
||||||
/// Interrupt vector index of the queue
|
/// Interrupt vector index of the queue
|
||||||
@ -424,6 +424,12 @@ pub struct Queue {
|
|||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub iommu_mapping_cb: Option<Arc<VirtioIommuRemapping>>,
|
pub iommu_mapping_cb: Option<Arc<VirtioIommuRemapping>>,
|
||||||
|
|
||||||
|
/// VIRTIO_F_RING_EVENT_IDX negotiated
|
||||||
|
event_idx: bool,
|
||||||
|
|
||||||
|
/// The last used value when using EVENT_IDX
|
||||||
|
signalled_used: Option<Wrapping<u16>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Queue {
|
impl Queue {
|
||||||
@ -440,6 +446,8 @@ impl Queue {
|
|||||||
next_avail: Wrapping(0),
|
next_avail: Wrapping(0),
|
||||||
next_used: Wrapping(0),
|
next_used: Wrapping(0),
|
||||||
iommu_mapping_cb: None,
|
iommu_mapping_cb: None,
|
||||||
|
event_idx: false,
|
||||||
|
signalled_used: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,6 +686,31 @@ impl Queue {
|
|||||||
pub fn available_descriptors(&self, mem: &GuestMemoryMmap) -> Result<bool, Error> {
|
pub fn available_descriptors(&self, mem: &GuestMemoryMmap) -> Result<bool, Error> {
|
||||||
Ok(self.used_index_from_memory(mem)? < self.avail_index_from_memory(mem)?)
|
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<u16>) -> 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)]
|
#[cfg(test)]
|
||||||
|
Loading…
Reference in New Issue
Block a user