mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
block: qcow: Port tests to QcowTempDisk
Port tests over to QcowTempDisk and also over to QcowDisk rather than QcowFile where necessary. Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
@@ -205,13 +205,12 @@ fn open_qcow2(
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use vmm_sys_util::tempfile::TempFile;
|
||||
|
||||
use super::*;
|
||||
use crate::qcow::{QcowFile, RawFile};
|
||||
use crate::formats::qcow;
|
||||
|
||||
fn default_options(path: &Path) -> DiskOpenOptions<'_> {
|
||||
DiskOpenOptions {
|
||||
@@ -247,12 +246,9 @@ mod unit_tests {
|
||||
|
||||
#[test]
|
||||
fn detect_qcow2_image() {
|
||||
let tmp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(tmp.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow = QcowFile::new(raw, 3, 100 * 1024 * 1024, true).unwrap();
|
||||
qcow.flush().unwrap();
|
||||
}
|
||||
let tmp = qcow::QcowTempDisk::new(100 * 1024 * 1024, None, false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
let path = tmp.as_path().to_owned();
|
||||
let options = default_options(&path);
|
||||
let opened = open_disk(&options).unwrap();
|
||||
|
||||
@@ -18,6 +18,7 @@ use std::os::unix::io::AsRawFd;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, io};
|
||||
|
||||
use vm_memory::{Bytes, GuestAddress, GuestMemoryMmap};
|
||||
#[cfg(test)]
|
||||
use vmm_sys_util::tempfile::TempFile;
|
||||
|
||||
@@ -30,8 +31,9 @@ use self::internal::{MAX_NESTING_DEPTH, RawFile, parse_qcow};
|
||||
#[cfg(feature = "io_uring")]
|
||||
use self::worker::async_uring::QcowAsync;
|
||||
use self::worker::sync::QcowSync;
|
||||
use crate::async_io::{AsyncIo, BorrowedDiskFd, DiskFileError};
|
||||
use crate::async_io::{AsyncIo, BorrowedDiskFd, DiskFileError, GuestMemoryTarget};
|
||||
use crate::disk_file;
|
||||
use crate::disk_file::AsyncDiskFile;
|
||||
use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp};
|
||||
|
||||
/// Unified DiskFile wrapper for QCOW2 disk images.
|
||||
@@ -102,6 +104,20 @@ impl QcowDisk {
|
||||
use_io_uring,
|
||||
})
|
||||
}
|
||||
|
||||
/// Synchronous write convenience for tests and benchmarks.
|
||||
pub fn write_all_at(&self, offset: u64, data: &[u8]) {
|
||||
let mut async_io = self.create_async_io(1).unwrap();
|
||||
let mem =
|
||||
Arc::new(GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), data.len())]).unwrap());
|
||||
mem.write_slice(data, GuestAddress(0)).unwrap();
|
||||
let range = [(GuestAddress(0), data.len() as u32)];
|
||||
let target = GuestMemoryTarget::new(Arc::clone(&mem), &range).unwrap();
|
||||
async_io
|
||||
.write_from_memory(offset as libc::off_t, target, 0)
|
||||
.unwrap();
|
||||
while async_io.next_completed_request().is_some() {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes a fresh qcow2 layout into `file`
|
||||
@@ -288,9 +304,6 @@ impl disk_file::AsyncDiskFile for QcowDisk {
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use vmm_sys_util::tempfile::TempFile;
|
||||
|
||||
use self::internal::{QcowFile, RawFile};
|
||||
use super::*;
|
||||
use crate::async_io::AsyncIo;
|
||||
use crate::disk_file::{AsyncDiskFile, DiskSize, PhysicalSize};
|
||||
@@ -298,12 +311,10 @@ mod unit_tests {
|
||||
const TEST_SIZE: u64 = 0x5566_7788;
|
||||
|
||||
fn make_qcow_file() -> File {
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
QcowFile::new(raw, 3, TEST_SIZE, true).unwrap();
|
||||
}
|
||||
temp_file.into_file()
|
||||
QcowTempDisk::new(TEST_SIZE, None, false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile()
|
||||
.into_file()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -523,7 +523,7 @@ impl QcowAsync {
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use std::io::{Seek, SeekFrom, Write};
|
||||
use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
@@ -534,9 +534,9 @@ mod unit_tests {
|
||||
use crate::SECTOR_SIZE;
|
||||
use crate::async_io::{AsyncIoCompletion, AsyncIoOperation, GuestMemoryTarget, OwnedIoBuffer};
|
||||
use crate::disk_file::AsyncDiskFile;
|
||||
use crate::formats::qcow::QcowDisk;
|
||||
use crate::formats::qcow::common::unit_tests::compress_allocated_clusters;
|
||||
use crate::formats::qcow::internal::{BackingFileConfig, ImageType, QcowFile, RawFile};
|
||||
use crate::formats::qcow::internal::{BackingFileConfig, ImageType};
|
||||
use crate::formats::qcow::{QcowDisk, QcowTempDisk};
|
||||
|
||||
fn create_disk_with_data(
|
||||
file_size: u64,
|
||||
@@ -544,14 +544,15 @@ mod unit_tests {
|
||||
offset: u64,
|
||||
sparse: bool,
|
||||
) -> (TempFile, QcowDisk) {
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow_file = QcowFile::new(raw_file, 3, file_size, sparse).unwrap();
|
||||
qcow_file.seek(SeekFrom::Start(offset)).unwrap();
|
||||
qcow_file.write_all(data).unwrap();
|
||||
qcow_file.flush().unwrap();
|
||||
}
|
||||
let temp_file = if data.is_empty() {
|
||||
QcowTempDisk::new(file_size, None, false, sparse, true)
|
||||
.unwrap()
|
||||
.into_tempfile()
|
||||
} else {
|
||||
let tmp_disk = QcowTempDisk::new(file_size, None, false, sparse, true).unwrap();
|
||||
tmp_disk.disk().write_all_at(offset, data);
|
||||
tmp_disk.into_tempfile()
|
||||
};
|
||||
let disk = QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
false,
|
||||
@@ -573,15 +574,13 @@ mod unit_tests {
|
||||
backing_temp.as_file().sync_all().unwrap();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let disk = QcowDisk::new(
|
||||
overlay_temp.as_file().try_clone().unwrap(),
|
||||
@@ -722,11 +721,9 @@ mod unit_tests {
|
||||
#[test]
|
||||
fn test_qcow_async_write_read_roundtrip() {
|
||||
let file_size = 100 * 1024 * 1024;
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
QcowFile::new(raw_file, 3, file_size, true).unwrap();
|
||||
}
|
||||
let temp_file = QcowTempDisk::new(file_size, None, false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
let disk = QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
false,
|
||||
@@ -805,11 +802,9 @@ mod unit_tests {
|
||||
#[test]
|
||||
fn test_qcow_async_sync_write_from_guest_memory() {
|
||||
let file_size = 100 * 1024 * 1024;
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
QcowFile::new(raw_file, 3, file_size, true).unwrap();
|
||||
}
|
||||
let temp_file = QcowTempDisk::new(file_size, None, false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
let disk = QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
false,
|
||||
@@ -843,11 +838,9 @@ mod unit_tests {
|
||||
#[test]
|
||||
fn test_qcow_async_batch_mixed_requests() {
|
||||
let file_size = 100 * 1024 * 1024;
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
QcowFile::new(raw_file, 3, file_size, true).unwrap();
|
||||
}
|
||||
let temp_file = QcowTempDisk::new(file_size, None, false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
let disk = QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
false,
|
||||
@@ -929,11 +922,9 @@ mod unit_tests {
|
||||
#[test]
|
||||
fn test_qcow_async_read_unallocated() {
|
||||
let file_size = 100 * 1024 * 1024;
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
QcowFile::new(raw_file, 3, file_size, true).unwrap();
|
||||
}
|
||||
let temp_file = QcowTempDisk::new(file_size, None, false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
let disk = QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
false,
|
||||
@@ -954,11 +945,9 @@ mod unit_tests {
|
||||
fn test_qcow_async_sub_cluster_write() {
|
||||
let cluster_size = 65536usize;
|
||||
let file_size = 100 * 1024 * 1024;
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
QcowFile::new(raw_file, 3, file_size, true).unwrap();
|
||||
}
|
||||
let temp_file = QcowTempDisk::new(file_size, None, false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
let disk = QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
false,
|
||||
@@ -1049,11 +1038,9 @@ mod unit_tests {
|
||||
#[test]
|
||||
fn test_qcow_async_alignment_without_direct_io() {
|
||||
let file_size = 100 * 1024 * 1024;
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
QcowFile::new(raw_file, 3, file_size, true).unwrap();
|
||||
}
|
||||
let temp_file = QcowTempDisk::new(file_size, None, false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
let disk = QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
false,
|
||||
@@ -1066,51 +1053,33 @@ mod unit_tests {
|
||||
assert_eq!(async_io.alignment(), SECTOR_SIZE);
|
||||
}
|
||||
|
||||
/// Returns None if O_DIRECT is not supported (e.g. tmpfs).
|
||||
fn try_create_direct_io_disk(temp_file: &TempFile, file_size: u64) -> Option<QcowDisk> {
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
QcowFile::new(raw_file, 3, file_size, true).unwrap();
|
||||
}
|
||||
QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.ok()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_qcow_async_alignment_with_direct_io() {
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
let disk = match try_create_direct_io_disk(&temp_file, 100 * 1024 * 1024) {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
let tmp_disk = match QcowTempDisk::new(100 * 1024 * 1024, None, true, true, true) {
|
||||
Ok(d) => d,
|
||||
Err(_) => {
|
||||
eprintln!("skipping: O_DIRECT not supported on this filesystem");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let async_io = disk.create_async_io(1).unwrap();
|
||||
let async_io = tmp_disk.disk().create_async_io(1).unwrap();
|
||||
assert!(async_io.alignment() >= SECTOR_SIZE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_qcow_async_sub_sector_read_with_direct_io() {
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
let disk = match try_create_direct_io_disk(&temp_file, 100 * 1024 * 1024) {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
let tmp_disk = match QcowTempDisk::new(100 * 1024 * 1024, None, true, true, true) {
|
||||
Ok(d) => d,
|
||||
Err(_) => {
|
||||
eprintln!("skipping: O_DIRECT not supported on this filesystem");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let pattern = vec![0xAB; 65536];
|
||||
async_write(&disk, 0, &pattern);
|
||||
async_write(tmp_disk.disk(), 0, &pattern);
|
||||
|
||||
let buf = async_read(&disk, 0, 512);
|
||||
let buf = async_read(tmp_disk.disk(), 0, 512);
|
||||
assert!(
|
||||
buf.iter().all(|&b| b == 0xAB),
|
||||
"sub-sector O_DIRECT read should return written data"
|
||||
@@ -1119,19 +1088,18 @@ mod unit_tests {
|
||||
|
||||
#[test]
|
||||
fn test_qcow_async_direct_io_write_read_roundtrip() {
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
let disk = match try_create_direct_io_disk(&temp_file, 100 * 1024 * 1024) {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
let tmp_disk = match QcowTempDisk::new(100 * 1024 * 1024, None, true, true, true) {
|
||||
Ok(d) => d,
|
||||
Err(_) => {
|
||||
eprintln!("skipping: O_DIRECT not supported on this filesystem");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let pattern: Vec<u8> = (0..128 * 1024).map(|i| (i % 251) as u8).collect();
|
||||
async_write(&disk, 0, &pattern);
|
||||
async_write(tmp_disk.disk(), 0, &pattern);
|
||||
|
||||
let buf = async_read(&disk, 0, pattern.len());
|
||||
let buf = async_read(tmp_disk.disk(), 0, pattern.len());
|
||||
assert_eq!(buf, pattern, "O_DIRECT roundtrip should match");
|
||||
}
|
||||
|
||||
|
||||
@@ -342,6 +342,7 @@ mod unit_tests {
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::os::fd::RawFd;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::{env, thread};
|
||||
|
||||
use vmm_sys_util::tempdir::TempDir;
|
||||
@@ -351,11 +352,12 @@ mod unit_tests {
|
||||
use crate::async_io::{AsyncIoCompletion, OwnedIoBuffer};
|
||||
use crate::disk_file::{AsyncDiskFile, DiskSize, Resizable};
|
||||
use crate::error::BlockErrorKind;
|
||||
use crate::formats::qcow::QcowDisk;
|
||||
use crate::formats::qcow;
|
||||
use crate::formats::qcow::common::unit_tests::compress_allocated_clusters;
|
||||
use crate::formats::qcow::internal::{
|
||||
BackingFileConfig, Error as QcowError, ImageType, QcowFile, QcowHeader, RawFile,
|
||||
BackingFileConfig, Error as QcowError, ImageType, QcowHeader, RawFile,
|
||||
};
|
||||
use crate::formats::qcow::{QcowDisk, QcowTempDisk};
|
||||
|
||||
const TEST_L1_L2_ADDR_MASK: u64 = 0x00ff_ffff_ffff_fe00;
|
||||
const TEST_HEADER_L1_TABLE_OFFSET: u64 = 40;
|
||||
@@ -416,14 +418,15 @@ mod unit_tests {
|
||||
sparse: bool,
|
||||
direct_io: bool,
|
||||
) -> (TempFile, QcowDisk) {
|
||||
let temp_file = TempFile::new().unwrap();
|
||||
{
|
||||
let raw_file = RawFile::new(temp_file.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow_file = QcowFile::new(raw_file, 3, file_size, sparse).unwrap();
|
||||
qcow_file.seek(SeekFrom::Start(offset)).unwrap();
|
||||
qcow_file.write_all(data).unwrap();
|
||||
qcow_file.flush().unwrap();
|
||||
}
|
||||
let temp_file = if data.is_empty() {
|
||||
QcowTempDisk::new(file_size, None, false, sparse, false)
|
||||
.unwrap()
|
||||
.into_tempfile()
|
||||
} else {
|
||||
let tmp_disk = QcowTempDisk::new(file_size, None, false, sparse, false).unwrap();
|
||||
tmp_disk.disk().write_all_at(offset, data);
|
||||
tmp_disk.into_tempfile()
|
||||
};
|
||||
let disk = QcowDisk::new(
|
||||
temp_file.as_file().try_clone().unwrap(),
|
||||
direct_io,
|
||||
@@ -446,15 +449,13 @@ mod unit_tests {
|
||||
backing_temp.as_file().sync_all().unwrap();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let disk = QcowDisk::new(
|
||||
overlay_temp.as_file().try_clone().unwrap(),
|
||||
@@ -644,17 +645,20 @@ mod unit_tests {
|
||||
let data = vec![0xFF; 64 * 1024];
|
||||
let (_temp, _) = create_disk_with_data(100 * 1024 * 1024, &[], 0, true, false);
|
||||
|
||||
// Write data at multiple offsets via QcowFile first, then punch
|
||||
// Populate four 64 KiB regions at 128 KiB strides so the subsequent
|
||||
// punch_hole calls have allocated clusters to operate on.
|
||||
{
|
||||
let temp_file = _temp.as_file().try_clone().unwrap();
|
||||
let raw_file = RawFile::new(temp_file, false);
|
||||
let mut qcow_file = QcowFile::from(raw_file).unwrap();
|
||||
let disk = QcowDisk::new(
|
||||
_temp.as_file().try_clone().unwrap(),
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
for i in 0..4u64 {
|
||||
let off = i * 128 * 1024;
|
||||
qcow_file.seek(SeekFrom::Start(off)).unwrap();
|
||||
qcow_file.write_all(&data).unwrap();
|
||||
disk.write_all_at(i * 128 * 1024, &data);
|
||||
}
|
||||
qcow_file.flush().unwrap();
|
||||
}
|
||||
|
||||
let disk = QcowDisk::new(
|
||||
@@ -819,16 +823,13 @@ mod unit_tests {
|
||||
backing_temp.as_file().sync_all().unwrap();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -883,22 +884,18 @@ mod unit_tests {
|
||||
}
|
||||
|
||||
fn create_qcow2_overlay(overlay_path: &Path, backing_path: &str, file_size: u64) {
|
||||
let raw = RawFile::new(
|
||||
OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(overlay_path)
|
||||
.unwrap(),
|
||||
false,
|
||||
);
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(overlay_path)
|
||||
.unwrap();
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path.to_string(),
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
qcow::create_image(&file, file_size, Some(&backing_config)).unwrap();
|
||||
}
|
||||
|
||||
fn create_qcow2_overlay_header(overlay_path: &Path, backing_path: &str, file_size: u64) {
|
||||
@@ -1115,29 +1112,21 @@ mod unit_tests {
|
||||
}
|
||||
|
||||
fn test_backing_file_read_qcow2_backing_impl(direct_io: bool) {
|
||||
let backing_temp = TempFile::new().unwrap();
|
||||
let cluster_size = 1u64 << 16;
|
||||
let file_size = cluster_size * 4;
|
||||
let pattern: Vec<u8> = (0..file_size as usize).map(|i| (i % 251) as u8).collect();
|
||||
{
|
||||
let raw = RawFile::new(backing_temp.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow = QcowFile::new(raw, 3, file_size, true).unwrap();
|
||||
qcow.seek(SeekFrom::Start(0)).unwrap();
|
||||
qcow.write_all(&pattern).unwrap();
|
||||
qcow.flush().unwrap();
|
||||
}
|
||||
let backing = QcowTempDisk::new(file_size, None, false, true, false).unwrap();
|
||||
backing.disk().write_all_at(0, &pattern);
|
||||
let backing_temp = backing.into_tempfile();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1238,29 +1227,21 @@ mod unit_tests {
|
||||
fn test_multi_queue_concurrent_reads_qcow2_backing_impl(direct_io: bool) {
|
||||
// Same as above but reads go through a Qcow2Backing,
|
||||
// exercising concurrent metadata resolution + pread64 in the backing.
|
||||
let backing_temp = TempFile::new().unwrap();
|
||||
let cluster_size = 1u64 << 16;
|
||||
let file_size = cluster_size * 16;
|
||||
let pattern: Vec<u8> = (0..file_size as usize).map(|i| (i % 251) as u8).collect();
|
||||
{
|
||||
let raw = RawFile::new(backing_temp.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow = QcowFile::new(raw, 3, file_size, true).unwrap();
|
||||
qcow.seek(SeekFrom::Start(0)).unwrap();
|
||||
qcow.write_all(&pattern).unwrap();
|
||||
qcow.flush().unwrap();
|
||||
}
|
||||
let backing = QcowTempDisk::new(file_size, None, false, true, false).unwrap();
|
||||
backing.disk().write_all_at(0, &pattern);
|
||||
let backing_temp = backing.into_tempfile();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = Arc::new(QcowDisk::new(file, direct_io, true, true, false).unwrap());
|
||||
@@ -1313,37 +1294,37 @@ mod unit_tests {
|
||||
let base_path = base_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
// Layer 1: qcow2 mid pointing at raw base, write to cluster 0 only
|
||||
let mid_temp = TempFile::new().unwrap();
|
||||
let mid_pattern = vec![0xBBu8; cluster_size as usize];
|
||||
{
|
||||
let raw = RawFile::new(mid_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
let mid = QcowTempDisk::new(
|
||||
file_size,
|
||||
Some(&BackingFileConfig {
|
||||
path: base_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let mut mid =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
mid.seek(SeekFrom::Start(0)).unwrap();
|
||||
mid.write_all(&mid_pattern).unwrap();
|
||||
mid.flush().unwrap();
|
||||
}
|
||||
}),
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
mid.disk().write_all_at(0, &mid_pattern);
|
||||
let mid_temp = mid.into_tempfile();
|
||||
let mid_path = mid_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
// Layer 2: qcow2 overlay pointing at qcow2 mid, write to cluster 1 only
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
let overlay_pattern = vec![0xCCu8; cluster_size as usize];
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
let overlay = QcowTempDisk::new(
|
||||
file_size,
|
||||
Some(&BackingFileConfig {
|
||||
path: mid_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let mut overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
overlay.seek(SeekFrom::Start(cluster_size)).unwrap();
|
||||
overlay.write_all(&overlay_pattern).unwrap();
|
||||
overlay.flush().unwrap();
|
||||
}
|
||||
}),
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
overlay.disk().write_all_at(cluster_size, &overlay_pattern);
|
||||
let overlay_temp = overlay.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1399,26 +1380,18 @@ mod unit_tests {
|
||||
let file_size = cluster_size * num_clusters;
|
||||
let pattern: Vec<u8> = (0..file_size as usize).map(|i| (i % 251) as u8).collect();
|
||||
|
||||
let backing_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(backing_temp.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow = QcowFile::new(raw, 3, file_size, true).unwrap();
|
||||
qcow.seek(SeekFrom::Start(0)).unwrap();
|
||||
qcow.write_all(&pattern).unwrap();
|
||||
qcow.flush().unwrap();
|
||||
}
|
||||
let backing = QcowTempDisk::new(file_size, None, false, true, false).unwrap();
|
||||
backing.disk().write_all_at(0, &pattern);
|
||||
let backing_temp = backing.into_tempfile();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1471,26 +1444,21 @@ mod unit_tests {
|
||||
let backing_size = cluster_size * 2;
|
||||
let overlay_size = cluster_size * 4; // overlay is larger than backing
|
||||
|
||||
let backing_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(backing_temp.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow = QcowFile::new(raw, 3, backing_size, true).unwrap();
|
||||
qcow.seek(SeekFrom::Start(0)).unwrap();
|
||||
qcow.write_all(&vec![0xAA; backing_size as usize]).unwrap();
|
||||
qcow.flush().unwrap();
|
||||
}
|
||||
let backing = QcowTempDisk::new(backing_size, None, false, true, false).unwrap();
|
||||
backing
|
||||
.disk()
|
||||
.write_all_at(0, &vec![0xAA; backing_size as usize]);
|
||||
let backing_temp = backing.into_tempfile();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, overlay_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let overlay_temp =
|
||||
QcowTempDisk::new(overlay_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1520,27 +1488,20 @@ mod unit_tests {
|
||||
let backing_size = cluster_size * 2;
|
||||
let overlay_size = cluster_size * 4;
|
||||
|
||||
let backing_temp = TempFile::new().unwrap();
|
||||
let backing_data = vec![0xBBu8; backing_size as usize];
|
||||
{
|
||||
let raw = RawFile::new(backing_temp.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow = QcowFile::new(raw, 3, backing_size, true).unwrap();
|
||||
qcow.seek(SeekFrom::Start(0)).unwrap();
|
||||
qcow.write_all(&backing_data).unwrap();
|
||||
qcow.flush().unwrap();
|
||||
}
|
||||
let backing = QcowTempDisk::new(backing_size, None, false, true, false).unwrap();
|
||||
backing.disk().write_all_at(0, &backing_data);
|
||||
let backing_temp = backing.into_tempfile();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, overlay_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let overlay_temp =
|
||||
QcowTempDisk::new(overlay_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1584,16 +1545,14 @@ mod unit_tests {
|
||||
backing_temp.as_file().sync_all().unwrap();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, overlay_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let overlay_temp =
|
||||
QcowTempDisk::new(overlay_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1635,26 +1594,18 @@ mod unit_tests {
|
||||
let file_size = cluster_size * 4;
|
||||
let pattern: Vec<u8> = (0..file_size as usize).map(|i| (i % 251) as u8).collect();
|
||||
|
||||
let backing_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(backing_temp.as_file().try_clone().unwrap(), false);
|
||||
let mut qcow = QcowFile::new(raw, 3, file_size, true).unwrap();
|
||||
qcow.seek(SeekFrom::Start(0)).unwrap();
|
||||
qcow.write_all(&pattern).unwrap();
|
||||
qcow.flush().unwrap();
|
||||
}
|
||||
let backing = QcowTempDisk::new(file_size, None, false, true, false).unwrap();
|
||||
backing.disk().write_all_at(0, &pattern);
|
||||
let backing_temp = backing.into_tempfile();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Qcow2),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1702,16 +1653,13 @@ mod unit_tests {
|
||||
backing_temp.as_file().sync_all().unwrap();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1812,16 +1760,13 @@ mod unit_tests {
|
||||
backing_temp.as_file().sync_all().unwrap();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let disk = QcowDisk::new(file, direct_io, true, true, false).unwrap();
|
||||
@@ -1972,16 +1917,13 @@ mod unit_tests {
|
||||
backing_temp.as_file().sync_all().unwrap();
|
||||
let backing_path = backing_temp.as_path().to_str().unwrap().to_string();
|
||||
|
||||
let overlay_temp = TempFile::new().unwrap();
|
||||
{
|
||||
let raw = RawFile::new(overlay_temp.as_file().try_clone().unwrap(), false);
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let _overlay =
|
||||
QcowFile::new_from_backing(raw, 3, file_size, &backing_config, true).unwrap();
|
||||
}
|
||||
let backing_config = BackingFileConfig {
|
||||
path: backing_path,
|
||||
format: Some(ImageType::Raw),
|
||||
};
|
||||
let overlay_temp = QcowTempDisk::new(file_size, Some(&backing_config), false, true, false)
|
||||
.unwrap()
|
||||
.into_tempfile();
|
||||
|
||||
let file = overlay_temp.as_file().try_clone().unwrap();
|
||||
let mut disk = QcowDisk::new(file, false, true, true, false).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user