mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-04 04:25:45 +00:00
virtio-devices: vhost_user: Reconnection for slave request handler
Add the support for reconnecting the backend request handler after a disconnection/crash happened. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
acec7e34fc
commit
1a5c6631a5
@ -23,7 +23,7 @@ use std::vec::Vec;
|
|||||||
use vhost::vhost_user::message::VhostUserConfigFlags;
|
use vhost::vhost_user::message::VhostUserConfigFlags;
|
||||||
use vhost::vhost_user::message::VHOST_USER_CONFIG_OFFSET;
|
use vhost::vhost_user::message::VHOST_USER_CONFIG_OFFSET;
|
||||||
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
||||||
use vhost::vhost_user::{Master, VhostUserMaster, VhostUserMasterReqHandler};
|
use vhost::vhost_user::{Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
|
||||||
use vhost::VhostBackend;
|
use vhost::VhostBackend;
|
||||||
use virtio_bindings::bindings::virtio_blk::{
|
use virtio_bindings::bindings::virtio_blk::{
|
||||||
VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_CONFIG_WCE, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_FLUSH,
|
VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_CONFIG_WCE, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_FLUSH,
|
||||||
@ -215,6 +215,8 @@ impl VirtioDevice for Blk {
|
|||||||
|
|
||||||
self.guest_memory = Some(mem.clone());
|
self.guest_memory = Some(mem.clone());
|
||||||
|
|
||||||
|
let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
|
||||||
|
|
||||||
// The backend acknowledged features must contain the protocol feature
|
// The backend acknowledged features must contain the protocol feature
|
||||||
// bit in case it was initially set but lost through the features
|
// bit in case it was initially set but lost through the features
|
||||||
// negotiation with the guest.
|
// negotiation with the guest.
|
||||||
@ -228,6 +230,7 @@ impl VirtioDevice for Blk {
|
|||||||
queue_evts.iter().map(|q| q.try_clone().unwrap()).collect(),
|
queue_evts.iter().map(|q| q.try_clone().unwrap()).collect(),
|
||||||
&interrupt_cb,
|
&interrupt_cb,
|
||||||
backend_acked_features,
|
backend_acked_features,
|
||||||
|
&slave_req_handler,
|
||||||
)
|
)
|
||||||
.map_err(ActivateError::VhostUserBlkSetup)?;
|
.map_err(ActivateError::VhostUserBlkSetup)?;
|
||||||
|
|
||||||
|
@ -415,22 +415,6 @@ impl VirtioDevice for Fs {
|
|||||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||||
self.guest_memory = Some(mem.clone());
|
self.guest_memory = Some(mem.clone());
|
||||||
|
|
||||||
// The backend acknowledged features must contain the protocol feature
|
|
||||||
// bit in case it was initially set but lost through the features
|
|
||||||
// negotiation with the guest.
|
|
||||||
let backend_acked_features = self.common.acked_features
|
|
||||||
| (self.common.avail_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits());
|
|
||||||
|
|
||||||
setup_vhost_user(
|
|
||||||
&mut self.vu.lock().unwrap(),
|
|
||||||
&mem.memory(),
|
|
||||||
queues.clone(),
|
|
||||||
queue_evts.iter().map(|q| q.try_clone().unwrap()).collect(),
|
|
||||||
&interrupt_cb,
|
|
||||||
backend_acked_features,
|
|
||||||
)
|
|
||||||
.map_err(ActivateError::VhostUserFsSetup)?;
|
|
||||||
|
|
||||||
// Initialize slave communication.
|
// Initialize slave communication.
|
||||||
let slave_req_handler = if self.slave_req_support {
|
let slave_req_handler = if self.slave_req_support {
|
||||||
if let Some(cache) = self.cache.as_ref() {
|
if let Some(cache) = self.cache.as_ref() {
|
||||||
@ -446,13 +430,6 @@ impl VirtioDevice for Fs {
|
|||||||
ActivateError::VhostUserFsSetup(Error::MasterReqHandlerCreation(e))
|
ActivateError::VhostUserFsSetup(Error::MasterReqHandlerCreation(e))
|
||||||
})?;
|
})?;
|
||||||
req_handler.set_reply_ack_flag(true);
|
req_handler.set_reply_ack_flag(true);
|
||||||
self.vu
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.set_slave_request_fd(req_handler.get_tx_raw_fd())
|
|
||||||
.map_err(|e| {
|
|
||||||
ActivateError::VhostUserFsSetup(Error::VhostUserSetSlaveRequestFd(e))
|
|
||||||
})?;
|
|
||||||
Some(req_handler)
|
Some(req_handler)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -461,6 +438,23 @@ impl VirtioDevice for Fs {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The backend acknowledged features must contain the protocol feature
|
||||||
|
// bit in case it was initially set but lost through the features
|
||||||
|
// negotiation with the guest.
|
||||||
|
let backend_acked_features = self.common.acked_features
|
||||||
|
| (self.common.avail_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits());
|
||||||
|
|
||||||
|
setup_vhost_user(
|
||||||
|
&mut self.vu.lock().unwrap(),
|
||||||
|
&mem.memory(),
|
||||||
|
queues.clone(),
|
||||||
|
queue_evts.iter().map(|q| q.try_clone().unwrap()).collect(),
|
||||||
|
&interrupt_cb,
|
||||||
|
backend_acked_features,
|
||||||
|
&slave_req_handler,
|
||||||
|
)
|
||||||
|
.map_err(ActivateError::VhostUserFsSetup)?;
|
||||||
|
|
||||||
// Run a dedicated thread for handling potential reconnections with
|
// Run a dedicated thread for handling potential reconnections with
|
||||||
// the backend as well as requests initiated by the backend.
|
// the backend as well as requests initiated by the backend.
|
||||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||||
|
@ -197,6 +197,7 @@ impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
|
|||||||
&self.virtio_interrupt,
|
&self.virtio_interrupt,
|
||||||
self.acked_features,
|
self.acked_features,
|
||||||
self.acked_protocol_features,
|
self.acked_protocol_features,
|
||||||
|
&self.slave_req_handler,
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
EpollHelperError::IoError(std::io::Error::new(
|
EpollHelperError::IoError(std::io::Error::new(
|
||||||
|
@ -23,7 +23,7 @@ use std::sync::{Arc, Barrier, Mutex};
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
||||||
use vhost::vhost_user::{Master, VhostUserMaster, VhostUserMasterReqHandler};
|
use vhost::vhost_user::{Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
|
||||||
use virtio_bindings::bindings::virtio_net::{
|
use virtio_bindings::bindings::virtio_net::{
|
||||||
VIRTIO_NET_F_CSUM, VIRTIO_NET_F_CTRL_VQ, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN,
|
VIRTIO_NET_F_CSUM, VIRTIO_NET_F_CTRL_VQ, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN,
|
||||||
VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO,
|
VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO,
|
||||||
@ -283,6 +283,8 @@ impl VirtioDevice for Net {
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
|
||||||
|
|
||||||
// The backend acknowledged features must contain the protocol feature
|
// The backend acknowledged features must contain the protocol feature
|
||||||
// bit in case it was initially set but lost through the features
|
// bit in case it was initially set but lost through the features
|
||||||
// negotiation with the guest. Additionally, it must not contain
|
// negotiation with the guest. Additionally, it must not contain
|
||||||
@ -297,6 +299,7 @@ impl VirtioDevice for Net {
|
|||||||
queue_evts.iter().map(|q| q.try_clone().unwrap()).collect(),
|
queue_evts.iter().map(|q| q.try_clone().unwrap()).collect(),
|
||||||
&interrupt_cb,
|
&interrupt_cb,
|
||||||
backend_acked_features,
|
backend_acked_features,
|
||||||
|
&slave_req_handler,
|
||||||
)
|
)
|
||||||
.map_err(ActivateError::VhostUserNetSetup)?;
|
.map_err(ActivateError::VhostUserNetSetup)?;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ use std::thread::sleep;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
|
||||||
use vhost::vhost_user::{Master, VhostUserMaster};
|
use vhost::vhost_user::{Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
|
||||||
use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData};
|
use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData};
|
||||||
use vm_memory::{Address, Error as MmapError, GuestMemory, GuestMemoryRegion};
|
use vm_memory::{Address, Error as MmapError, GuestMemory, GuestMemoryRegion};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
@ -100,13 +100,14 @@ pub fn negotiate_features_vhost_user(
|
|||||||
Ok((acked_features, acked_protocol_features))
|
Ok((acked_features, acked_protocol_features))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_vhost_user(
|
pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
|
||||||
vu: &mut Master,
|
vu: &mut Master,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
queues: Vec<Queue>,
|
queues: Vec<Queue>,
|
||||||
queue_evts: Vec<EventFd>,
|
queue_evts: Vec<EventFd>,
|
||||||
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
||||||
acked_features: u64,
|
acked_features: u64,
|
||||||
|
slave_req_handler: &Option<MasterReqHandler<S>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
vu.set_features(acked_features)
|
vu.set_features(acked_features)
|
||||||
.map_err(Error::VhostUserSetFeatures)?;
|
.map_err(Error::VhostUserSetFeatures)?;
|
||||||
@ -164,7 +165,12 @@ pub fn setup_vhost_user(
|
|||||||
.map_err(Error::VhostUserSetVringEnable)?;
|
.map_err(Error::VhostUserSetVringEnable)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
if let Some(slave_req_handler) = slave_req_handler {
|
||||||
|
vu.set_slave_request_fd(slave_req_handler.get_tx_raw_fd())
|
||||||
|
.map_err(Error::VhostUserSetSlaveRequestFd)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_vhost_user(vu: &mut Master, num_queues: usize) -> Result<()> {
|
pub fn reset_vhost_user(vu: &mut Master, num_queues: usize) -> Result<()> {
|
||||||
@ -178,7 +184,8 @@ pub fn reset_vhost_user(vu: &mut Master, num_queues: usize) -> Result<()> {
|
|||||||
vu.reset_owner().map_err(Error::VhostUserResetOwner)
|
vu.reset_owner().map_err(Error::VhostUserResetOwner)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reinitialize_vhost_user(
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn reinitialize_vhost_user<S: VhostUserMasterReqHandler>(
|
||||||
vu: &mut Master,
|
vu: &mut Master,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
queues: Vec<Queue>,
|
queues: Vec<Queue>,
|
||||||
@ -186,6 +193,7 @@ pub fn reinitialize_vhost_user(
|
|||||||
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
||||||
acked_features: u64,
|
acked_features: u64,
|
||||||
acked_protocol_features: u64,
|
acked_protocol_features: u64,
|
||||||
|
slave_req_handler: &Option<MasterReqHandler<S>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
vu.set_owner().map_err(Error::VhostUserSetOwner)?;
|
vu.set_owner().map_err(Error::VhostUserSetOwner)?;
|
||||||
vu.get_features().map_err(Error::VhostUserGetFeatures)?;
|
vu.get_features().map_err(Error::VhostUserGetFeatures)?;
|
||||||
@ -206,6 +214,7 @@ pub fn reinitialize_vhost_user(
|
|||||||
queue_evts,
|
queue_evts,
|
||||||
virtio_interrupt,
|
virtio_interrupt,
|
||||||
acked_features,
|
acked_features,
|
||||||
|
slave_req_handler,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user