mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
block: qcow: Test freed clusters stay on the free list
After churning a single L2 region with an fsync per write, scan the file for refcount==0 clusters and assert every one is on the runtime free list. The reuse bug left relocated refcount block clusters free on disk but off the list, so this fails without the fix, reporting the exact count of stranded clusters. Assisted-by: Claude:Opus-4.8 Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
365d6b8017
commit
8acefad893
@@ -516,6 +516,37 @@ mod unit_tests {
|
||||
}
|
||||
}
|
||||
|
||||
// Every refcount==0 cluster in the file must be on the runtime free list.
|
||||
// The bug left relocated refcount-block clusters free on disk yet absent
|
||||
// from the list, so the allocator never reused them.
|
||||
#[test]
|
||||
fn freed_clusters_are_tracked_in_free_list() {
|
||||
const CL: u64 = 65536;
|
||||
let virtual_size = 512 * 1024 * 1024;
|
||||
let (temp, disk) = create_disk_with_data(virtual_size, &[], 0, false, false);
|
||||
let n: u64 = 400;
|
||||
|
||||
for i in 0..n {
|
||||
let pattern = vec![(i as u8).wrapping_add(1); CL as usize];
|
||||
async_write(&disk, i * CL, &pattern);
|
||||
async_fsync(&disk);
|
||||
}
|
||||
|
||||
let file_clusters = temp.as_file().metadata().unwrap().len() / CL;
|
||||
let mut free_on_disk = 0u64;
|
||||
for c in 0..file_clusters {
|
||||
if disk.metadata().cluster_refcount(c * CL).unwrap() == 0 {
|
||||
free_on_disk += 1;
|
||||
}
|
||||
}
|
||||
let tracked = disk.metadata().free_list_len() as u64;
|
||||
assert_eq!(
|
||||
free_on_disk, tracked,
|
||||
"{free_on_disk} free clusters on disk but {tracked} tracked; \
|
||||
relocated clusters are stranded off the free list",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_qcow_sync_rejects_out_of_bounds_allocated_l2_entry_on_read() {
|
||||
let data = vec![0x5a; 4096];
|
||||
|
||||
@@ -357,6 +357,12 @@ impl QcowMetadata {
|
||||
self.inner.read().unwrap().header.clone()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn free_list_len(&self) -> usize {
|
||||
let inner = self.inner.read().unwrap();
|
||||
inner.avail_clusters.len() + inner.unref_clusters.len()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn cluster_refcount(&self, address: u64) -> io::Result<u64> {
|
||||
let mut inner = self.inner.write().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user