Skip to content

Commit 14db3cd

Browse files
alyssaisstefano-garzarella
authored andcommitted
vhost_user: fix replies without GET_PROTOCOL_FEATURES
I observed hangs in the following situation when using Cloud Hypervisor with virtiofsd: 1. Start virtiofsd 2. Start Cloud Hypervisor instance 1, connected to virtiofsd. 3. Start Cloud Hypervisor instance 2, waiting for migration. 4. Migrate VM from Cloud Hypervisor instance 1 to 2. 5. Start virtiofsd again. The hangs happened because Cloud Hypervisor remembered, as part of the migration data, which vhost-user protocol features the backend for its fs device supported. Instance 2 therefore never sent GET_PROTOCOL_FEATURES to the second invocation of virtiofsd. This should work, but it didn't, because update_reply_ack_flag() checked whether self.protocol_features contained GET_PROTOCOL_FEATURES, but self.protocol_features is only filled in when GET_PROTOCOL_FEATURES is called. As a result, Cloud Hypervisor expected a reply that virtiofsd would never send. Since REPLY_ACK is handled entirely by the vhost-user library, and not by the backend, there's no need to ask the backend whether it supports REPLY_ACK in the first place, so we can just drop the check for that from update_reply_ack_flag(). We know that we always support it, so we just need to check whether the backend has acked it. This fixes the hang described above. Since we will now always reply if the backend acks the feature, REPLY_ACK is now always included in the set of features returned by GET_PROTOCOL_FEATURES, just like with XEN_MMAP (when enabled). Signed-off-by: Alyssa Ross <[email protected]>
1 parent 8c7cc59 commit 14db3cd

File tree

3 files changed

+9
-6
lines changed

3 files changed

+9
-6
lines changed

vhost-user-backend/tests/vhost-user-server.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ impl VhostUserBackendMut for MockVhostBackend {
5959
}
6060

6161
fn protocol_features(&self) -> VhostUserProtocolFeatures {
62-
VhostUserProtocolFeatures::all()
62+
// Exclude REPLY_ACK to test that it is automatically added.
63+
VhostUserProtocolFeatures::all() - VhostUserProtocolFeatures::REPLY_ACK
6364
}
6465

6566
fn reset_device(&mut self) {

vhost/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
- [[#268]](https://github.com/rust-vmm/vhost/pull/268) Add support for `VHOST_USER_GET_SHARED_OBJECT`
66

77
### Changed
8+
- [[#290]](https://github.com/rust-vmm/vhost/pull/290) Backends now
9+
always support `VHOST_USER_PROTOCOL_F_REPLY_ACK`, without the
10+
`VhostUserBackendReqHandler` implementation having to include it in
11+
the features returned from `get_protocol_features`.
812

913
### Deprecated
1014

vhost/src/vhost_user/backend_req_handler.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ pub struct BackendReqHandler<S: VhostUserBackendReqHandler> {
327327

328328
virtio_features: u64,
329329
acked_virtio_features: u64,
330-
protocol_features: VhostUserProtocolFeatures,
331330
acked_protocol_features: u64,
332331

333332
// sending ack for messages without payload
@@ -347,7 +346,6 @@ impl<S: VhostUserBackendReqHandler> BackendReqHandler<S> {
347346
backend,
348347
virtio_features: 0,
349348
acked_virtio_features: 0,
350-
protocol_features: VhostUserProtocolFeatures::empty(),
351349
acked_protocol_features: 0,
352350
reply_ack_enabled: false,
353351
error: None,
@@ -512,15 +510,16 @@ impl<S: VhostUserBackendReqHandler> BackendReqHandler<S> {
512510
}
513511
Ok(FrontendReq::GET_PROTOCOL_FEATURES) => {
514512
self.check_request_size(&hdr, size, 0)?;
515-
let features = self.backend.get_protocol_features()?;
513+
// REPLY_ACK is implemented entirely by this library, so it's always supported.
514+
let features =
515+
self.backend.get_protocol_features()? | VhostUserProtocolFeatures::REPLY_ACK;
516516

517517
// Enable the `XEN_MMAP` protocol feature for backends if xen feature is enabled.
518518
#[cfg(feature = "xen")]
519519
let features = features | VhostUserProtocolFeatures::XEN_MMAP;
520520

521521
let msg = VhostUserU64::new(features.bits());
522522
self.send_reply_message(&hdr, &msg)?;
523-
self.protocol_features = features;
524523
self.update_reply_ack_flag();
525524
}
526525
Ok(FrontendReq::SET_PROTOCOL_FEATURES) => {
@@ -952,7 +951,6 @@ impl<S: VhostUserBackendReqHandler> BackendReqHandler<S> {
952951
let pflag = VhostUserProtocolFeatures::REPLY_ACK;
953952

954953
self.reply_ack_enabled = (self.virtio_features & vflag) != 0
955-
&& self.protocol_features.contains(pflag)
956954
&& (self.acked_protocol_features & pflag.bits()) != 0;
957955
}
958956

0 commit comments

Comments
 (0)