From f24094392ecc11218b70caf878705e3dcb8716e2 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Tue, 2 Feb 2021 16:17:35 +0100 Subject: [PATCH] virtio-devices: mem: Improve semantic around Resize object By introducing a ResizeSender object, we avoid having a Resize clone with a different content than the original Resize object. Signed-off-by: Sebastien Boeuf --- virtio-devices/src/mem.rs | 69 +++++++++++++++++++++++---------------- vmm/src/device_manager.rs | 8 ++--- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/virtio-devices/src/mem.rs b/virtio-devices/src/mem.rs index 4fec90a9a..43d49af79 100644 --- a/virtio-devices/src/mem.rs +++ b/virtio-devices/src/mem.rs @@ -254,10 +254,39 @@ impl Request { } } +pub struct ResizeSender { + size: Arc, + tx: mpsc::Sender>, + evt: EventFd, +} + +impl ResizeSender { + fn size(&self) -> u64 { + self.size.load(Ordering::Acquire) + } + + fn send(&self, r: Result<(), Error>) -> Result<(), mpsc::SendError>> { + self.tx.send(r) + } +} + +impl Clone for ResizeSender { + fn clone(&self) -> Self { + ResizeSender { + size: self.size.clone(), + tx: self.tx.clone(), + evt: self + .evt + .try_clone() + .expect("Failed cloning EventFd from ResizeSender"), + } + } +} + pub struct Resize { size: Arc, tx: mpsc::Sender>, - rx: Option>>, + rx: mpsc::Receiver>, evt: EventFd, } @@ -268,36 +297,23 @@ impl Resize { Ok(Resize { size: Arc::new(AtomicU64::new(0)), tx, - rx: Some(rx), + rx, evt: EventFd::new(EFD_NONBLOCK)?, }) } - pub fn try_clone(&self) -> Result { - Ok(Resize { + pub fn new_resize_sender(&self) -> Result { + Ok(ResizeSender { size: self.size.clone(), tx: self.tx.clone(), - rx: None, evt: self.evt.try_clone().map_err(Error::EventFdTryCloneFail)?, }) } pub fn work(&self, size: u64) -> Result<(), Error> { - if let Some(rx) = &self.rx { - self.size.store(size, Ordering::Release); - self.evt.write(1).map_err(Error::EventFdWriteFail)?; - rx.recv().map_err(Error::MpscRecvFail)? - } else { - panic!("work should not work with cloned resize") - } - } - - fn get_size(&self) -> u64 { - self.size.load(Ordering::Acquire) - } - - fn send(&self, r: Result<(), Error>) -> Result<(), mpsc::SendError>> { - self.tx.send(r) + self.size.store(size, Ordering::Release); + self.evt.write(1).map_err(Error::EventFdWriteFail)?; + self.rx.recv().map_err(Error::MpscRecvFail)? } } @@ -306,7 +322,7 @@ struct MemEpollHandler { host_fd: Option, mem_state: Vec, config: Arc>, - resize: Resize, + resize: ResizeSender, queue: Queue, mem: GuestMemoryAtomic, interrupt_cb: Arc, @@ -651,7 +667,7 @@ impl EpollHelperHandler for MemEpollHandler { error!("Failed to get resize event: {:?}", e); return true; } else { - let size = self.resize.get_size(); + let size = self.resize.size(); let mut config = self.config.lock().unwrap(); let mut signal_error = false; let mut r = virtio_mem_config_resize(&mut config, size); @@ -698,7 +714,7 @@ impl EpollHelperHandler for MemEpollHandler { pub struct Mem { common: VirtioCommon, id: String, - resize: Resize, + resize: ResizeSender, host_addr: u64, host_fd: Option, config: Arc>, @@ -710,7 +726,7 @@ impl Mem { pub fn new( id: String, region: &Arc, - resize: Resize, + resize: ResizeSender, seccomp_action: SeccompAction, numa_node_id: Option, initial_size: u64, @@ -842,10 +858,7 @@ impl VirtioDevice for Mem { host_fd: self.host_fd, mem_state: vec![false; config.region_size as usize / config.block_size as usize], config: self.config.clone(), - resize: self.resize.try_clone().map_err(|e| { - error!("failed to clone resize EventFd: {:?}", e); - ActivateError::BadActivate - })?, + resize: self.resize.clone(), queue: queues.remove(0), mem, interrupt_cb, diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index c83ca3fc9..43e5b2efe 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -330,8 +330,8 @@ pub enum DeviceManagerError { /// Cannot create virtio-mem device CreateVirtioMem(io::Error), - /// Cannot try Clone virtio-mem resize - TryCloneVirtioMemResize(virtio_devices::mem::Error), + /// Cannot generate a ResizeSender from the Resize object. + CreateResizeSender(virtio_devices::mem::Error), /// Cannot find a memory range for virtio-mem memory VirtioMemRangeAllocation, @@ -2342,8 +2342,8 @@ impl DeviceManager { virtio_mem_zone.region(), virtio_mem_zone .resize_handler() - .try_clone() - .map_err(DeviceManagerError::TryCloneVirtioMemResize)?, + .new_resize_sender() + .map_err(DeviceManagerError::CreateResizeSender)?, self.seccomp_action.clone(), node_id, virtio_mem_zone.hotplugged_size(),