diff --git a/performance-metrics/src/util.rs b/performance-metrics/src/util.rs index 09d6ad7e6..3ba9a9eee 100644 --- a/performance-metrics/src/util.rs +++ b/performance-metrics/src/util.rs @@ -5,11 +5,12 @@ //! Shared benchmark helpers. use std::io::{ErrorKind, Seek, SeekFrom, Write}; +use std::os::unix::fs::FileExt; use std::thread; use std::time::Duration; use block::async_io::AsyncIo; -use block::qcow::{QcowFile, RawFile}; +use block::qcow::{BackingFileConfig, ImageType, QcowFile, RawFile}; use block::qcow_async::QcowDiskAsync; use block::qcow_sync::QcowDiskSync; use vmm_sys_util::eventfd::EventFd; @@ -143,6 +144,44 @@ pub fn empty_qcow_tempfile(num_clusters: usize) -> (TempFile, QcowDiskSync) { (tmp, disk) } +/// Create a QCOW2 overlay backed by a raw file with `num_clusters` +/// pre-populated clusters. Returns (backing_tempfile, overlay_tempfile). +fn create_overlay_tempfiles(num_clusters: usize) -> (TempFile, TempFile) { + let virtual_size = QCOW_CLUSTER_SIZE * num_clusters as u64; + + let backing = TempFile::new().expect("failed to create backing tempfile"); + { + let f = backing.as_file(); + f.set_len(virtual_size).expect("set_len failed"); + let buf = vec![0xA5u8; QCOW_CLUSTER_SIZE as usize]; + for i in 0..num_clusters { + f.write_at(&buf, i as u64 * QCOW_CLUSTER_SIZE) + .expect("write_at failed"); + } + } + + let overlay = TempFile::new().expect("failed to create overlay tempfile"); + { + let raw = RawFile::new(overlay.as_file().try_clone().unwrap(), false); + let backing_config = BackingFileConfig { + path: backing.as_path().to_str().unwrap().to_string(), + format: Some(ImageType::Raw), + }; + QcowFile::new_from_backing(raw, 3, virtual_size, &backing_config, true) + .expect("failed to create overlay qcow2"); + } + + (backing, overlay) +} + +/// QCOW2 overlay with raw backing opened via QcowDiskSync. +pub fn qcow_overlay_tempfile(num_clusters: usize) -> (TempFile, TempFile, QcowDiskSync) { + let (backing, overlay) = create_overlay_tempfiles(num_clusters); + let disk = QcowDiskSync::new(overlay.as_file().try_clone().unwrap(), false, true, true) + .expect("failed to open overlay qcow2 via QcowDiskSync"); + (backing, overlay, disk) +} + /// Spin and wait until the given eventfd becomes readable. pub fn wait_for_eventfd(notifier: &EventFd) { loop {