Blame SOURCES/kvm-qcow2-Repair-OFLAG_COPIED-when-fixing-leaks.patch

1bdc94
From dfcb9147d46e9e0da762349fd62a4ac620100cb4 Mon Sep 17 00:00:00 2001
1bdc94
From: Max Reitz <mreitz@redhat.com>
1bdc94
Date: Mon, 18 Jun 2018 17:16:54 +0200
1bdc94
Subject: [PATCH 45/54] qcow2: Repair OFLAG_COPIED when fixing leaks
1bdc94
1bdc94
RH-Author: Max Reitz <mreitz@redhat.com>
1bdc94
Message-id: <20180618171655.25987-2-mreitz@redhat.com>
1bdc94
Patchwork-id: 80782
1bdc94
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 1/2] qcow2: Repair OFLAG_COPIED when fixing leaks
1bdc94
Bugzilla: 1527085
1bdc94
RH-Acked-by: John Snow <jsnow@redhat.com>
1bdc94
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
1bdc94
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
1bdc94
1bdc94
Repairing OFLAG_COPIED is usually safe because it is done after the
1bdc94
refcounts have been repaired.  Therefore, it we did not find anyone else
1bdc94
referencing a data or L2 cluster, it makes no sense to not set
1bdc94
OFLAG_COPIED -- and the other direction (clearing OFLAG_COPIED) is
1bdc94
always safe, anyway, it may just induce leaks.
1bdc94
1bdc94
Furthermore, if OFLAG_COPIED is actually consistent with a wrong (leaky)
1bdc94
refcount, we will decrement the refcount with -r leaks, but OFLAG_COPIED
1bdc94
will then be wrong.  qemu-img check should not produce images that are
1bdc94
more corrupted afterwards then they were before.
1bdc94
1bdc94
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1527085
1bdc94
Signed-off-by: Max Reitz <mreitz@redhat.com>
1bdc94
Reviewed-by: Eric Blake <eblake@redhat.com>
1bdc94
Message-id: 20180509200059.31125-2-mreitz@redhat.com
1bdc94
Signed-off-by: Max Reitz <mreitz@redhat.com>
1bdc94
(cherry picked from commit 3cce51c919c7b4028cf6676dfcb80a45741b5117)
1bdc94
Signed-off-by: Max Reitz <mreitz@redhat.com>
1bdc94
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
1bdc94
---
1bdc94
 block/qcow2-refcount.c | 25 +++++++++++++++++--------
1bdc94
 1 file changed, 17 insertions(+), 8 deletions(-)
1bdc94
1bdc94
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
1bdc94
index 6b8b635..4e14c0a 100644
1bdc94
--- a/block/qcow2-refcount.c
1bdc94
+++ b/block/qcow2-refcount.c
1bdc94
@@ -1799,6 +1799,19 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
1bdc94
     int ret;
1bdc94
     uint64_t refcount;
1bdc94
     int i, j;
1bdc94
+    bool repair;
1bdc94
+
1bdc94
+    if (fix & BDRV_FIX_ERRORS) {
1bdc94
+        /* Always repair */
1bdc94
+        repair = true;
1bdc94
+    } else if (fix & BDRV_FIX_LEAKS) {
1bdc94
+        /* Repair only if that seems safe: This function is always
1bdc94
+         * called after the refcounts have been fixed, so the refcount
1bdc94
+         * is accurate if that repair was successful */
1bdc94
+        repair = !res->check_errors && !res->corruptions && !res->leaks;
1bdc94
+    } else {
1bdc94
+        repair = false;
1bdc94
+    }
1bdc94
 
1bdc94
     for (i = 0; i < s->l1_size; i++) {
1bdc94
         uint64_t l1_entry = s->l1_table[i];
1bdc94
@@ -1818,10 +1831,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
1bdc94
         if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) {
1bdc94
             fprintf(stderr, "%s OFLAG_COPIED L2 cluster: l1_index=%d "
1bdc94
                     "l1_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
1bdc94
-                    fix & BDRV_FIX_ERRORS ? "Repairing" :
1bdc94
-                                            "ERROR",
1bdc94
-                    i, l1_entry, refcount);
1bdc94
-            if (fix & BDRV_FIX_ERRORS) {
1bdc94
+                    repair ? "Repairing" : "ERROR", i, l1_entry, refcount);
1bdc94
+            if (repair) {
1bdc94
                 s->l1_table[i] = refcount == 1
1bdc94
                                ? l1_entry |  QCOW_OFLAG_COPIED
1bdc94
                                : l1_entry & ~QCOW_OFLAG_COPIED;
1bdc94
@@ -1862,10 +1873,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
1bdc94
                 if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) {
1bdc94
                     fprintf(stderr, "%s OFLAG_COPIED data cluster: "
1bdc94
                             "l2_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
1bdc94
-                            fix & BDRV_FIX_ERRORS ? "Repairing" :
1bdc94
-                                                    "ERROR",
1bdc94
-                            l2_entry, refcount);
1bdc94
-                    if (fix & BDRV_FIX_ERRORS) {
1bdc94
+                            repair ? "Repairing" : "ERROR", l2_entry, refcount);
1bdc94
+                    if (repair) {
1bdc94
                         l2_table[j] = cpu_to_be64(refcount == 1
1bdc94
                                     ? l2_entry |  QCOW_OFLAG_COPIED
1bdc94
                                     : l2_entry & ~QCOW_OFLAG_COPIED);
1bdc94
-- 
1bdc94
1.8.3.1
1bdc94