diff --git a/src/bin/vhost_user_blk.rs b/src/bin/vhost_user_blk.rs index f80bb3539..b5c6481d8 100644 --- a/src/bin/vhost_user_blk.rs +++ b/src/bin/vhost_user_blk.rs @@ -23,6 +23,7 @@ use std::fs::OpenOptions; use std::io::Read; use std::io::{Seek, SeekFrom, Write}; use std::mem; +use std::os::unix::fs::OpenOptionsExt; use std::path::PathBuf; use std::process; use std::slice; @@ -58,6 +59,8 @@ pub enum Error { GuestMemory(GuestMemoryError), /// Can't open image file. OpenImage, + /// Failed to parse direct parameter. + ParseDirectParam, /// Failed to parse image parameter. ParseImageParam, /// Failed to parse sock parameter. @@ -77,13 +80,15 @@ struct VhostUserBlkBackend { } impl VhostUserBlkBackend { - pub fn new(image_path: String, rdonly: bool) -> Result { - let image: File = OpenOptions::new() - .read(true) - .write(!rdonly) - .open(&image_path) - .unwrap(); - let mut raw_img = vm_virtio::RawFile::new(image, false); + pub fn new(image_path: String, rdonly: bool, direct: bool) -> Result { + let mut options = OpenOptions::new(); + options.read(true); + options.write(!rdonly); + if direct { + options.custom_flags(libc::O_DIRECT); + } + let image: File = options.open(&image_path).unwrap(); + let mut raw_img: vm_virtio::RawFile = vm_virtio::RawFile::new(image, direct); let image_id = build_disk_image_id(&PathBuf::from(&image_path)); let image_type = qcow::detect_image_type(&mut raw_img).unwrap(); @@ -225,6 +230,7 @@ pub struct VhostUserBlkBackendConfig<'a> { pub image: &'a str, pub sock: &'a str, pub readonly: bool, + pub direct: bool, } impl<'a> VhostUserBlkBackendConfig<'a> { @@ -234,6 +240,7 @@ impl<'a> VhostUserBlkBackendConfig<'a> { let mut image: &str = ""; let mut sock: &str = ""; let mut readonly: bool = false; + let mut direct: bool = false; for param in params_list.iter() { if param.starts_with("image=") { @@ -245,6 +252,11 @@ impl<'a> VhostUserBlkBackendConfig<'a> { 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), + } } } @@ -259,6 +271,7 @@ impl<'a> VhostUserBlkBackendConfig<'a> { image, sock, readonly, + direct, }) } } @@ -273,7 +286,8 @@ fn main() { .long("backend") .help( "Backend parameters \"image=,\ - sock=,readonly=true|false\"", + sock=,readonly=true|false,\ + direct=true|false\"", ) .takes_value(true) .min_values(1), @@ -291,8 +305,12 @@ fn main() { }; let blk_backend = Arc::new(RwLock::new( - VhostUserBlkBackend::new(backend_config.image.to_string(), backend_config.readonly) - .unwrap(), + VhostUserBlkBackend::new( + backend_config.image.to_string(), + backend_config.readonly, + backend_config.direct, + ) + .unwrap(), )); debug!("blk_backend is created!\n");