render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
c401cc
From feb15e85c1f12d31dc2db7bbaabcfb4ad93ccb03 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <feb15e85c1f12d31dc2db7bbaabcfb4ad93ccb03@dist-git>
c401cc
From: Peter Krempa <pkrempa@redhat.com>
c401cc
Date: Wed, 26 Feb 2014 14:55:19 +0100
c401cc
Subject: [PATCH] qemu: snapshot: Avoid libvirtd crash when qemu crashes while
c401cc
 snapshotting
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
c401cc
c401cc
We shouldn't access the domain definition while we are in the monitor
c401cc
section as the domain is unlocked. Additionally after we exit from the
c401cc
monitor we need to check if the VM is still alive. Not doing so resulted
c401cc
in a crash if qemu exits while attempting to do an external VM snapshot.
c401cc
c401cc
(cherry picked from commit 55bbb011b965c7962933604c70f61cef45e8ec04)
c401cc
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/qemu/qemu_driver.c | 53 ++++++++++++++++++++++++++++++++++++++------------
c401cc
 1 file changed, 41 insertions(+), 12 deletions(-)
c401cc
c401cc
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
c401cc
index 2fe128e..fe55fed 100644
c401cc
--- a/src/qemu/qemu_driver.c
c401cc
+++ b/src/qemu/qemu_driver.c
c401cc
@@ -12489,7 +12489,8 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
c401cc
                                          virDomainDiskDefPtr disk,
c401cc
                                          virDomainDiskDefPtr persistDisk,
c401cc
                                          virJSONValuePtr actions,
c401cc
-                                         bool reuse)
c401cc
+                                         bool reuse,
c401cc
+                                         enum qemuDomainAsyncJob asyncJob)
c401cc
 {
c401cc
     qemuDomainObjPrivatePtr priv = vm->privateData;
c401cc
     char *device = NULL;
c401cc
@@ -12541,8 +12542,25 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
c401cc
     /* create the actual snapshot */
c401cc
     if (snap->format)
c401cc
         formatStr = virStorageFileFormatTypeToString(snap->format);
c401cc
+
c401cc
+    /* The monitor is only accessed if qemu doesn't support transactions.
c401cc
+     * Otherwise the following monitor command only constructs the command.
c401cc
+     */
c401cc
+    if (!actions &&
c401cc
+        qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
c401cc
+        goto cleanup;
c401cc
+
c401cc
     ret = qemuMonitorDiskSnapshot(priv->mon, actions, device, source,
c401cc
                                   formatStr, reuse);
c401cc
+    if (!actions) {
c401cc
+        qemuDomainObjExitMonitor(driver, vm);
c401cc
+        if (!virDomainObjIsActive(vm)) {
c401cc
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c401cc
+                           _("domain crashed while taking the snapshot"));
c401cc
+            ret = -1;
c401cc
+        }
c401cc
+    }
c401cc
+
c401cc
     virDomainAuditDisk(vm, disk->src, source, "snapshot", ret >= 0);
c401cc
     if (ret < 0)
c401cc
         goto cleanup;
c401cc
@@ -12648,9 +12666,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
c401cc
      * Based on earlier qemuDomainSnapshotPrepare, all
c401cc
      * disks in this list are now either SNAPSHOT_NO, or
c401cc
      * SNAPSHOT_EXTERNAL with a valid file name and qcow2 format.  */
c401cc
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
c401cc
-        goto cleanup;
c401cc
-
c401cc
     for (i = 0; i < snap->def->ndisks; i++) {
c401cc
         virDomainDiskDefPtr persistDisk = NULL;
c401cc
 
c401cc
@@ -12660,24 +12675,36 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
c401cc
             int indx = virDomainDiskIndexByName(vm->newDef,
c401cc
                                                 vm->def->disks[i]->dst,
c401cc
                                                 false);
c401cc
-            if (indx >= 0) {
c401cc
+            if (indx >= 0)
c401cc
                 persistDisk = vm->newDef->disks[indx];
c401cc
-                persist = true;
c401cc
-            }
c401cc
         }
c401cc
 
c401cc
         ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
c401cc
                                                        &snap->def->disks[i],
c401cc
                                                        vm->def->disks[i],
c401cc
                                                        persistDisk, actions,
c401cc
-                                                       reuse);
c401cc
+                                                       reuse, asyncJob);
c401cc
         if (ret < 0)
c401cc
             break;
c401cc
     }
c401cc
     if (actions) {
c401cc
-        if (ret == 0)
c401cc
-            ret = qemuMonitorTransaction(priv->mon, actions);
c401cc
+        if (ret == 0) {
c401cc
+            if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
c401cc
+                ret = qemuMonitorTransaction(priv->mon, actions);
c401cc
+                qemuDomainObjExitMonitor(driver, vm);
c401cc
+                if (!virDomainObjIsActive(vm)) {
c401cc
+                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c401cc
+                                   _("domain crashed while taking the snapshot"));
c401cc
+                    ret = -1;
c401cc
+                }
c401cc
+            } else {
c401cc
+                /* failed to enter monitor, clean stuff up and quit */
c401cc
+                ret = -1;
c401cc
+            }
c401cc
+        }
c401cc
+
c401cc
         virJSONValueFree(actions);
c401cc
+
c401cc
         if (ret < 0) {
c401cc
             /* Transaction failed; undo the changes to vm.  */
c401cc
             bool need_unlink = !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT);
c401cc
@@ -12691,8 +12718,11 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
c401cc
                     int indx = virDomainDiskIndexByName(vm->newDef,
c401cc
                                                         vm->def->disks[i]->dst,
c401cc
                                                         false);
c401cc
-                    if (indx >= 0)
c401cc
+                    if (indx >= 0) {
c401cc
                         persistDisk = vm->newDef->disks[indx];
c401cc
+                        persist = true;
c401cc
+                    }
c401cc
+
c401cc
                 }
c401cc
 
c401cc
                 qemuDomainSnapshotUndoSingleDiskActive(driver, vm,
c401cc
@@ -12703,7 +12733,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
c401cc
             }
c401cc
         }
c401cc
     }
c401cc
-    qemuDomainObjExitMonitor(driver, vm);
c401cc
 
c401cc
 cleanup:
c401cc
 
c401cc
-- 
c401cc
1.9.0
c401cc