From 313f64127f812b5ffa97fcfeb74a1e98e64f6fbf Mon Sep 17 00:00:00 2001 From: Chuanxiao Dong Date: Tue, 3 Dec 2019 09:48:28 +0800 Subject: virtio: implement reset for balloon/rng/blk/net The reset method will be called when guest virtio driver is resetting the device. Currently the balloon/Rng/block/net virtio drivers will re-configure the virt queue during the reset so they required to be re-activated for using the new virt queue configurations. To support this, need these device models to return back the moved ownership of the important variables so that they can do the re-activate. BUG=chromium:1030609 TEST=Launch linux guest and follow the reproduce steps in BUG#1030609 to check if balloon/Rng/block/net driver still complain failure. Change-Id: I5b40fd303ea334484c590982e3e0874ea4e854ee Signed-off-by: Chuanxiao Dong Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1971097 Reviewed-by: Daniel Verkamp Tested-by: kokoro --- devices/src/virtio/block.rs | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'devices/src/virtio/block.rs') diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs index dd37f09..51a7779 100644 --- a/devices/src/virtio/block.rs +++ b/devices/src/virtio/block.rs @@ -242,6 +242,7 @@ struct Worker { disk_size: Arc>, read_only: bool, sparse: bool, + control_socket: DiskControlResponseSocket, } impl Worker { @@ -350,12 +351,7 @@ impl Worker { DiskControlResult::Ok } - fn run( - &mut self, - queue_evt: EventFd, - kill_evt: EventFd, - control_socket: DiskControlResponseSocket, - ) { + fn run(&mut self, queue_evt: EventFd, kill_evt: EventFd) { #[derive(PollToken)] enum Token { FlushTimer, @@ -377,7 +373,7 @@ impl Worker { let poll_ctx: PollContext = match PollContext::build_with(&[ (&flush_timer, Token::FlushTimer), (&queue_evt, Token::QueueAvailable), - (&control_socket, Token::ControlRequest), + (&self.control_socket, Token::ControlRequest), (self.interrupt.get_resample_evt(), Token::InterruptResample), (&kill_evt, Token::Kill), ]) { @@ -420,7 +416,7 @@ impl Worker { } } Token::ControlRequest => { - let req = match control_socket.recv() { + let req = match self.control_socket.recv() { Ok(req) => req, Err(e) => { error!("control socket failed recv: {}", e); @@ -435,7 +431,7 @@ impl Worker { } }; - if let Err(e) = control_socket.send(&resp) { + if let Err(e) = self.control_socket.send(&resp) { error!("control socket failed send: {}", e); break 'poll; } @@ -456,7 +452,7 @@ impl Worker { /// Virtio device for exposing block level read/write operations on a host file. pub struct Block { kill_evt: Option, - worker_thread: Option>, + worker_thread: Option>, disk_image: Option>, disk_size: Arc>, avail_features: u64, @@ -768,8 +764,10 @@ impl VirtioDevice for Block { disk_size, read_only, sparse, + control_socket, }; - worker.run(queue_evts.remove(0), kill_evt, control_socket); + worker.run(queue_evts.remove(0), kill_evt); + worker }); match worker_result { @@ -784,6 +782,30 @@ impl VirtioDevice for Block { } } } + + fn reset(&mut self) -> bool { + if let Some(kill_evt) = self.kill_evt.take() { + if kill_evt.write(1).is_err() { + error!("{}: failed to notify the kill event", self.debug_label()); + return false; + } + } + + if let Some(worker_thread) = self.worker_thread.take() { + match worker_thread.join() { + Err(_) => { + error!("{}: failed to get back resources", self.debug_label()); + return false; + } + Ok(worker) => { + self.disk_image = Some(worker.disk_image); + self.control_socket = Some(worker.control_socket); + return true; + } + } + } + return false; + } } #[cfg(test)] -- cgit 1.4.1