diff --git a/block/src/factory.rs b/block/src/factory.rs index 9877712ea..f1db7973a 100644 --- a/block/src/factory.rs +++ b/block/src/factory.rs @@ -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(); diff --git a/block/src/formats/qcow/mod.rs b/block/src/formats/qcow/mod.rs index fa050ad0d..f9a6942da 100644 --- a/block/src/formats/qcow/mod.rs +++ b/block/src/formats/qcow/mod.rs @@ -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] diff --git a/block/src/formats/qcow/worker/async_uring.rs b/block/src/formats/qcow/worker/async_uring.rs index a30198228..17aa77bfd 100644 --- a/block/src/formats/qcow/worker/async_uring.rs +++ b/block/src/formats/qcow/worker/async_uring.rs @@ -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 { - { - 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 = (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"); } diff --git a/block/src/formats/qcow/worker/sync.rs b/block/src/formats/qcow/worker/sync.rs index 304b8b256..7e90d8361 100644 --- a/block/src/formats/qcow/worker/sync.rs +++ b/block/src/formats/qcow/worker/sync.rs @@ -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 = (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 = (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 = (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 = (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();