performance-metrics: Add compressed QCOW2 tempfile helper

Add compressed_qcow_tempfile() which creates a zlib compressed QCOW2
image by populating a RAW tempfile with data and converting it via
qemu-img convert -c.  Every cluster in the resulting image is stored
compressed so reads exercise the decompression path.

To be used by the compressed read benchmark.

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

View File

@@ -4,8 +4,10 @@
//! Shared benchmark helpers.
use std::fs::File;
use std::io::{ErrorKind, Seek, SeekFrom, Write};
use std::os::unix::fs::FileExt;
use std::process::Command;
use std::thread;
use std::time::Duration;
@@ -182,6 +184,59 @@ pub fn qcow_overlay_tempfile(num_clusters: usize) -> (TempFile, TempFile, QcowDi
(backing, overlay, disk)
}
/// Create a zlib compressed QCOW2 image with `num_clusters` clusters
/// via `qemu-img convert -c`.
fn create_compressed_qcow_tempfile(num_clusters: usize) -> TempFile {
let virtual_size = QCOW_CLUSTER_SIZE * num_clusters as u64;
let raw_tmp = TempFile::new().expect("failed to create raw tempfile");
{
let f = raw_tmp.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 qcow_tmp = TempFile::new().expect("failed to create qcow2 tempfile");
let qcow_path = qcow_tmp.as_path().to_str().unwrap().to_string();
let raw_path = raw_tmp.as_path().to_str().unwrap().to_string();
let status = Command::new("qemu-img")
.args([
"convert",
"-f",
"raw",
"-O",
"qcow2",
"-c",
"-o",
"compression_type=zlib",
&raw_path,
&qcow_path,
])
.status()
.expect("failed to run qemu-img");
assert!(status.success(), "qemu-img convert failed");
qcow_tmp
}
/// Compressed QCOW2 opened via QcowDiskSync.
pub fn compressed_qcow_tempfile(num_clusters: usize) -> (TempFile, QcowDiskSync) {
let tmp = create_compressed_qcow_tempfile(num_clusters);
let path = tmp.as_path().to_str().unwrap().to_string();
let disk = QcowDiskSync::new(
File::open(&path).expect("failed to open compressed qcow2"),
false,
false,
true,
)
.expect("failed to open compressed qcow2 via QcowDiskSync");
(tmp, disk)
}
/// Spin and wait until the given eventfd becomes readable.
pub fn wait_for_eventfd(notifier: &EventFd) {
loop {