Blob Blame History Raw
From 97a6adcb3ac735ff135469aa602c798fbc0b1491 Mon Sep 17 00:00:00 2001
Message-Id: <97a6adcb3ac735ff135469aa602c798fbc0b1491@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 23 Jun 2020 12:23:36 +0200
Subject: [PATCH] qemu: backup: Fix backup of disk skipped in an intermediate
 checkpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If a disk is not captured by one of the intermediate checkpoints the
code would fail, but we can easily calculate the bitmaps to merge
correctly by skipping over checkpoints which don't describe the disk.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit c89a44777fdf89b400878adcb03a3557bcec3f4e)

https://bugzilla.redhat.com/show_bug.cgi?id=1804593
Message-Id: <d0efe760e9f8049758691b7f66a7de41fce5c264.1592906423.git.pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
---
 src/qemu/qemu_backup.c | 24 ++++++++++++++++++++++++
 tests/qemublocktest.c  |  6 ++++++
 2 files changed, 30 insertions(+)

diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c
index 400b711f79..adbf696de6 100644
--- a/src/qemu/qemu_backup.c
+++ b/src/qemu/qemu_backup.c
@@ -240,6 +240,30 @@ qemuBackupDiskPrepareOneBitmapsChain(virDomainMomentDefPtr *incremental,
     for (incridx = 0; incremental[incridx]; incridx++) {
         g_autoptr(virJSONValue) tmp = virJSONValueNewArray();
         virStorageSourcePtr tmpsrc = NULL;
+        virDomainCheckpointDefPtr chkdef = (virDomainCheckpointDefPtr) incremental[incridx];
+        bool checkpoint_has_disk = false;
+        size_t i;
+
+        for (i = 0; i < chkdef->ndisks; i++) {
+            if (STRNEQ_NULLABLE(diskdst, chkdef->disks[i].name))
+                continue;
+
+            if (chkdef->disks[i].type == VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
+                checkpoint_has_disk = true;
+
+            break;
+        }
+
+        if (!checkpoint_has_disk) {
+            if (!incremental[incridx + 1]) {
+                virReportError(VIR_ERR_INVALID_ARG,
+                               _("disk '%s' not found in checkpoint '%s'"),
+                               diskdst, incremental[incridx]->name);
+                return NULL;
+            }
+
+            continue;
+        }
 
         if (qemuBackupGetBitmapMergeRange(n, incremental[incridx]->name,
                                           &tmp, &tmpsrc, diskdst,
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index e461b3a23d..d15965d9eb 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -727,6 +727,12 @@ testQemuBackupGetIncrementalMoment(const char *name)
     if (!(checkpoint = virDomainCheckpointDefNew()))
         abort();
 
+    checkpoint->disks = g_new0(virDomainCheckpointDiskDef, 1);
+    checkpoint->ndisks = 1;
+
+    checkpoint->disks[0].name = g_strdup("testdisk");
+    checkpoint->disks[0].type = VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP;
+
     checkpoint->parent.name = g_strdup(name);
 
     return (virDomainMomentDefPtr) checkpoint;
-- 
2.27.0