mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2025-12-25 22:18:59 +00:00
template: split into main.rs and lib.rs
Split functionality between library crate and an executable crate that consumes the library. Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
This commit is contained in:
parent
37e527045a
commit
6ec4e6eb29
@ -5,10 +5,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
use std::{
|
||||
convert,
|
||||
io::{self, Result as IoResult},
|
||||
};
|
||||
use std::io::Result as IoResult;
|
||||
|
||||
use log::{info, warn};
|
||||
use thiserror::Error as ThisError;
|
||||
@ -34,7 +31,7 @@ type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, ThisError)]
|
||||
/// Errors related to vhost-device-foo daemon.
|
||||
pub(crate) enum Error {
|
||||
pub enum Error {
|
||||
#[error("Failed to handle event, didn't match EPOLLIN")]
|
||||
HandleEventNotEpollIn,
|
||||
#[error("Failed to handle unknown event")]
|
||||
@ -47,13 +44,13 @@ pub(crate) enum Error {
|
||||
EventFdFailed,
|
||||
}
|
||||
|
||||
impl convert::From<Error> for io::Error {
|
||||
impl From<Error> for std::io::Error {
|
||||
fn from(e: Error) -> Self {
|
||||
io::Error::other(e)
|
||||
std::io::Error::other(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct VhostUserFooBackend {
|
||||
pub struct VhostUserFooBackend {
|
||||
info: FooInfo,
|
||||
event_idx: bool,
|
||||
pub exit_event: EventFd,
|
||||
@ -469,7 +466,7 @@ mod tests {
|
||||
.handle_event(0, EventSet::OUT, &[vring.clone()], 0)
|
||||
.unwrap_err()
|
||||
.kind(),
|
||||
io::ErrorKind::Other
|
||||
std::io::ErrorKind::Other
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@ -477,7 +474,7 @@ mod tests {
|
||||
.handle_event(1, EventSet::IN, &[vring.clone()], 0)
|
||||
.unwrap_err()
|
||||
.kind(),
|
||||
io::ErrorKind::Other
|
||||
std::io::ErrorKind::Other
|
||||
);
|
||||
|
||||
// Hit the loop part
|
||||
104
vhost-device-template/src/lib.rs
Normal file
104
vhost-device-template/src/lib.rs
Normal file
@ -0,0 +1,104 @@
|
||||
// VIRTIO FOO Emulation via vhost-user
|
||||
//
|
||||
// Copyright 2023 Linaro Ltd. All Rights Reserved.
|
||||
// Viresh Kumar <viresh.kumar@linaro.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
pub mod backend;
|
||||
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
sync::{Arc, RwLock},
|
||||
thread::{spawn, JoinHandle},
|
||||
};
|
||||
|
||||
use backend::VhostUserFooBackend;
|
||||
use log::error;
|
||||
use thiserror::Error as ThisError;
|
||||
use vhost_user_backend::VhostUserDaemon;
|
||||
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
/// Errors related to low level foo helpers
|
||||
pub enum Error {
|
||||
#[error("Could not create backend: {0}")]
|
||||
CouldNotCreateBackend(backend::Error),
|
||||
#[error("Could not create daemon: {0}")]
|
||||
CouldNotCreateDaemon(vhost_user_backend::Error),
|
||||
#[error("Fatal error: {0}")]
|
||||
ServeFailed(vhost_user_backend::Error),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct FooConfiguration {
|
||||
pub socket_path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct FooInfo {
|
||||
counter: u32,
|
||||
}
|
||||
|
||||
impl FooInfo {
|
||||
pub fn new() -> Self {
|
||||
Self { counter: 0 }
|
||||
}
|
||||
|
||||
pub fn counter(&mut self) -> u32 {
|
||||
self.counter += 1;
|
||||
self.counter
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FooInfo {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_backend(config: FooConfiguration) -> Result<()> {
|
||||
let socket_path = config.socket_path.clone();
|
||||
let info = FooInfo::new();
|
||||
|
||||
let handle: JoinHandle<Result<()>> = spawn(move || loop {
|
||||
// There isn't much value in complicating code here to return an error from the
|
||||
// threads, and so the code uses unwrap() instead. The panic on a thread
|
||||
// won't cause trouble to the main() function and should be safe for the
|
||||
// daemon.
|
||||
let backend = Arc::new(RwLock::new(
|
||||
VhostUserFooBackend::new(info).map_err(Error::CouldNotCreateBackend)?,
|
||||
));
|
||||
|
||||
let mut daemon = VhostUserDaemon::new(
|
||||
String::from("vhost-device-template-backend"),
|
||||
backend,
|
||||
GuestMemoryAtomic::new(GuestMemoryMmap::new()),
|
||||
)
|
||||
.map_err(Error::CouldNotCreateDaemon)?;
|
||||
|
||||
daemon.serve(&socket_path).map_err(Error::ServeFailed)?;
|
||||
});
|
||||
|
||||
handle.join().map_err(std::panic::resume_unwind).unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_fail_listener() {
|
||||
// This will fail the listeners and thread will panic.
|
||||
let socket_path = Path::new("/proc/foo/path/not/present").to_path_buf();
|
||||
let cmd_args = FooConfiguration { socket_path };
|
||||
|
||||
assert_matches!(start_backend(cmd_args).unwrap_err(), Error::ServeFailed(_));
|
||||
}
|
||||
}
|
||||
@ -5,35 +5,10 @@
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
mod vhu_foo;
|
||||
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
process::exit,
|
||||
sync::{Arc, RwLock},
|
||||
thread::{spawn, JoinHandle},
|
||||
};
|
||||
use std::{path::PathBuf, process::exit};
|
||||
|
||||
use clap::Parser;
|
||||
use log::error;
|
||||
use thiserror::Error as ThisError;
|
||||
use vhost_user_backend::VhostUserDaemon;
|
||||
use vhu_foo::VhostUserFooBackend;
|
||||
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
|
||||
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
/// Errors related to low level foo helpers
|
||||
pub(crate) enum Error {
|
||||
#[error("Could not create backend: {0}")]
|
||||
CouldNotCreateBackend(vhu_foo::Error),
|
||||
#[error("Could not create daemon: {0}")]
|
||||
CouldNotCreateDaemon(vhost_user_backend::Error),
|
||||
#[error("Fatal error: {0}")]
|
||||
ServeFailed(vhost_user_backend::Error),
|
||||
}
|
||||
|
||||
use vhost_device_template::{start_backend, Error, FooConfiguration, Result};
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct FooArgs {
|
||||
@ -42,11 +17,6 @@ struct FooArgs {
|
||||
socket_path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct FooConfiguration {
|
||||
socket_path: PathBuf,
|
||||
}
|
||||
|
||||
impl TryFrom<FooArgs> for FooConfiguration {
|
||||
type Error = Error;
|
||||
|
||||
@ -61,55 +31,12 @@ impl TryFrom<FooArgs> for FooConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct FooInfo {
|
||||
counter: u32,
|
||||
}
|
||||
|
||||
impl FooInfo {
|
||||
pub fn new() -> Self {
|
||||
Self { counter: 0 }
|
||||
}
|
||||
|
||||
pub fn counter(&mut self) -> u32 {
|
||||
self.counter += 1;
|
||||
self.counter
|
||||
}
|
||||
}
|
||||
|
||||
fn start_backend(args: FooArgs) -> Result<()> {
|
||||
let config = FooConfiguration::try_from(args).unwrap();
|
||||
|
||||
let socket_path = config.socket_path.clone();
|
||||
let info = FooInfo::new();
|
||||
|
||||
let handle: JoinHandle<Result<()>> = spawn(move || loop {
|
||||
// There isn't much value in complicating code here to return an error from the
|
||||
// threads, and so the code uses unwrap() instead. The panic on a thread
|
||||
// won't cause trouble to the main() function and should be safe for the
|
||||
// daemon.
|
||||
let backend = Arc::new(RwLock::new(
|
||||
VhostUserFooBackend::new(info).map_err(Error::CouldNotCreateBackend)?,
|
||||
));
|
||||
|
||||
let mut daemon = VhostUserDaemon::new(
|
||||
String::from("vhost-device-template-backend"),
|
||||
backend,
|
||||
GuestMemoryAtomic::new(GuestMemoryMmap::new()),
|
||||
)
|
||||
.map_err(Error::CouldNotCreateDaemon)?;
|
||||
|
||||
daemon.serve(&socket_path).map_err(Error::ServeFailed)?;
|
||||
});
|
||||
|
||||
handle.join().map_err(std::panic::resume_unwind).unwrap()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
if let Err(e) = start_backend(FooArgs::parse()) {
|
||||
error!("{e}");
|
||||
let config = FooConfiguration::try_from(FooArgs::parse()).unwrap();
|
||||
if let Err(e) = start_backend(config) {
|
||||
log::error!("{e}");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -118,8 +45,6 @@ fn main() {
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl FooArgs {
|
||||
@ -143,13 +68,4 @@ mod tests {
|
||||
|
||||
assert_eq!(config, expected_config);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fail_listener() {
|
||||
// This will fail the listeners and thread will panic.
|
||||
let socket_name = Path::new("~/path/not/present/foo");
|
||||
let cmd_args = FooArgs::from_args(socket_name);
|
||||
|
||||
assert_matches!(start_backend(cmd_args).unwrap_err(), Error::ServeFailed(_));
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user