From 36de390caf98c3c06774032086585fa7035ba203 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Mon, 16 Sep 2019 14:40:28 -0700 Subject: [PATCH] vhost_user_backend: Make some trait functions as mutable Let's be realistic, the trait VhostUserBackend will need to have mutable self for some functions like handle_event, process_queue and set_config, which is the reason why this commit needs to introduce a RwLock on the backend instance that was passed around as a simple Arc. Signed-off-by: Sebastien Boeuf --- vhost_user_backend/src/lib.rs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/vhost_user_backend/src/lib.rs b/vhost_user_backend/src/lib.rs index f8400bbf5..a4c3c572e 100644 --- a/vhost_user_backend/src/lib.rs +++ b/vhost_user_backend/src/lib.rs @@ -66,12 +66,12 @@ pub trait VhostUserBackend: Send + Sync + 'static { /// listeners onto specific file descriptors. The library can handle /// virtqueues on its own, but does not know what to do with events /// happening on custom listeners. - fn handle_event(&self, device_event: u16, evset: epoll::Events) -> Result; + fn handle_event(&mut self, device_event: u16, evset: epoll::Events) -> Result; /// This function is responsible for the actual processing that needs to /// happen when one of the virtqueues is available. fn process_queue( - &self, + &mut self, q_idx: u16, avail_desc: &DescriptorChain, mem: &GuestMemoryMmap, @@ -81,7 +81,7 @@ pub trait VhostUserBackend: Send + Sync + 'static { fn get_config(&self, offset: u32, size: u32) -> Vec; /// Set virtio device configuration. - fn set_config(&self, offset: u32, buf: &[u8]); + fn set_config(&mut self, offset: u32, buf: &[u8]); } /// This structure is the public API the backend is allowed to interact with @@ -225,7 +225,7 @@ impl Vring { } struct VringEpollHandler { - backend: Arc, + backend: Arc>, vrings: Vec>>, mem: Option, epoll_fd: RawFd, @@ -244,6 +244,8 @@ impl VringEpollHandler { for avail_desc in vring.queue.iter(&mem) { let used_len = self .backend + .write() + .unwrap() .process_queue(q_idx, &avail_desc, &mem) .unwrap(); @@ -277,7 +279,11 @@ impl VringEpollHandler { Ok(false) } - _ => self.backend.handle_event(device_event, evset), + _ => self + .backend + .write() + .unwrap() + .handle_event(device_event, evset), } } @@ -376,7 +382,7 @@ impl VringWorker { } struct VhostUserHandler { - backend: Arc, + backend: Arc>, vring_handler: Arc>>, owned: bool, features_acked: bool, @@ -393,7 +399,7 @@ impl VhostUserHandler { let num_queues = backend.num_queues(); let max_queue_size = backend.max_queue_size(); - let arc_backend = Arc::new(backend); + let arc_backend = Arc::new(RwLock::new(backend)); let vrings = vec![Arc::new(RwLock::new(Vring::new(max_queue_size as u16))); num_queues]; // Create the epoll file descriptor let epoll_fd = epoll::create(true).unwrap(); @@ -462,13 +468,13 @@ impl VhostUserSlaveReqHandler for VhostUserHandler { } fn get_features(&mut self) -> VhostUserResult { - Ok(self.backend.features()) + Ok(self.backend.read().unwrap().features()) } fn set_features(&mut self, features: u64) -> VhostUserResult<()> { if !self.owned || self.features_acked { return Err(VhostUserError::InvalidOperation); - } else if (features & !self.backend.features()) != 0 { + } else if (features & !self.backend.read().unwrap().features()) != 0 { return Err(VhostUserError::InvalidParam); } @@ -635,7 +641,7 @@ impl VhostUserSlaveReqHandler for VhostUserHandler { }; } self.vrings[index as usize].write().unwrap().kick = - Some(unsafe { EventFd::from_raw_fd(fd.unwrap()) });; + Some(unsafe { EventFd::from_raw_fd(fd.unwrap()) }); // Quotation from vhost-user spec: // Client must start ring upon receiving a kick (that is, detecting @@ -738,7 +744,7 @@ impl VhostUserSlaveReqHandler for VhostUserHandler { return Err(VhostUserError::InvalidParam); } - Ok(self.backend.get_config(offset, size)) + Ok(self.backend.read().unwrap().get_config(offset, size)) } fn set_config( @@ -758,7 +764,7 @@ impl VhostUserSlaveReqHandler for VhostUserHandler { return Err(VhostUserError::InvalidParam); } - self.backend.set_config(offset, buf); + self.backend.write().unwrap().set_config(offset, buf); Ok(()) } }