]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: checkpoint: Fix rollback and access to unlocked 'vm' when deleting checkpoints
authorPeter Krempa <pkrempa@redhat.com>
Thu, 26 Sep 2019 14:56:16 +0000 (16:56 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Wed, 20 Nov 2019 12:24:54 +0000 (13:24 +0100)
Delete/merge bitmaps when deleting checkpoints using a 'transaction' so
that we don't have to deal with halfway-failed scenarios and also fix
access to 'vm' while in the monitor lock.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_checkpoint.c

index 20cefd1af403506d62e649c17d070143845de0e0..d667ef9f06e4d59c1292557934d074d12ac5106a 100644 (file)
@@ -130,11 +130,14 @@ qemuCheckpointDiscard(virQEMUDriverPtr driver,
 
     if (!metadata_only) {
         qemuDomainObjPrivatePtr priv = vm->privateData;
-        bool success = true;
         bool search_parents;
         virDomainCheckpointDefPtr chkdef = virDomainCheckpointObjGetDef(chk);
+        int rc;
+        g_autoptr(virJSONValue) actions = NULL;
+
+        if (!(actions = virJSONValueNewArray()))
+            return -1;
 
-        qemuDomainObjEnterMonitor(driver, vm);
         parent = virDomainCheckpointFindByName(vm->checkpoints,
                                                chk->def->parent_name);
         for (i = 0; i < chkdef->ndisks; i++) {
@@ -164,31 +167,29 @@ qemuCheckpointDiscard(virQEMUDriverPtr driver,
                         continue;
                     search_parents = false;
 
-                    arr = virJSONValueNewArray();
-                    if (!arr ||
-                        virJSONValueArrayAppendString(arr, disk->bitmap) < 0) {
-                        success = false;
-                        break;
-                    }
-                    if (chk == virDomainCheckpointGetCurrent(vm->checkpoints) &&
-                        qemuMonitorEnableBitmap(priv->mon, node,
-                                                disk2->bitmap) < 0) {
-                        success = false;
-                        break;
-                    }
-                    if (qemuMonitorMergeBitmaps(priv->mon, node,
-                                                disk2->bitmap, &arr) < 0) {
-                        success = false;
-                        break;
+                    if (!(arr = virJSONValueNewArray()))
+                        return -1;
+
+                    if (virJSONValueArrayAppendString(arr, disk->bitmap) < 0)
+                        return -1;
+
+                    if (chk == virDomainCheckpointGetCurrent(vm->checkpoints)) {
+                        if (qemuMonitorTransactionBitmapEnable(actions, node, disk2->bitmap) < 0)
+                            return -1;
                     }
+
+                    if (qemuMonitorTransactionBitmapMerge(actions, node, disk2->bitmap, &arr) < 0)
+                        return -1;
                 }
             }
-            if (qemuMonitorDeleteBitmap(priv->mon, node, disk->bitmap) < 0) {
-                success = false;
-                break;
-            }
+
+            if (qemuMonitorTransactionBitmapRemove(actions, node, disk->bitmap) < 0)
+                return -1;
         }
-        if (qemuDomainObjExitMonitor(driver, vm) < 0 || !success)
+
+        qemuDomainObjEnterMonitor(driver, vm);
+        rc = qemuMonitorTransaction(priv->mon, &actions);
+        if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
             return -1;
     }