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

[RFC] [PATCH] Re: [libvirt] race between qemu monitor startup and blocking migrate -incoming



[ This is also filed in Red Hat's bugzilla at https://bugzilla.redhat.com/show_bug.cgi?id=537938 ]

In cases where compression is in use, putting the waitpid() for the decompression tool before the qemudWaitForMonitor() call appears to eliminate the race in question.

As much of a cheap hack as it is, it seems like it would resolve the race condition in question to always spawn and block on an intermediate process, even if this means having *two* "cat" processes between libvirtd and the qemu or kvm it is starting.

Comments?
--- libvirt-0.7.2/src/qemu/qemu_driver.c.orig	2009-11-18 17:30:52.502986557 -0600
+++ libvirt-0.7.2/src/qemu/qemu_driver.c	2009-11-18 17:37:30.414042960 -0600
@@ -100,7 +100,9 @@
                               struct qemud_driver *driver,
                               virDomainObjPtr vm,
                               const char *migrateFrom,
-                              int stdin_fd);
+                              int stdin_fd,
+                              int intermediate_pid,
+                              int intermediate_fd);
 
 static void qemudShutdownVMDaemon(virConnectPtr conn,
                                   struct qemud_driver *driver,
@@ -223,7 +225,7 @@
             int ret;
 
             virResetLastError();
-            ret = qemudStartVMDaemon(conn, driver, vm, NULL, -1);
+            ret = qemudStartVMDaemon(conn, driver, vm, NULL, -1, -1, -1);
             if (ret < 0) {
                 virErrorPtr err = virGetLastError();
                 VIR_ERROR(_("Failed to autostart VM '%s': %s\n"),
@@ -1941,7 +1943,9 @@
                               struct qemud_driver *driver,
                               virDomainObjPtr vm,
                               const char *migrateFrom,
-                              int stdin_fd) {
+                              int stdin_fd,
+                              int intermediate_pid,
+                              int intermediate_fd) {
     const char **argv = NULL, **tmp;
     const char **progenv = NULL;
     int i, ret;
@@ -1956,6 +1960,7 @@
     char ebuf[1024];
     char *pidfile = NULL;
     int logfile;
+    int childstat;
 
     struct qemudHookData hookData;
     hookData.conn = conn;
@@ -2131,6 +2136,14 @@
     if (ret == -1)
         goto cleanup;
 
+    if (intermediate_pid != -1) {
+        /* Wait for intermediate process to exit */
+        while (waitpid(intermediate_pid, &childstat, 0) == -1 &&
+               errno == EINTR);
+    }
+    if (intermediate_fd != -1)
+        close(intermediate_fd);
+
     if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
         (qemuDetectVcpuPIDs(conn, vm) < 0) ||
         (qemudInitCpus(conn, vm, migrateFrom) < 0) ||
@@ -2723,7 +2736,7 @@
 
     def = NULL;
 
-    if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
+    if (qemudStartVMDaemon(conn, driver, vm, NULL, -1, -1, -1) < 0) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
         vm = NULL;
@@ -3837,14 +3850,8 @@
         }
     }
     /* Set the migration source and start it up. */
-    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
-    if (intermediate_pid != -1) {
-        /* Wait for intermediate process to exit */
-        while (waitpid(intermediate_pid, &childstat, 0) == -1 &&
-               errno == EINTR);
-    }
-    if (intermediatefd != -1)
-        close(intermediatefd);
+    ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd,
+        intermediate_pid, intermediatefd);
     close(fd);
     fd = -1;
     if (ret < 0) {
@@ -4144,7 +4151,7 @@
         goto cleanup;
     }
 
-    ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1);
+    ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL, -1, -1, -1);
     if (ret != -1)
         event = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_STARTED,
@@ -6209,7 +6216,7 @@
     /* Start the QEMU daemon, with the same command-line arguments plus
      * -incoming unix:/path/to/file or exec:nc -U /path/to/file
      */
-    internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, -1);
+    internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, -1, -1, -1);
     VIR_FREE(migrateFrom);
     if (internalret < 0) {
         /* Note that we don't set an error here because qemudStartVMDaemon
@@ -6404,7 +6411,7 @@
      * -incoming tcp:0.0.0.0:port
      */
     snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d", this_port);
-    if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1) < 0) {
+    if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, -1, -1, -1) < 0) {
         /* Note that we don't set an error here because qemudStartVMDaemon
          * should have already done that.
          */

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