mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: Abort vhost-user client connect on kill_evt
Client connect retried for a full minute on every failure and did not watch kill_evt for early exit, unlike reconnect, so teardown and permanent connect errors both stalled for CONNECT_TIMEOUT. Update the client path to watch kill_evt for early abort, fail non-retryable errors immediately, and surface timeout with a dedicated error. Partially Fixes #8052 Signed-off-by: Chinmoy <daschinmoyy21@gmail.com> Assisted-by: GLM 5.2
This commit is contained in:
@@ -63,7 +63,7 @@ impl Blk {
|
||||
&vu_cfg.socket,
|
||||
num_queues as u64,
|
||||
false,
|
||||
None,
|
||||
&exit_evt,
|
||||
)?;
|
||||
|
||||
let (
|
||||
|
||||
@@ -90,7 +90,7 @@ impl Fs {
|
||||
|
||||
// Connect to the vhost-user socket.
|
||||
let mut vu =
|
||||
VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false, None)?;
|
||||
VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false, &exit_evt)?;
|
||||
|
||||
let (
|
||||
avail_features,
|
||||
|
||||
@@ -77,7 +77,7 @@ impl GenericVhostUser {
|
||||
|
||||
// Connect to the vhost-user socket.
|
||||
let mut vu =
|
||||
VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false, None)?;
|
||||
VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false, &exit_evt)?;
|
||||
|
||||
let (
|
||||
avail_features,
|
||||
|
||||
@@ -179,6 +179,8 @@ pub enum Error {
|
||||
EpollWait(#[source] io::Error),
|
||||
#[error("Aborted vhost-user connect: kill event received")]
|
||||
ConnectKilled,
|
||||
#[error("Timed out waiting for vhost-user connection")]
|
||||
VhostUserConnectTimeout,
|
||||
}
|
||||
type Result<T> = result::Result<T, Error>;
|
||||
|
||||
@@ -329,7 +331,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
|
||||
&self.socket_path,
|
||||
self.queues.len() as u64,
|
||||
true,
|
||||
Some(&self.kill_evt),
|
||||
&self.kill_evt,
|
||||
) {
|
||||
Ok(vu) => vu,
|
||||
// Kill event fired during the connect retry loop; abandon the
|
||||
|
||||
@@ -93,7 +93,7 @@ impl Net {
|
||||
&vu_cfg.socket,
|
||||
num_queues as u64,
|
||||
false,
|
||||
None,
|
||||
&exit_evt,
|
||||
)?;
|
||||
|
||||
let (
|
||||
|
||||
@@ -17,9 +17,13 @@ use vhost::vhost_user::message::{
|
||||
VhostUserProtocolFeatures, VhostUserVirtioFeatures,
|
||||
};
|
||||
use vhost::vhost_user::{
|
||||
Frontend, FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler,
|
||||
Error as VhostUserError, Frontend, FrontendReqHandler, VhostUserFrontend,
|
||||
VhostUserFrontendReqHandler,
|
||||
};
|
||||
use vhost::{
|
||||
Error as VhostError, VhostBackend, VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo,
|
||||
VringConfigData,
|
||||
};
|
||||
use vhost::{VhostBackend, VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo, VringConfigData};
|
||||
use virtio_queue::desc::RawDescriptor;
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_memory::guest_memory::Error as MmapError;
|
||||
@@ -381,7 +385,7 @@ impl VhostUserHandle {
|
||||
socket_path: &str,
|
||||
num_queues: u64,
|
||||
unlink_socket: bool,
|
||||
kill_evt: Option<&EventFd>,
|
||||
kill_evt: &EventFd,
|
||||
) -> Result<Self> {
|
||||
if server {
|
||||
if unlink_socket {
|
||||
@@ -427,15 +431,13 @@ impl VhostUserHandle {
|
||||
)
|
||||
.map_err(Error::EpollCtl)?;
|
||||
|
||||
if let Some(kill_evt) = kill_evt {
|
||||
epoll
|
||||
.ctl(
|
||||
ControlOperation::Add,
|
||||
kill_evt.as_raw_fd(),
|
||||
EpollEvent::new(EventSet::IN, ConnectEvent::Kill as u64),
|
||||
)
|
||||
.map_err(Error::EpollCtl)?;
|
||||
}
|
||||
epoll
|
||||
.ctl(
|
||||
ControlOperation::Add,
|
||||
kill_evt.as_raw_fd(),
|
||||
EpollEvent::new(EventSet::IN, ConnectEvent::Kill as u64),
|
||||
)
|
||||
.map_err(Error::EpollCtl)?;
|
||||
|
||||
let start = Instant::now();
|
||||
let mut events = [EpollEvent::default(); 1];
|
||||
@@ -457,13 +459,30 @@ impl VhostUserHandle {
|
||||
Err(e) => e,
|
||||
};
|
||||
|
||||
if start.elapsed() >= CONNECT_TIMEOUT {
|
||||
let retryable = match &err {
|
||||
VhostError::VhostUserProtocol(VhostUserError::SocketConnect(io_err)) => {
|
||||
matches!(
|
||||
io_err.kind(),
|
||||
io::ErrorKind::NotFound
|
||||
| io::ErrorKind::Interrupted
|
||||
| io::ErrorKind::ConnectionRefused
|
||||
)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !retryable {
|
||||
error!(
|
||||
"Failed connecting the backend after trying for 1 minute for socket {socket_path}: {err:?}"
|
||||
"Failed connecting to vhost-user backend for socket {socket_path}: {err:?}"
|
||||
);
|
||||
return Err(Error::VhostUserConnect(err));
|
||||
}
|
||||
|
||||
if start.elapsed() >= CONNECT_TIMEOUT {
|
||||
error!("Timed out waiting for vhost-user connection on socket {socket_path}");
|
||||
return Err(Error::VhostUserConnectTimeout);
|
||||
}
|
||||
|
||||
loop {
|
||||
match epoll.wait(-1, &mut events) {
|
||||
Ok(_) => break,
|
||||
|
||||
Reference in New Issue
Block a user