From 25c6ac33621ced5d77db3aae385b4f2e317244f4 Mon Sep 17 00:00:00 2001 From: Erik Schilling Date: Fri, 7 Jul 2023 12:18:41 +0200 Subject: [PATCH] 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 --- staging/vhost-device-sound/src/lib.rs | 26 ++--------------- staging/vhost-device-video/src/main.rs | 38 ++++-------------------- vhost-device-gpio/src/backend.rs | 26 ++++------------- vhost-device-i2c/src/main.rs | 28 ++++-------------- vhost-device-rng/src/main.rs | 40 ++++++-------------------- vhost-device-scmi/src/main.rs | 28 +++--------------- vhost-device-scsi/src/main.rs | 35 ++++------------------ vhost-device-vsock/src/main.rs | 29 ++++++------------- 8 files changed, 45 insertions(+), 205 deletions(-) diff --git a/staging/vhost-device-sound/src/lib.rs b/staging/vhost-device-sound/src/lib.rs index 84f71dd..a1aa851 100644 --- a/staging/vhost-device-sound/src/lib.rs +++ b/staging/vhost-device-sound/src/lib.rs @@ -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)] diff --git a/staging/vhost-device-video/src/main.rs b/staging/vhost-device-video/src/main.rs index 5d4d756..d9f0d78 100644 --- a/staging/vhost-device-video/src/main.rs +++ b/staging/vhost-device-video/src/main.rs @@ -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"); diff --git a/vhost-device-gpio/src/backend.rs b/vhost-device-gpio/src/backend.rs index e0cc8c6..e1e2815 100644 --- a/vhost-device-gpio/src/backend.rs +++ b/vhost-device-gpio/src/backend.rs @@ -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(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(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(_)); } } diff --git a/vhost-device-i2c/src/main.rs b/vhost-device-i2c/src/main.rs index 457feba..eb838a0 100644 --- a/vhost-device-i2c/src/main.rs +++ b/vhost-device-i2c/src/main.rs @@ -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(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(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::(cmd_args).unwrap_err(), - Error::FailedJoiningThreads + Error::ServeFailed(_) ); } } diff --git a/vhost-device-rng/src/main.rs b/vhost-device-rng/src/main.rs index eac7ba8..b639aa5 100644 --- a/vhost-device-rng/src/main.rs +++ b/vhost-device-rng/src/main.rs @@ -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(_)); } } diff --git a/vhost-device-scmi/src/main.rs b/vhost-device-scmi/src/main.rs index 8a925d8..32b143d 100644 --- a/vhost-device-scmi/src/main.rs +++ b/vhost-device-scmi/src/main.rs @@ -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"); } } diff --git a/vhost-device-scsi/src/main.rs b/vhost-device-scsi/src/main.rs index cd075b8..1f0e9a6 100644 --- a/vhost-device-scsi/src/main.rs +++ b/vhost-device-scsi/src/main.rs @@ -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 = std::result::Result; @@ -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"); } diff --git a/vhost-device-vsock/src/main.rs b/vhost-device-vsock/src/main.rs index ab512e3..293779e 100644 --- a/vhost-device-vsock/src/main.rs +++ b/vhost-device-vsock/src/main.rs @@ -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), } @@ -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(); } }