summary refs log tree commit diff
path: root/devices
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-06-13 08:17:27 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-15 08:33:57 +0000
commit5bd2e7f606b726b598fdc26fe26a9b4029fab6d3 (patch)
tree2f12d905d51580d78b75af45b48a3588e2497d45 /devices
parent89059ee485b2eefdecc1e55daa14bcb857e6d2f1 (diff)
downloadcrosvm-5bd2e7f606b726b598fdc26fe26a9b4029fab6d3.tar
crosvm-5bd2e7f606b726b598fdc26fe26a9b4029fab6d3.tar.gz
crosvm-5bd2e7f606b726b598fdc26fe26a9b4029fab6d3.tar.bz2
crosvm-5bd2e7f606b726b598fdc26fe26a9b4029fab6d3.tar.lz
crosvm-5bd2e7f606b726b598fdc26fe26a9b4029fab6d3.tar.xz
crosvm-5bd2e7f606b726b598fdc26fe26a9b4029fab6d3.tar.zst
crosvm-5bd2e7f606b726b598fdc26fe26a9b4029fab6d3.zip
crosvm: fix deadlock on early VmRequest
If a DiskCommand was received on the crosvm socket before the
virtio-block device was activated, the Token::VmRequest case in the
main event loop would forward the request to the block device socket,
and then wait syncronously for a response.  That response would never
come because the device hadn't been activated, and it would never be
activated because the event loop would never continue, and therefore
never be able to respond to the event that causes the device to be
activated.  crosvm would therefore just hang forever, waiting for a
response that would never come.

This patch fixes this deadlock by keeping track of whether devices
that send a response in this way have been activated yet.  If they
have already been activated, messages are sent and responses are
received as normal.  If they have not been activated, messages are
instead put into a per-device queue.  Once the device is activated,
queued messages are processed all at once, and then the device is
marked as ready, and the queue is dropped.  Future messages are
processed immediately as they come in, with no further queueing.

A device indicates that it is ready by sending a message on its
socket.  The main crosvm event loop can then poll the socket, to be
notified when the device is ready.  This poll event will only trigger
once -- once it has been received, it is removed from the poll
context.

Currently, the only device type that responds to external control
messages AND needs to be activated by an event is the block device.
The balloon device does not respond to messages, and the xhci
controller device is activated up front.  The code is nevertheless
structured so that it should be very easy to drop another kind of
device in to the queuing system, should that be required.

Message-Id: <20200614114344.22642-3-hi@alyssa.is>
Notes
Reviewed-by: Cole Helbling <cole.e.helbling@outlook.com>
Diffstat (limited to 'devices')
-rw-r--r--devices/src/virtio/block.rs5
1 files changed, 5 insertions, 0 deletions
diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs
index 80d5103..5a8972a 100644
--- a/devices/src/virtio/block.rs
+++ b/devices/src/virtio/block.rs
@@ -390,6 +390,11 @@ impl Worker {
             }
         };
 
+        if let Err(e) = self.control_socket.send(&DiskControlResult::Ready) {
+            error!("control socket failed to notify readiness: {}", e);
+            return;
+        }
+
         'poll: loop {
             let events = match poll_ctx.wait() {
                 Ok(v) => v,