Skip to content

Commit 8b24cd1

Browse files
committed
qcow2: Free allocated clusters on write error
If we managed to allocate the clusters, but then failed to write the data, there's a good chance that we'll still be able to free the clusters again in order to avoid cluster leaks (the refcounts are cached, so even if we can't write them out right now, we may be able to do so when the VM is resumed after a werror=stop/enospc pause). Signed-off-by: Kevin Wolf <[email protected]> Reviewed-by: Max Reitz <[email protected]> Reviewed-by: Eric Blake <[email protected]> Tested-by: Eric Blake <[email protected]>
1 parent 93a3642 commit 8b24cd1

File tree

3 files changed

+14
-0
lines changed

3 files changed

+14
-0
lines changed

Diff for: block/qcow2-cluster.c

+11
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,17 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
994994
return ret;
995995
}
996996

997+
/**
998+
* Frees the allocated clusters because the request failed and they won't
999+
* actually be linked.
1000+
*/
1001+
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
1002+
{
1003+
BDRVQcow2State *s = bs->opaque;
1004+
qcow2_free_clusters(bs, m->alloc_offset, m->nb_clusters << s->cluster_bits,
1005+
QCOW2_DISCARD_NEVER);
1006+
}
1007+
9971008
/*
9981009
* Returns the number of contiguous clusters that can be used for an allocating
9991010
* write, but require COW to be performed (this includes yet unallocated space,

Diff for: block/qcow2.c

+2
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,8 @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
17751775
if (ret) {
17761776
goto out;
17771777
}
1778+
} else {
1779+
qcow2_alloc_cluster_abort(bs, l2meta);
17781780
}
17791781

17801782
/* Take the request off the list of running requests */

Diff for: block/qcow2.h

+1
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
614614
int compressed_size);
615615

616616
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
617+
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
617618
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
618619
uint64_t bytes, enum qcow2_discard_type type,
619620
bool full_discard);

0 commit comments

Comments
 (0)