performance-metrics: Add QCOW2 overlay tempfile helper

Add qcow_overlay_tempfile() which creates a raw backing file with
pre-populated data and a QCOW2 overlay on top with no allocated
clusters.  The overlay is opened with backing file support via
QcowDiskSync so reads fall through to the backing file.

To be used by backing file read and copy-on-write write
benchmarks.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-03-26 21:08:14 +01:00
committed by Rob Bradford
parent 99b4320279
commit bdce007aac

View File

@@ -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 {