block: qcow: Fix refcount leak when refcount blocks are replaced

When a refcount block is evicted from cache and replaced with a new
one, the old refcount block cluster was added to unref_clusters but
its refcount was never decremented to 0 on disk. This left the cluster
with refcount=1 while no metadata referenced it, causing errors in
qemu-img check

`Leaked cluster X refcount=1 reference=0`

This fix recursively calls set_cluster_refcount(freed_cluster, 0) to
properly decrement the freed refcount block's refcount on disk. The
recursion handles cascading replacements where freeing one refcount
block may trigger the replacement of another.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski 2025-11-27 09:43:17 +01:00 committed by Rob Bradford
parent f7edfefe42
commit 9e2e85a48f

View file

@ -1518,7 +1518,9 @@ impl QcowFile {
refcount_set = true;
}
Ok(Some(freed_cluster)) => {
unref_clusters.push(freed_cluster);
// Recursively set the freed refcount block's refcount to 0
let mut freed = self.set_cluster_refcount(freed_cluster, 0)?;
unref_clusters.append(&mut freed);
refcount_set = true;
}
Err(refcount::Error::EvictingRefCounts(e)) => {