ae23c9
From 175dbc6a2217f7a8cf319d8da487fa80ff68eba4 Mon Sep 17 00:00:00 2001
ae23c9
From: Kevin Wolf <kwolf@redhat.com>
ae23c9
Date: Mon, 2 Jul 2018 15:40:07 +0200
ae23c9
Subject: [PATCH 183/268] qcow2: Free allocated clusters on write error
ae23c9
ae23c9
RH-Author: Kevin Wolf <kwolf@redhat.com>
ae23c9
Message-id: <20180702154008.15533-3-kwolf@redhat.com>
ae23c9
Patchwork-id: 81185
ae23c9
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 2/3] qcow2: Free allocated clusters on write error
ae23c9
Bugzilla: 1528541
ae23c9
RH-Acked-by: Max Reitz <mreitz@redhat.com>
ae23c9
RH-Acked-by: Fam Zheng <famz@redhat.com>
ae23c9
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
ae23c9
If we managed to allocate the clusters, but then failed to write the
ae23c9
data, there's a good chance that we'll still be able to free the
ae23c9
clusters again in order to avoid cluster leaks (the refcounts are
ae23c9
cached, so even if we can't write them out right now, we may be able to
ae23c9
do so when the VM is resumed after a werror=stop/enospc pause).
ae23c9
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Reviewed-by: Max Reitz <mreitz@redhat.com>
ae23c9
Reviewed-by: Eric Blake <eblake@redhat.com>
ae23c9
Tested-by: Eric Blake <eblake@redhat.com>
ae23c9
(cherry picked from commit 8b24cd141549b5b264baeddd4e72902cfb5de23b)
ae23c9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
ae23c9
---
ae23c9
 block/qcow2-cluster.c | 11 +++++++++++
ae23c9
 block/qcow2.c         |  2 ++
ae23c9
 block/qcow2.h         |  1 +
ae23c9
 3 files changed, 14 insertions(+)
ae23c9
ae23c9
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
ae23c9
index 1aee726..c90e2ec 100644
ae23c9
--- a/block/qcow2-cluster.c
ae23c9
+++ b/block/qcow2-cluster.c
ae23c9
@@ -994,6 +994,17 @@ err:
ae23c9
     return ret;
ae23c9
  }
ae23c9
 
ae23c9
+/**
ae23c9
+ * Frees the allocated clusters because the request failed and they won't
ae23c9
+ * actually be linked.
ae23c9
+ */
ae23c9
+void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
ae23c9
+{
ae23c9
+    BDRVQcow2State *s = bs->opaque;
ae23c9
+    qcow2_free_clusters(bs, m->alloc_offset, m->nb_clusters << s->cluster_bits,
ae23c9
+                        QCOW2_DISCARD_NEVER);
ae23c9
+}
ae23c9
+
ae23c9
 /*
ae23c9
  * Returns the number of contiguous clusters that can be used for an allocating
ae23c9
  * write, but require COW to be performed (this includes yet unallocated space,
ae23c9
diff --git a/block/qcow2.c b/block/qcow2.c
ae23c9
index 4404dc7..da74e2a 100644
ae23c9
--- a/block/qcow2.c
ae23c9
+++ b/block/qcow2.c
ae23c9
@@ -1771,6 +1771,8 @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
ae23c9
             if (ret) {
ae23c9
                 goto out;
ae23c9
             }
ae23c9
+        } else {
ae23c9
+            qcow2_alloc_cluster_abort(bs, l2meta);
ae23c9
         }
ae23c9
 
ae23c9
         /* Take the request off the list of running requests */
ae23c9
diff --git a/block/qcow2.h b/block/qcow2.h
ae23c9
index adf5c39..b5e2aa3 100644
ae23c9
--- a/block/qcow2.h
ae23c9
+++ b/block/qcow2.h
ae23c9
@@ -618,6 +618,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
ae23c9
                                          int compressed_size);
ae23c9
 
ae23c9
 int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
ae23c9
+void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
ae23c9
 int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
ae23c9
                           uint64_t bytes, enum qcow2_discard_type type,
ae23c9
                           bool full_discard);
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9