From: Peter Krempa Date: Thu, 21 May 2020 11:23:40 +0000 (+0200) Subject: qemu: backup: Fix backup of disk skipped in an intermediate checkpoint X-Git-Tag: v6.5.0-rc1~117 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c89a44777fdf89b400878adcb03a3557bcec3f4e;p=thirdparty%2Flibvirt.git qemu: backup: Fix backup of disk skipped in an intermediate checkpoint 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 Reviewed-by: Eric Blake --- diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index 8d75b59db2..d56794af1f 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 0cdedb9ad4..f00d2ff129 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;