From 48155c4151816ff57aee0bc615aea876b00b3c0b Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 30 Mar 2026 23:36:27 +0200 Subject: [PATCH] block: qcow: Test async sub cluster write Add a QcowAsync unit test that writes 4K into the middle of a cluster, then reads the entire cluster back. Verifies that the written region matches and surrounding bytes remain zero. This exercises the COW path where unwritten parts of a newly allocated cluster must be zero filled. Signed-off-by: Anatol Belski --- block/src/qcow_async.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/block/src/qcow_async.rs b/block/src/qcow_async.rs index bdc4fe341..9063fd7d5 100644 --- a/block/src/qcow_async.rs +++ b/block/src/qcow_async.rs @@ -857,4 +857,42 @@ mod unit_tests { "unallocated region should read as zeroes" ); } + + #[test] + 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 disk = QcowDiskAsync::new(temp_file.as_file().try_clone().unwrap(), false, false, true) + .unwrap(); + + // Write 4K into the middle of a cluster. + let write_offset = 4096u64; + let write_len = 4096; + let pattern = vec![0xCC; write_len]; + async_write(&disk, write_offset, &pattern); + + // Read the entire cluster back. + let buf = async_read(&disk, 0, cluster_size); + + assert!( + buf[..write_offset as usize].iter().all(|&b| b == 0), + "bytes before the write should be zero" + ); + assert_eq!( + &buf[write_offset as usize..write_offset as usize + write_len], + &pattern[..], + "written region should match" + ); + assert!( + buf[write_offset as usize + write_len..] + .iter() + .all(|&b| b == 0), + "bytes after the write should be zero" + ); + } }