]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: backup: roll-back checkpoint metadata if the checkpoint wasn't taken
authorPeter Krempa <pkrempa@redhat.com>
Mon, 6 Jan 2020 14:32:54 +0000 (15:32 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 7 Jan 2020 14:20:14 +0000 (15:20 +0100)
We insert the checkpoint metadata into the list of checkpoints prior to
actually creating the on-disk bits. If the 'transaction' or any other
steps done between inserting the checkpoint and creating the on-disk
data fail we'd end up with an unusable checkpoint that would vanish
after libvirtd restart.

Prevent this by rolling back the metadata if we didn't actually take and
record the checkpoint.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
src/qemu/qemu_backup.c

index c0445e0869434bb14aa924e7fbdc07329b494695..e7358082d595b6846cb1a7d1b02b5b509644edad 100644 (file)
@@ -812,6 +812,8 @@ qemuBackupBegin(virDomainObjPtr vm,
     if (!(actions = virJSONValueNewArray()))
         goto endjob;
 
+    /* The 'chk' checkpoint must be rolled back if the transaction command
+     * which creates it on disk is not executed or fails */
     if (chkdef) {
         if (qemuCheckpointCreateCommon(priv->driver, vm, &chkdef,
                                        &actions, &chk) < 0)
@@ -857,9 +859,11 @@ qemuBackupBegin(virDomainObjPtr vm,
     job_started = true;
     qemuBackupDiskStarted(vm, dd, ndd);
 
-    if (chk &&
-        qemuCheckpointCreateFinalize(priv->driver, vm, cfg, chk, true) < 0)
-        goto endjob;
+    if (chk) {
+        virDomainMomentObjPtr tmpchk = g_steal_pointer(&chk);
+        if (qemuCheckpointCreateFinalize(priv->driver, vm, cfg, tmpchk, true) < 0)
+            goto endjob;
+    }
 
     if (pull) {
         if (qemuDomainObjEnterMonitorAsync(priv->driver, vm, QEMU_ASYNC_JOB_BACKUP) < 0)
@@ -880,6 +884,10 @@ qemuBackupBegin(virDomainObjPtr vm,
 
  endjob:
     qemuBackupDiskDataCleanup(vm, dd, ndd);
+
+    /* if 'chk' is non-NULL here it's a failure and it must be rolled back */
+    qemuCheckpointRollbackMetadata(vm, chk);
+
     if (!job_started && nbd_running &&
         qemuDomainObjEnterMonitorAsync(priv->driver, vm, QEMU_ASYNC_JOB_BACKUP) < 0) {
         ignore_value(qemuMonitorNBDServerStop(priv->mon));