|
|
169b9a |
From ec8057f43c44075e02b59078b38b40340220f955 Mon Sep 17 00:00:00 2001
|
|
|
169b9a |
From: Max Reitz <mreitz@redhat.com>
|
|
|
169b9a |
Date: Mon, 18 Jun 2018 17:24:53 +0200
|
|
|
169b9a |
Subject: [PATCH 05/17] qcow2: Repair OFLAG_COPIED when fixing leaks
|
|
|
169b9a |
|
|
|
169b9a |
RH-Author: Max Reitz <mreitz@redhat.com>
|
|
|
169b9a |
Message-id: <20180618172454.27434-2-mreitz@redhat.com>
|
|
|
169b9a |
Patchwork-id: 80785
|
|
|
169b9a |
O-Subject: [RHEL-7.6 qemu-kvm PATCH 1/2] qcow2: Repair OFLAG_COPIED when fixing leaks
|
|
|
169b9a |
Bugzilla: 1527122
|
|
|
169b9a |
RH-Acked-by: John Snow <jsnow@redhat.com>
|
|
|
169b9a |
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
169b9a |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
169b9a |
|
|
|
169b9a |
Repairing OFLAG_COPIED is usually safe because it is done after the
|
|
|
169b9a |
refcounts have been repaired. Therefore, it we did not find anyone else
|
|
|
169b9a |
referencing a data or L2 cluster, it makes no sense to not set
|
|
|
169b9a |
OFLAG_COPIED -- and the other direction (clearing OFLAG_COPIED) is
|
|
|
169b9a |
always safe, anyway, it may just induce leaks.
|
|
|
169b9a |
|
|
|
169b9a |
Furthermore, if OFLAG_COPIED is actually consistent with a wrong (leaky)
|
|
|
169b9a |
refcount, we will decrement the refcount with -r leaks, but OFLAG_COPIED
|
|
|
169b9a |
will then be wrong. qemu-img check should not produce images that are
|
|
|
169b9a |
more corrupted afterwards then they were before.
|
|
|
169b9a |
|
|
|
169b9a |
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1527085
|
|
|
169b9a |
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
|
169b9a |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
169b9a |
Message-id: 20180509200059.31125-2-mreitz@redhat.com
|
|
|
169b9a |
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
|
169b9a |
(cherry picked from commit 3cce51c919c7b4028cf6676dfcb80a45741b5117)
|
|
|
169b9a |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
169b9a |
|
|
|
169b9a |
Conflicts:
|
|
|
169b9a |
block/qcow2-refcount.c
|
|
|
169b9a |
|
|
|
169b9a |
Conflicts due to refcounts being fixed to 16 bit downstream, which means
|
|
|
169b9a |
that every instance of the "refcount" variable is an int instead of
|
|
|
169b9a |
uint64_t. This results in contextual conflicts in the corruption
|
|
|
169b9a |
printf()s.
|
|
|
169b9a |
|
|
|
169b9a |
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
|
169b9a |
---
|
|
|
169b9a |
block/qcow2-refcount.c | 25 +++++++++++++++++--------
|
|
|
169b9a |
1 file changed, 17 insertions(+), 8 deletions(-)
|
|
|
169b9a |
|
|
|
169b9a |
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
|
|
|
169b9a |
index 848fd31..7a69bcd 100644
|
|
|
169b9a |
--- a/block/qcow2-refcount.c
|
|
|
169b9a |
+++ b/block/qcow2-refcount.c
|
|
|
169b9a |
@@ -1333,6 +1333,19 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
|
|
|
169b9a |
int ret;
|
|
|
169b9a |
int refcount;
|
|
|
169b9a |
int i, j;
|
|
|
169b9a |
+ bool repair;
|
|
|
169b9a |
+
|
|
|
169b9a |
+ if (fix & BDRV_FIX_ERRORS) {
|
|
|
169b9a |
+ /* Always repair */
|
|
|
169b9a |
+ repair = true;
|
|
|
169b9a |
+ } else if (fix & BDRV_FIX_LEAKS) {
|
|
|
169b9a |
+ /* Repair only if that seems safe: This function is always
|
|
|
169b9a |
+ * called after the refcounts have been fixed, so the refcount
|
|
|
169b9a |
+ * is accurate if that repair was successful */
|
|
|
169b9a |
+ repair = !res->check_errors && !res->corruptions && !res->leaks;
|
|
|
169b9a |
+ } else {
|
|
|
169b9a |
+ repair = false;
|
|
|
169b9a |
+ }
|
|
|
169b9a |
|
|
|
169b9a |
for (i = 0; i < s->l1_size; i++) {
|
|
|
169b9a |
uint64_t l1_entry = s->l1_table[i];
|
|
|
169b9a |
@@ -1351,10 +1364,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
|
|
|
169b9a |
if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) {
|
|
|
169b9a |
fprintf(stderr, "%s OFLAG_COPIED L2 cluster: l1_index=%d "
|
|
|
169b9a |
"l1_entry=%" PRIx64 " refcount=%d\n",
|
|
|
169b9a |
- fix & BDRV_FIX_ERRORS ? "Repairing" :
|
|
|
169b9a |
- "ERROR",
|
|
|
169b9a |
- i, l1_entry, refcount);
|
|
|
169b9a |
- if (fix & BDRV_FIX_ERRORS) {
|
|
|
169b9a |
+ repair ? "Repairing" : "ERROR", i, l1_entry, refcount);
|
|
|
169b9a |
+ if (repair) {
|
|
|
169b9a |
s->l1_table[i] = refcount == 1
|
|
|
169b9a |
? l1_entry | QCOW_OFLAG_COPIED
|
|
|
169b9a |
: l1_entry & ~QCOW_OFLAG_COPIED;
|
|
|
169b9a |
@@ -1393,10 +1404,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
|
|
|
169b9a |
if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) {
|
|
|
169b9a |
fprintf(stderr, "%s OFLAG_COPIED data cluster: "
|
|
|
169b9a |
"l2_entry=%" PRIx64 " refcount=%d\n",
|
|
|
169b9a |
- fix & BDRV_FIX_ERRORS ? "Repairing" :
|
|
|
169b9a |
- "ERROR",
|
|
|
169b9a |
- l2_entry, refcount);
|
|
|
169b9a |
- if (fix & BDRV_FIX_ERRORS) {
|
|
|
169b9a |
+ repair ? "Repairing" : "ERROR", l2_entry, refcount);
|
|
|
169b9a |
+ if (repair) {
|
|
|
169b9a |
l2_table[j] = cpu_to_be64(refcount == 1
|
|
|
169b9a |
? l2_entry | QCOW_OFLAG_COPIED
|
|
|
169b9a |
: l2_entry & ~QCOW_OFLAG_COPIED);
|
|
|
169b9a |
--
|
|
|
169b9a |
1.8.3.1
|
|
|
169b9a |
|