vhost_user_backend: Don't discard events when queue is not enabled

The vhost crate does not support the need_reply flag yet, meaning we
can't be sure the backend is properly setup before the guest goes on.

One can run in a race condition where the VMM enables the vring, but
never gets any acknowledgement, meaning it assumes everything went well
and finalize the virtio device activation. Once the device is seen as
ready by the guest, it keeps going by sending some messages through the
virtqueues. Problem is, if it took some time for the backend to enable
the queue, one of the backend thread might receive a kick from the guest
while the corresponding queue is not enabled. This leads to the loss of
the event as it is discarded because the queue is not enabled.

Until vhost crate allows for requests with ACK, the way to mitigate this
issue is by ignoring an event coming up on a queue that has not been
enabled.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2021-05-19 16:53:53 +02:00
parent c05010887f
commit c2137e33a0

View File

@ -295,16 +295,16 @@ impl<S: VhostUserBackend> VringEpollHandler<S> {
let num_queues = self.vrings.len();
if (device_event as usize) < num_queues {
// If the vring is not enabled, it should not be processed.
// But let's not read it (hence lose it) in case it is later enabled.
if !self.vrings[device_event as usize].read().unwrap().enabled {
return Ok(false);
}
if let Some(kick) = &self.vrings[device_event as usize].read().unwrap().kick {
kick.read()
.map_err(VringEpollHandlerError::HandleEventReadKick)?;
}
// If the vring is not enabled, it should not be processed.
// The event is only read to be discarded.
if !self.vrings[device_event as usize].read().unwrap().enabled {
return Ok(false);
}
}
self.backend