84 lines
3.1 KiB
Diff
84 lines
3.1 KiB
Diff
From 175dbc6a2217f7a8cf319d8da487fa80ff68eba4 Mon Sep 17 00:00:00 2001
|
|
From: Kevin Wolf <kwolf@redhat.com>
|
|
Date: Mon, 2 Jul 2018 15:40:07 +0200
|
|
Subject: [PATCH 183/268] qcow2: Free allocated clusters on write error
|
|
|
|
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
Message-id: <20180702154008.15533-3-kwolf@redhat.com>
|
|
Patchwork-id: 81185
|
|
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 2/3] qcow2: Free allocated clusters on write error
|
|
Bugzilla: 1528541
|
|
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
|
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>
|
|
(cherry picked from commit 8b24cd141549b5b264baeddd4e72902cfb5de23b)
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
---
|
|
block/qcow2-cluster.c | 11 +++++++++++
|
|
block/qcow2.c | 2 ++
|
|
block/qcow2.h | 1 +
|
|
3 files changed, 14 insertions(+)
|
|
|
|
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
|
|
index 1aee726..c90e2ec 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 4404dc7..da74e2a 100644
|
|
--- a/block/qcow2.c
|
|
+++ b/block/qcow2.c
|
|
@@ -1771,6 +1771,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 adf5c39..b5e2aa3 100644
|
|
--- a/block/qcow2.h
|
|
+++ b/block/qcow2.h
|
|
@@ -618,6 +618,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);
|
|
--
|
|
1.8.3.1
|
|
|