Add virtio block test util Change-Id: Icb0fe5d324fa56542cbdad84f70b6e507ffd377d
diff --git a/Cargo.lock b/Cargo.lock index e12886a..6598979 100644 --- a/Cargo.lock +++ b/Cargo.lock
@@ -1,4 +1,179 @@ [[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6", +] + +[[package]] +name = "atty" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6", +] + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.43" + +[[package]] +name = "libc" +version = "0.2.43" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "linux_tests" version = "0.1.0" +dependencies = [ + "libc 0.2.43", + "structopt 0.2.12", +] +[[package]] +name = "proc-macro2" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.2.12" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" + +[[patch.unused]] +name = "winapi-build" +version = "0.3.6" + +[[patch.unused]] +name = "winapi-util" +version = "0.1.1" + +[metadata] +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" +"checksum redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cf8fb82a4d1c9b28f1c26c574a5b541f5ffb4315f6c9a791fa47b6a04438fe93" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum structopt-derive 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "17ff01fe96de9d16e7372ae5f19dd7ece2c703b51043c3db9ea27f9e393ea311" +"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
diff --git a/Cargo.toml b/Cargo.toml index 003dfd4..d401652 100644 --- a/Cargo.toml +++ b/Cargo.toml
@@ -11,4 +11,11 @@ license = "BSD-3-Clause" edition = "2018" -[dependencies] \ No newline at end of file +[dependencies] +structopt = { path = "rust-crates/rustc_deps/vendor/structopt" } +libc = { path = "rust-crates/rustc_deps/vendor/libc" } + +[patch.crates-io] +winapi = { path = "rust-crates/rustc_deps/tiny_mirrors/winapi" } +winapi-build = { path = "rust-crates/rustc_deps/tiny_mirrors/winapi-build" } +winapi-util = { path = "rust-crates/rustc_deps/tiny_mirrors/winapi-util" }
diff --git a/build.sh b/build.sh index 87e4eae..3557af4 100755 --- a/build.sh +++ b/build.sh
@@ -37,6 +37,7 @@ mkdir -p ${OUT_DIR} cp target/${TARGET}/debug/virtio_rng_test_util ${OUT_DIR} +cp target/${TARGET}/debug/virtio_block_test_util ${OUT_DIR} declare -r BLOCK_SIZE=4096 declare -r ADDITIONAL_BLOCKS=1024
diff --git a/src/bin/virtio_block_test_util.rs b/src/bin/virtio_block_test_util.rs new file mode 100644 index 0000000..59d6964 --- /dev/null +++ b/src/bin/virtio_block_test_util.rs
@@ -0,0 +1,138 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#![deny(warnings)] + +use libc::{self, c_int}; +use std::fs::{self, File, OpenOptions}; +use std::io::{Error, ErrorKind, Read, Seek, SeekFrom, Write}; +use std::os::unix::io::AsRawFd; +use std::path::Path; +use structopt::StructOpt; + +const DEV_DIR: &str = "/dev"; + +// Ioctl requests are comprised of 32 bits: +// [31:30] Access mode +// [29:16] Size of the parameter structure +// [15:8] Request type +// [7:0] Request number +// For the ioctls we care about here there are no parameters, so we set only a type and a number. +// See Linux:include/uapi/asm-generic/ioctl.h for more details. +const TYPE_SHIFT: usize = 8; +macro_rules! define_ioctl { + ($name:ident, $typ:expr, $num:expr, $return_type:ty) => { + fn $name(file: &File) -> $return_type { + let request: c_int = ($typ << TYPE_SHIFT) | ($num & 0xff); + let mut r: $return_type = 0; + unsafe { + libc::ioctl(file.as_raw_fd(), request, &mut r); + } + r + } + }; +} + +// Block ioctl types and number are defined in Linux:include/uapi/linux/fs.h. +define_ioctl!(block_dev_size, 0x12, 96, u64); +define_ioctl!(block_dev_sector_size, 0x12, 104, u32); + +#[derive(StructOpt, Debug)] +struct Config { + block_size: u32, + block_count: u64, + #[structopt(subcommand)] + cmd: Command, +} + +#[derive(StructOpt, Debug)] +enum Command { + #[structopt(name = "check")] + Check, + #[structopt(name = "read")] + Read { offset: u64, expected: u8 }, + #[structopt(name = "write")] + Write { offset: u64, value: u8 }, +} + +fn find_block_device(block_size: u32, block_count: u64, write: bool) -> std::io::Result<File> { + let dir = Path::new(DEV_DIR); + if !dir.is_dir() { + return Err(Error::new( + ErrorKind::Other, + format!("{} is not a directory", DEV_DIR), + )); + } + for entry in fs::read_dir(dir)?.collect::<std::io::Result<Vec<_>>>()? { + if !entry + .file_name() + .to_str() + .map_or(false, |f| f.starts_with("vd")) + { + continue; + } + let file = OpenOptions::new() + .read(true) + .write(write) + .open(entry.path())?; + if block_size != block_dev_sector_size(&file) { + continue; + } + if block_count != block_dev_size(&file) { + continue; + } + return Ok(file); + } + Err(Error::new(ErrorKind::NotFound, "Block device not found")) +} + +fn read_block( + block_dev: &mut File, + block_size: u32, + offset: u64, + expected: u8, +) -> std::io::Result<()> { + block_dev.seek(SeekFrom::Start(offset * block_size as u64))?; + let mut data: Vec<u8> = vec![0; block_size as usize]; + block_dev.read_exact(&mut data)?; + if !data.iter().all(|&b| b == expected) { + return Err(Error::new(ErrorKind::Other, "Incorrect data read")); + } + Ok(()) +} + +fn write_block( + block_dev: &mut File, + block_size: u32, + offset: u64, + value: u8, +) -> std::io::Result<()> { + block_dev.seek(SeekFrom::Start(offset * block_size as u64))?; + let data: Vec<u8> = vec![value; block_size as usize]; + block_dev.write_all(&data)?; + block_dev.sync_all()?; + Ok(()) +} + +fn main() -> std::io::Result<()> { + let config = Config::from_args(); + let write = if let Command::Write { .. } = config.cmd { + true + } else { + false + }; + let mut block_dev = find_block_device(config.block_size, config.block_count, write)?; + let result = match config.cmd { + Command::Check => Ok(()), + Command::Read { offset, expected } => { + read_block(&mut block_dev, config.block_size, offset, expected) + } + Command::Write { offset, value } => { + write_block(&mut block_dev, config.block_size, offset, value) + } + }; + if result.is_ok() { + println!("PASS"); + } + result +}