diff options
-rw-r--r-- | block/qcow2-cluster.c | 11 | ||||
-rw-r--r-- | block/qcow2.c | 2 | ||||
-rw-r--r-- | block/qcow2.h | 1 |
3 files changed, 14 insertions, 0 deletions
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 0d74584c9b..d37fe08b3d 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -994,6 +994,17 @@ err: return ret; } +/** + * Frees the allocated clusters because the request failed and they won't + * actually be linked. + */ +void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m) +{ + BDRVQcow2State *s = bs->opaque; + qcow2_free_clusters(bs, m->alloc_offset, m->nb_clusters << s->cluster_bits, + QCOW2_DISCARD_NEVER); +} + /* * Returns the number of contiguous clusters that can be used for an allocating * write, but require COW to be performed (this includes yet unallocated space, diff --git a/block/qcow2.c b/block/qcow2.c index 78aeb1f9ea..286640c0e3 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1775,6 +1775,8 @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs, if (ret) { goto out; } + } else { + qcow2_alloc_cluster_abort(bs, l2meta); } /* Take the request off the list of running requests */ diff --git a/block/qcow2.h b/block/qcow2.h index 01b5250415..1c9c0d3631 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -614,6 +614,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, int compressed_size); int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m); +void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m); int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes, enum qcow2_discard_type type, bool full_discard); |