diff --git a/Cargo.lock b/Cargo.lock index 08c3d57e3..8e89b3ed1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1386,6 +1386,7 @@ dependencies = [ "virtio-bindings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "vm-memory", "vm-virtio", + "vmm", "vmm-sys-util", ] diff --git a/vhost_user_block/Cargo.toml b/vhost_user_block/Cargo.toml index d88e8001e..5b89727f0 100644 --- a/vhost_user_block/Cargo.toml +++ b/vhost_user_block/Cargo.toml @@ -15,4 +15,5 @@ vhost_rs = { git = "https://github.com/cloud-hypervisor/vhost", branch = "dragon virtio-bindings = "0.1.0" vm-memory = "0.2.0" vm-virtio = { path = "../vm-virtio" } +vmm = { path = "../vmm" } vmm-sys-util = ">=0.3.1" diff --git a/vhost_user_block/src/lib.rs b/vhost_user_block/src/lib.rs index f60638cf3..a46befe96 100644 --- a/vhost_user_block/src/lib.rs +++ b/vhost_user_block/src/lib.rs @@ -38,6 +38,7 @@ use virtio_bindings::bindings::virtio_blk::*; use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX; use vm_memory::{Bytes, GuestMemoryMmap}; use vm_virtio::block::{build_disk_image_id, Request}; +use vmm::config::{OptionParser, OptionParserError, Toggle}; use vmm_sys_util::eventfd::EventFd; const QUEUE_SIZE: usize = 1024; @@ -57,24 +58,18 @@ type VhostUserBackendResult = std::result::Result; #[derive(Debug)] enum Error { - /// Failed to parse direct parameter. - ParseDirectParam, - /// Failed to parse image parameter. - ParseImageParam, - /// Failed to parse sock parameter. - ParseSockParam, - /// Failed to parse readonly parameter. - ParseReadOnlyParam, - /// Failed parsing fs number of queues parameter. - ParseBlkNumQueuesParam(std::num::ParseIntError), - /// Failed to parse the poll_queue parameter. - ParsePollQueueParam, - /// Failed to handle event other than input event. - HandleEventNotEpollIn, /// Failed to create kill eventfd CreateKillEventFd(io::Error), + /// Failed to parse configuration string + FailedConfigParse(OptionParserError), + /// Failed to handle event other than input event. + HandleEventNotEpollIn, /// Failed to handle unknown event. HandleEventUnknownEvent, + /// No path provided + PathParameterMissing, + /// No socket provided + SocketParameterMissing, } pub const SYNTAX: &str = "vhost-user-block backend parameters \ @@ -370,66 +365,52 @@ impl VhostUserBackend for VhostUserBlkBackend { } } -struct VhostUserBlkBackendConfig<'a> { - image: &'a str, - sock: &'a str, +struct VhostUserBlkBackendConfig { + path: String, + socket: String, num_queues: usize, readonly: bool, direct: bool, poll_queue: bool, } -impl<'a> VhostUserBlkBackendConfig<'a> { - fn parse(backend: &'a str) -> Result { - let params_list: Vec<&str> = backend.split(',').collect(); +impl VhostUserBlkBackendConfig { + fn parse(backend: &str) -> Result { + let mut parser = OptionParser::new(); + parser + .add("path") + .add("readonly") + .add("direct") + .add("num_queues") + .add("socket") + .add("poll_queue"); + parser.parse(backend).map_err(Error::FailedConfigParse)?; - let mut image: &str = ""; - let mut sock: &str = ""; - let mut num_queues_str: &str = ""; - let mut readonly: bool = false; - let mut direct: bool = false; - let mut poll_queue: bool = true; + let path = parser.get("path").ok_or(Error::PathParameterMissing)?; + let readonly = parser + .convert::("readonly") + .map_err(Error::FailedConfigParse)? + .unwrap_or(Toggle(false)) + .0; + let direct = parser + .convert::("direct") + .map_err(Error::FailedConfigParse)? + .unwrap_or(Toggle(false)) + .0; + let num_queues = parser + .convert("num_queues") + .map_err(Error::FailedConfigParse)? + .unwrap_or(1); + let socket = parser.get("socket").ok_or(Error::SocketParameterMissing)?; + let poll_queue = parser + .convert::("poll_queue") + .map_err(Error::FailedConfigParse)? + .unwrap_or_else(|| Toggle(true)) + .0; - for param in params_list.iter() { - if param.starts_with("path=") { - image = ¶m[5..]; - } else if param.starts_with("socket=") { - sock = ¶m[7..]; - } else if param.starts_with("num_queues=") { - num_queues_str = ¶m[11..]; - } else if param.starts_with("readonly=") { - readonly = match param[9..].parse::() { - Ok(b) => b, - Err(_) => return Err(Error::ParseReadOnlyParam), - } - } else if param.starts_with("direct=") { - direct = match param[7..].parse::() { - Ok(b) => b, - Err(_) => return Err(Error::ParseDirectParam), - } - } else if param.starts_with("poll_queue=") { - poll_queue = match param[11..].parse::() { - Ok(b) => b, - Err(_) => return Err(Error::ParsePollQueueParam), - } - } - } - - let mut num_queues: usize = 1; - if image.is_empty() { - return Err(Error::ParseImageParam); - } - if sock.is_empty() { - return Err(Error::ParseSockParam); - } - if !num_queues_str.is_empty() { - num_queues = num_queues_str - .parse() - .map_err(Error::ParseBlkNumQueuesParam)?; - } Ok(VhostUserBlkBackendConfig { - image, - sock, + path, + socket, num_queues, readonly, direct, @@ -449,7 +430,7 @@ pub fn start_block_backend(backend_command: &str) { let blk_backend = Arc::new(RwLock::new( VhostUserBlkBackend::new( - backend_config.image.to_string(), + backend_config.path, backend_config.num_queues, backend_config.readonly, backend_config.direct, @@ -461,12 +442,8 @@ pub fn start_block_backend(backend_command: &str) { debug!("blk_backend is created!\n"); let name = "vhost-user-blk-backend"; - let mut blk_daemon = VhostUserDaemon::new( - name.to_string(), - backend_config.sock.to_string(), - blk_backend.clone(), - ) - .unwrap(); + let mut blk_daemon = + VhostUserDaemon::new(name.to_string(), backend_config.socket, blk_backend.clone()).unwrap(); debug!("blk_daemon is created!\n"); if let Err(e) = blk_daemon.start() { diff --git a/vmm/src/config.rs b/vmm/src/config.rs index f612f8ffb..46c56fb0e 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -317,9 +317,9 @@ impl<'a> VmParams<'a> { } } -struct Toggle(bool); +pub struct Toggle(pub bool); -enum ToggleParseError { +pub enum ToggleParseError { InvalidValue(String), }