[libvirt] [PATCH] Ignore qemu STOP event when stopping CPUs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jiri Denemark <jdenemar@xxxxxxxxxx>

With JSON qemu monitor, we get a STOP event from qemu whenever qemu
stops guests CPUs. The downside of it is that vm->state is changed to
PAUSED and a new generic paused event is send to applications. However,
when we ask qemu to stop the CPUs we are not really interested in qemu
event and we usually want to issue a more specific event.

By setting vm->status to PAUSED before actually sending the request to
qemu (and resetting it back if the request fails) we can ignore the
event since the event handler does nothing when the guest is already
paused. This solution is quite hacky but unfortunately it's the best
solution which I was able to come up with and it doesn't introduce a
race condition.
---
 src/qemu/qemu_driver.c |   25 +++++++++++++++++++------
 1 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3c4876e..8ccf0b7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4117,13 +4117,16 @@ static int qemudDomainSuspend(virDomainPtr dom) {
         }
         if (vm->state != VIR_DOMAIN_PAUSED) {
             int rc;
+            int state = vm->state;
 
+            vm->state = VIR_DOMAIN_PAUSED;
             qemuDomainObjEnterMonitorWithDriver(driver, vm);
             rc = qemuMonitorStopCPUs(priv->mon);
             qemuDomainObjExitMonitorWithDriver(driver, vm);
-            if (rc < 0)
+            if (rc < 0) {
+                vm->state = state;
                 goto endjob;
-            vm->state = VIR_DOMAIN_PAUSED;
+            }
             event = virDomainEventNewFromObj(vm,
                                              VIR_DOMAIN_EVENT_SUSPENDED,
                                              VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
@@ -4491,8 +4494,10 @@ qemuDomainMigrateOffline(struct qemud_driver *driver,
                          virDomainObjPtr vm)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    int state = vm->state;
     int ret;
 
+    vm->state = VIR_DOMAIN_PAUSED;
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     ret = qemuMonitorStopCPUs(priv->mon);
     qemuDomainObjExitMonitorWithDriver(driver, vm);
@@ -4500,13 +4505,13 @@ qemuDomainMigrateOffline(struct qemud_driver *driver,
     if (ret == 0) {
         virDomainEventPtr event;
 
-        vm->state = VIR_DOMAIN_PAUSED;
         event = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_SUSPENDED,
                                          VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
         if (event)
             qemuDomainEventQueue(driver, event);
-    }
+    } else
+        vm->state = state;
 
     return ret;
 }
@@ -4743,13 +4748,14 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
     /* Pause */
     if (vm->state == VIR_DOMAIN_RUNNING) {
         header.was_running = 1;
+        vm->state = VIR_DOMAIN_PAUSED;
         qemuDomainObjEnterMonitorWithDriver(driver, vm);
         if (qemuMonitorStopCPUs(priv->mon) < 0) {
             qemuDomainObjExitMonitorWithDriver(driver, vm);
+            vm->state = VIR_DOMAIN_RUNNING;
             goto endjob;
         }
         qemuDomainObjExitMonitorWithDriver(driver, vm);
-        vm->state = VIR_DOMAIN_PAUSED;
     }
 
     /* Get XML for the domain */
@@ -5167,9 +5173,11 @@ static int qemudDomainCoreDump(virDomainPtr dom,
 
     /* Pause domain for non-live dump */
     if (!(flags & VIR_DUMP_LIVE) && vm->state == VIR_DOMAIN_RUNNING) {
+        vm->state = VIR_DOMAIN_PAUSED;
         qemuDomainObjEnterMonitorWithDriver(driver, vm);
         if (qemuMonitorStopCPUs(priv->mon) < 0) {
             qemuDomainObjExitMonitorWithDriver(driver, vm);
+            vm->state = VIR_DOMAIN_RUNNING;
             goto endjob;
         }
         qemuDomainObjExitMonitorWithDriver(driver, vm);
@@ -5214,6 +5222,7 @@ endjob:
                                 "%s", _("resuming after dump failed"));
         }
         qemuDomainObjExitMonitorWithDriver(driver, vm);
+        vm->state = VIR_DOMAIN_RUNNING;
     }
 
     if (qemuDomainObjEndJob(vm) == 0)
@@ -11056,12 +11065,16 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
             /* qemu unconditionally starts the domain running again after
              * loadvm, so let's pause it to keep consistency
              */
+            int state = vm->state;
             priv = vm->privateData;
+            vm->state = VIR_DOMAIN_PAUSED;
             qemuDomainObjEnterMonitorWithDriver(driver, vm);
             rc = qemuMonitorStopCPUs(priv->mon);
             qemuDomainObjExitMonitorWithDriver(driver, vm);
-            if (rc < 0)
+            if (rc < 0) {
+                vm->state = state;
                 goto cleanup;
+            }
         }
 
         event = virDomainEventNewFromObj(vm,
-- 
1.7.0.4

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]