]> xenbits.xensource.com Git - qemu-xen.git/commitdiff
qcow2: Free allocated clusters on write error
authorKevin Wolf <kwolf@redhat.com>
Thu, 28 Jun 2018 15:05:45 +0000 (17:05 +0200)
committerKevin Wolf <kwolf@redhat.com>
Fri, 29 Jun 2018 12:20:56 +0000 (14:20 +0200)
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 <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Tested-by: Eric Blake <eblake@redhat.com>
block/qcow2-cluster.c
block/qcow2.c
block/qcow2.h

index 0d74584c9b4bbc31daa2ed5f8acbc00e6ae5fb25..d37fe08b3d514424d51f3c8febb449808a2d3e18 100644 (file)
@@ -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,
index 78aeb1f9ea8bef2eb11350a08b2482b8d151c905..286640c0e34834d89efc9efa7d484e0c8669e495 100644 (file)
@@ -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 */
index 01b5250415f0242b58c742ac842735f56cb9173c..1c9c0d3631faf2f402746b60a5ab05e433d30fd1 100644 (file)
@@ -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);