tree-wide: use new serve convenience function

This become available with the recent vhost-user-backend [1] updates and
allows to get rid of some boilerplate code.

[1] https://github.com/rust-vmm/vhost/pull/173

Signed-off-by: Erik Schilling <erik.schilling@linaro.org>
This commit is contained in:
Erik Schilling 2023-07-07 12:18:41 +02:00 committed by Viresh Kumar
parent 9a6d12389f
commit 25c6ac3362
8 changed files with 45 additions and 205 deletions

View File

@ -42,10 +42,8 @@ use std::{
};
use clap::ValueEnum;
use log::{info, warn};
pub use stream::Stream;
use thiserror::Error as ThisError;
use vhost::{vhost_user, vhost_user::Listener};
use vhost_user_backend::{VhostUserDaemon, VringRwLock, VringT};
use virtio_sound::*;
use vm_memory::{
@ -347,36 +345,18 @@ impl Drop for IOMessage {
/// vhost-device-sound backend server.
pub fn start_backend_server(config: SoundConfig) {
log::trace!("Using config {:?}.", &config);
let listener = Listener::new(config.get_socket_path(), true).unwrap();
let socket = config.get_socket_path();
let backend = Arc::new(VhostUserSoundBackend::new(config).unwrap());
let mut daemon = VhostUserDaemon::new(
String::from("vhost-device-sound"),
backend.clone(),
backend,
GuestMemoryAtomic::new(GuestMemoryMmap::new()),
)
.unwrap();
log::trace!("Starting daemon.");
daemon.start(listener).unwrap();
match daemon.wait() {
Ok(()) => {
info!("Stopping cleanly.");
}
Err(vhost_user_backend::Error::HandleRequest(vhost_user::Error::PartialMessage)) => {
info!(
"vhost-user connection closed with partial message. If the VM is shutting down, \
this is expected behavior; otherwise, it might be a bug."
);
}
Err(e) => {
warn!("Error running daemon: {:?}", e);
}
}
// No matter the result, we need to shut down the worker thread.
backend.send_exit_event();
daemon.serve(socket).unwrap();
}
#[cfg(test)]

View File

@ -11,9 +11,8 @@ use std::{
};
use clap::Parser;
use log::{info, warn};
use log::info;
use thiserror::Error as ThisError;
use vhost::{vhost_user, vhost_user::Listener};
use vhost_user_backend::VhostUserDaemon;
use vhu_video::{BackendType, VuVideoBackend};
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
@ -26,8 +25,8 @@ pub(crate) enum Error {
CouldNotCreateBackend(vhu_video::VuVideoError),
#[error("Could not create daemon: {0}")]
CouldNotCreateDaemon(vhost_user_backend::Error),
#[error("Failed creating listener: {0}")]
FailedCreatingListener(vhost_user::Error),
#[error("Fatal error: {0}")]
ServeFailed(vhost_user_backend::Error),
}
#[derive(Clone, Parser, Debug)]
@ -91,33 +90,8 @@ pub(crate) fn start_backend(config: VuVideoConfig) -> Result<()> {
}
daemon
.start(Listener::new(&config.socket_path, true).map_err(Error::FailedCreatingListener)?)
.expect("Stargin daemon");
match daemon.wait() {
Ok(()) => {
info!("Stopping cleanly");
}
Err(vhost_user_backend::Error::HandleRequest(
vhost_user::Error::PartialMessage | vhost_user::Error::Disconnected,
)) => {
info!(
"vhost-user connection closed with partial message.
If the VM is shutting down, this is expected behavior;
otherwise, it might be a bug."
);
}
Err(e) => {
warn!("Error running daemon: {:?} -> {}", e, e.to_string());
}
}
vu_video_backend
.read()
.unwrap()
.exit_event
.write(1)
.expect("Shutting down worker thread");
.serve(&config.socket_path)
.map_err(Error::ServeFailed)?;
}
}
@ -193,7 +167,7 @@ mod tests {
};
assert_matches!(
start_backend(VuVideoConfig::try_from(config).unwrap()).unwrap_err(),
Error::FailedCreatingListener(_)
Error::ServeFailed(_)
);
// cleanup
std::fs::remove_file(v4l2_device).expect("Failed to clean up");

View File

@ -5,7 +5,7 @@
//
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
use log::{error, info, warn};
use log::error;
use std::num::ParseIntError;
use std::process::exit;
use std::sync::{Arc, RwLock};
@ -14,7 +14,6 @@ use std::thread::{spawn, JoinHandle};
use clap::Parser;
use env_logger::Env;
use thiserror::Error as ThisError;
use vhost::{vhost_user, vhost_user::Listener};
use vhost_user_backend::VhostUserDaemon;
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
@ -47,6 +46,8 @@ pub(crate) enum Error {
CouldNotCreateBackend(crate::vhu_gpio::Error),
#[error("Could not create daemon: {0}")]
CouldNotCreateDaemon(vhost_user_backend::Error),
#[error("Fatal error: {0}")]
ServeFailed(vhost_user_backend::Error),
}
const GPIO_AFTER_HELP: &str = "Each device number here will be used to \
@ -179,7 +180,6 @@ fn start_device_backend<D: GpioDevice>(device: D, socket: String) -> Result<()>
let backend = Arc::new(RwLock::new(
VhostUserGpioBackend::new(controller).map_err(Error::CouldNotCreateBackend)?,
));
let listener = Listener::new(socket, true).unwrap();
let mut daemon = VhostUserDaemon::new(
String::from("vhost-device-gpio-backend"),
@ -188,21 +188,8 @@ fn start_device_backend<D: GpioDevice>(device: D, socket: String) -> Result<()>
)
.map_err(Error::CouldNotCreateDaemon)?;
daemon.start(listener).unwrap();
daemon.serve(&socket).map_err(Error::ServeFailed)?;
match daemon.wait() {
Ok(()) => {
info!("Stopping cleanly.");
}
Err(vhost_user_backend::Error::HandleRequest(vhost_user::Error::PartialMessage)) => {
info!("vhost-user connection closed with partial message. If the VM is shutting down, this is expected behavior; otherwise, it might be a bug.");
}
Err(e) => {
warn!("Error running daemon: {:?}", e);
}
}
// No matter the result, we need to shut down the worker thread.
backend.read().unwrap().exit_event.write(1).unwrap();
Ok(())
}
@ -360,9 +347,6 @@ mod tests {
let socket_name = "~/path/not/present/gpio";
let cmd_args = get_cmd_args(socket_name, "s1:s4:s3:s5", 4);
assert_matches!(
start_backend(cmd_args).unwrap_err(),
Error::FailedJoiningThreads
);
assert_matches!(start_backend(cmd_args).unwrap_err(), Error::ServeFailed(_));
}
}

View File

@ -8,7 +8,7 @@
mod i2c;
mod vhu_i2c;
use log::{error, info, warn};
use log::error;
use std::num::ParseIntError;
use std::process::exit;
use std::sync::{Arc, RwLock};
@ -16,7 +16,6 @@ use std::thread::{spawn, JoinHandle};
use clap::Parser;
use thiserror::Error as ThisError;
use vhost::{vhost_user, vhost_user::Listener};
use vhost_user_backend::VhostUserDaemon;
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
@ -46,6 +45,8 @@ pub(crate) enum Error {
CouldNotCreateBackend(vhu_i2c::Error),
#[error("Could not create daemon: {0}")]
CouldNotCreateDaemon(vhost_user_backend::Error),
#[error("Fatal error: {0}")]
ServeFailed(vhost_user_backend::Error),
}
#[derive(Parser, Debug)]
@ -199,7 +200,6 @@ fn start_backend<D: 'static + I2cDevice + Send + Sync>(args: I2cArgs) -> Result<
let backend = Arc::new(RwLock::new(
VhostUserI2cBackend::new(i2c_map.clone()).map_err(Error::CouldNotCreateBackend)?,
));
let listener = Listener::new(socket.clone(), true).unwrap();
let mut daemon = VhostUserDaemon::new(
String::from("vhost-device-i2c-backend"),
@ -208,24 +208,7 @@ fn start_backend<D: 'static + I2cDevice + Send + Sync>(args: I2cArgs) -> Result<
)
.map_err(Error::CouldNotCreateDaemon)?;
daemon.start(listener).unwrap();
match daemon.wait() {
Ok(()) => {
info!("Stopping cleanly.");
}
Err(vhost_user_backend::Error::HandleRequest(
vhost_user::Error::PartialMessage | vhost_user::Error::Disconnected,
)) => {
info!("vhost-user connection closed with partial message. If the VM is shutting down, this is expected behavior; otherwise, it might be a bug.");
}
Err(e) => {
warn!("Error running daemon: {:?}", e);
}
}
// No matter the result, we need to shut down the worker thread.
backend.read().unwrap().exit_event.write(1).unwrap();
daemon.serve(&socket).map_err(Error::ServeFailed)?;
});
handles.push(handle);
@ -250,6 +233,7 @@ fn main() {
#[cfg(test)]
mod tests {
use assert_matches::assert_matches;
use vhost::vhost_user::Listener;
use super::*;
use crate::i2c::tests::DummyDevice;
@ -394,7 +378,7 @@ mod tests {
assert_matches!(
start_backend::<DummyDevice>(cmd_args).unwrap_err(),
Error::FailedJoiningThreads
Error::ServeFailed(_)
);
}
}

View File

@ -5,7 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
mod vhu_rng;
use log::{error, info, warn};
use log::error;
use std::fs::File;
use std::process::exit;
use std::sync::{Arc, Mutex, RwLock};
@ -13,7 +13,6 @@ use std::thread::{self, JoinHandle};
use clap::Parser;
use thiserror::Error as ThisError;
use vhost::{vhost_user, vhost_user::Listener};
use vhost_user_backend::VhostUserDaemon;
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
@ -40,6 +39,8 @@ pub(crate) enum Error {
CouldNotCreateBackend(std::io::Error),
#[error("Could not create daemon: {0}")]
CouldNotCreateDaemon(vhost_user_backend::Error),
#[error("Fatal error: {0}")]
ServeFailed(vhost_user_backend::Error),
}
#[derive(Clone, Parser, Debug, PartialEq)]
@ -131,30 +132,7 @@ pub(crate) fn start_backend(config: VuRngConfig) -> Result<()> {
)
.map_err(Error::CouldNotCreateDaemon)?;
let listener = Listener::new(socket.clone(), true).unwrap();
daemon.start(listener).unwrap();
match daemon.wait() {
Ok(()) => {
info!("Stopping cleanly.");
}
Err(vhost_user_backend::Error::HandleRequest(
vhost_user::Error::PartialMessage | vhost_user::Error::Disconnected,
)) => {
info!("vhost-user connection closed with partial message. If the VM is shutting down, this is expected behavior; otherwise, it might be a bug.");
}
Err(e) => {
warn!("Error running daemon: {:?}", e);
}
}
// No matter the result, we need to shut down the worker thread.
vu_rng_backend
.read()
.unwrap()
.exit_event
.write(1)
.expect("Shutting down worker thread");
daemon.serve(&socket).map_err(Error::ServeFailed)?;
});
handles.push(handle);
@ -243,12 +221,10 @@ mod tests {
);
// Set the RNG source to something valid, forcing the code to check the validity
// of the socket file. Since the latter is invalid the vhost_user::Listener will
// throw an error, forcing the thread to exit and the call to handle.join() to fail.
// of the socket file. Since the latter is invalid, serving will throw
// an error, forcing the thread to exit and the call to handle.join()
// to fail.
config.rng_source = random_path.to_str().unwrap().to_string();
assert_matches!(
start_backend(config).unwrap_err(),
Error::FailedJoiningThreads
);
assert_matches!(start_backend(config).unwrap_err(), Error::ServeFailed(_));
}
}

View File

@ -45,10 +45,8 @@ use std::{
use clap::{CommandFactory, Parser};
use itertools::Itertools;
use log::{debug, error, info, warn};
use log::{debug, error};
use vhost::vhost_user;
use vhost::vhost_user::Listener;
use vhost_user_backend::VhostUserDaemon;
use vhu_scmi::VuScmiBackend;
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
@ -113,7 +111,6 @@ fn start_backend(config: VuScmiConfig) -> Result<()> {
}
let backend = Arc::new(RwLock::new(backend_instance.unwrap()));
let listener = Listener::new(config.socket_path.clone(), true).unwrap();
let mut daemon = VhostUserDaemon::new(
"vhost-device-scmi".to_owned(),
backend.clone(),
@ -121,26 +118,9 @@ fn start_backend(config: VuScmiConfig) -> Result<()> {
)
.unwrap();
daemon.start(listener).unwrap();
match daemon.wait() {
Ok(()) => {
info!("Stopping cleanly");
}
Err(vhost_user_backend::Error::HandleRequest(vhost_user::Error::PartialMessage)) => {
info!(
"vhost-user connection closed with partial message.
If the VM is shutting down, this is expected behavior;
otherwise, it might be a bug."
);
}
Err(e) => {
warn!("Error running daemon: {:?}", e);
}
}
// No matter the result, we need to shut down the worker thread.
backend.read().unwrap().exit_event.write(1).unwrap();
daemon
.serve(&config.socket_path)
.map_err(|e| format!("{e}"))?;
debug!("Finishing backend");
}
}

View File

@ -12,9 +12,8 @@ use std::{
};
use clap::Parser;
use log::{error, info, warn};
use log::{error, warn};
use thiserror::Error as ThisError;
use vhost::vhost_user::{self, Listener};
use vhost_user_backend::VhostUserDaemon;
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
@ -28,8 +27,8 @@ use crate::vhu_scsi::VhostUserScsiBackend;
enum Error {
#[error("More than 256 LUNs aren't currently supported")]
TooManyLUNs,
#[error("Failed creating listener: {0}")]
FailedCreatingListener(vhost_user::Error),
#[error("Failed serving the daemon: {0}")]
ServeFailed(vhost_user_backend::Error),
}
type Result<T> = std::result::Result<T, Error>;
@ -100,32 +99,8 @@ fn start_backend(backend: VhostUserScsiBackend, args: ScsiArgs) -> Result<()> {
)
.expect("Creating daemon");
daemon
.start(Listener::new(args.socket_path, true).map_err(Error::FailedCreatingListener)?)
.expect("Starting daemon");
daemon.serve(args.socket_path).map_err(Error::ServeFailed)?;
match daemon.wait() {
Ok(()) => {
info!("Stopping cleanly.");
}
Err(vhost_user_backend::Error::HandleRequest(
vhost_user::Error::PartialMessage | vhost_user::Error::Disconnected,
)) => {
info!("vhost-user connection closed with partial message. If the VM is shutting down, this is expected behavior; otherwise, it might be a bug.");
}
Err(e) => {
warn!("Error running daemon: {:?}", e);
}
}
// No matter the result, we need to shut down the worker thread.
// unwrap will only panic if we already panicked somewhere else
backend
.read()
.unwrap()
.exit_event
.write(1)
.expect("Shutting down worker thread");
Ok(())
}
@ -172,7 +147,7 @@ mod tests {
};
let backend = create_backend(&args).unwrap();
let err = start_backend(backend, args).unwrap_err();
if let Error::FailedCreatingListener(_) = err {
if let Error::ServeFailed(_) = err {
} else {
panic!("expected failure when creating listener");
}

View File

@ -19,10 +19,9 @@ use std::{
use crate::vhu_vsock::{CidMap, VhostUserVsockBackend, VsockConfig};
use clap::{Args, Parser};
use log::{error, info, warn};
use log::error;
use serde::Deserialize;
use thiserror::Error as ThisError;
use vhost::{vhost_user, vhost_user::Listener};
use vhost_user_backend::VhostUserDaemon;
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
@ -56,6 +55,8 @@ enum BackendError {
CouldNotCreateBackend(vhu_vsock::Error),
#[error("Could not create daemon: {0}")]
CouldNotCreateDaemon(vhost_user_backend::Error),
#[error("Fatal error: {0}")]
ServeFailed(vhost_user_backend::Error),
#[error("Thread `{0}` panicked")]
ThreadPanic(String, Box<dyn Any + Send>),
}
@ -228,8 +229,6 @@ pub(crate) fn start_backend_server(
.map_err(BackendError::CouldNotCreateBackend)?,
);
let listener = Listener::new(config.get_socket_path(), true).unwrap();
let mut daemon = VhostUserDaemon::new(
String::from("vhost-device-vsock"),
backend.clone(),
@ -246,24 +245,12 @@ pub(crate) fn start_backend_server(
.register_listeners(epoll_handlers.remove(0));
}
daemon.start(listener).unwrap();
match daemon.wait() {
Ok(()) => {
info!("Stopping cleanly");
}
Err(vhost_user_backend::Error::HandleRequest(
vhost_user::Error::PartialMessage | vhost_user::Error::Disconnected,
)) => {
info!("vhost-user connection closed with partial message. If the VM is shutting down, this is expected behavior; otherwise, it might be a bug.");
}
Err(e) => {
warn!("Error running daemon: {:?}", e);
}
if let Err(e) = daemon
.serve(config.get_socket_path())
.map_err(BackendError::ServeFailed)
{
error!("{e}");
}
// No matter the result, we need to shut down the worker thread.
backend.exit_event.write(1).unwrap();
}
}