mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: vhost-user: Abandon reconnection if kill event sent
Abandon the reconnection to the vhost-user socket if the kill_evt is fired because e.g. a device removal request has come in during the reconnection. Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
@@ -59,8 +59,13 @@ impl Blk {
|
||||
) -> Result<Blk> {
|
||||
let num_queues = vu_cfg.num_queues;
|
||||
|
||||
let mut vu =
|
||||
VhostUserHandle::connect_vhost_user(false, &vu_cfg.socket, num_queues as u64, false)?;
|
||||
let mut vu = VhostUserHandle::connect_vhost_user(
|
||||
false,
|
||||
&vu_cfg.socket,
|
||||
num_queues as u64,
|
||||
false,
|
||||
None,
|
||||
)?;
|
||||
|
||||
let (
|
||||
avail_features,
|
||||
|
||||
@@ -90,7 +90,8 @@ impl Fs {
|
||||
let num_queues = NUM_QUEUE_OFFSET + req_num_queues;
|
||||
|
||||
// Connect to the vhost-user socket.
|
||||
let mut vu = VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false)?;
|
||||
let mut vu =
|
||||
VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false, None)?;
|
||||
|
||||
let (
|
||||
avail_features,
|
||||
|
||||
@@ -78,7 +78,8 @@ impl GenericVhostUser {
|
||||
let num_queues = request_queue_sizes.len();
|
||||
|
||||
// Connect to the vhost-user socket.
|
||||
let mut vu = VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false)?;
|
||||
let mut vu =
|
||||
VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false, None)?;
|
||||
|
||||
let (
|
||||
avail_features,
|
||||
|
||||
@@ -171,6 +171,8 @@ pub enum Error {
|
||||
EpollCtl(#[source] io::Error),
|
||||
#[error("Failed waiting on epoll")]
|
||||
EpollWait(#[source] io::Error),
|
||||
#[error("Aborted vhost-user connect: kill event received")]
|
||||
ConnectKilled,
|
||||
}
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
@@ -236,18 +238,25 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
|
||||
epoll::Events::EPOLLHUP,
|
||||
)?;
|
||||
|
||||
let mut vhost_user = VhostUserHandle::connect_vhost_user(
|
||||
let mut vhost_user = match VhostUserHandle::connect_vhost_user(
|
||||
self.server,
|
||||
&self.socket_path,
|
||||
self.queues.len() as u64,
|
||||
true,
|
||||
)
|
||||
.map_err(|e| {
|
||||
EpollHelperError::IoError(std::io::Error::other(format!(
|
||||
"failed connecting vhost-user backend for socket {}: {e:?}",
|
||||
self.socket_path
|
||||
)))
|
||||
})?;
|
||||
Some(&self.kill_evt),
|
||||
) {
|
||||
Ok(vu) => vu,
|
||||
// Kill event fired during the connect retry loop; abandon the
|
||||
// reconnect attempt. The EpollHelper observes the same kill
|
||||
// event and will tear down on its next iteration.
|
||||
Err(Error::ConnectKilled) => return Ok(()),
|
||||
Err(e) => {
|
||||
return Err(EpollHelperError::IoError(std::io::Error::other(format!(
|
||||
"failed connecting vhost-user backend for socket {}: {e:?}",
|
||||
self.socket_path
|
||||
))));
|
||||
}
|
||||
};
|
||||
|
||||
let queues = self
|
||||
.queues
|
||||
@@ -428,6 +437,7 @@ impl VhostUserCommon {
|
||||
&self.socket_path,
|
||||
self.vu_num_queues as u64,
|
||||
false,
|
||||
None,
|
||||
)?;
|
||||
|
||||
vu.set_protocol_features_vhost_user(acked_features, self.acked_protocol_features)?;
|
||||
|
||||
@@ -69,8 +69,13 @@ impl Net {
|
||||
) -> Result<Net> {
|
||||
let mut num_queues = vu_cfg.num_queues;
|
||||
|
||||
let mut vu =
|
||||
VhostUserHandle::connect_vhost_user(server, &vu_cfg.socket, num_queues as u64, false)?;
|
||||
let mut vu = VhostUserHandle::connect_vhost_user(
|
||||
server,
|
||||
&vu_cfg.socket,
|
||||
num_queues as u64,
|
||||
false,
|
||||
None,
|
||||
)?;
|
||||
|
||||
let (
|
||||
avail_features,
|
||||
|
||||
@@ -381,6 +381,7 @@ impl VhostUserHandle {
|
||||
socket_path: &str,
|
||||
num_queues: u64,
|
||||
unlink_socket: bool,
|
||||
kill_evt: Option<&EventFd>,
|
||||
) -> Result<Self> {
|
||||
if server {
|
||||
if unlink_socket {
|
||||
@@ -405,7 +406,12 @@ impl VhostUserHandle {
|
||||
} else {
|
||||
const RETRY_INTERVAL: Duration = Duration::from_millis(100);
|
||||
const CONNECT_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
const TIMER_EVENT: u64 = 0;
|
||||
|
||||
#[repr(u64)]
|
||||
enum ConnectEvent {
|
||||
Timer = 0,
|
||||
Kill = 1,
|
||||
}
|
||||
|
||||
let mut retry_timer = TimerFd::new().map_err(|e| Error::TimerFdCreate(e.into()))?;
|
||||
retry_timer
|
||||
@@ -417,10 +423,20 @@ impl VhostUserHandle {
|
||||
.ctl(
|
||||
ControlOperation::Add,
|
||||
retry_timer.as_raw_fd(),
|
||||
EpollEvent::new(EventSet::IN, TIMER_EVENT),
|
||||
EpollEvent::new(EventSet::IN, ConnectEvent::Timer as u64),
|
||||
)
|
||||
.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)?;
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
let mut events = [EpollEvent::default(); 1];
|
||||
|
||||
@@ -456,10 +472,21 @@ impl VhostUserHandle {
|
||||
}
|
||||
}
|
||||
|
||||
// Drain the timerfd so it stops signaling.
|
||||
retry_timer
|
||||
.wait()
|
||||
.map_err(|e| Error::TimerFdWait(e.into()))?;
|
||||
match events[0].data() {
|
||||
x if x == ConnectEvent::Kill as u64 => {
|
||||
info!(
|
||||
"Aborting vhost-user connect for socket {socket_path}: kill event received"
|
||||
);
|
||||
return Err(Error::ConnectKilled);
|
||||
}
|
||||
x if x == ConnectEvent::Timer as u64 => {
|
||||
// Drain the timerfd to clear the event.
|
||||
retry_timer
|
||||
.wait()
|
||||
.map_err(|e| Error::TimerFdWait(e.into()))?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user