Blob Blame History Raw
commit 326ecb78145cfeb7706ef0dcd521b19d934950e7
Author: Daniel P. Berrange <berrange@redhat.com>
Date:   Mon Jul 6 15:58:55 2009 +0100

    Fix PCI device hotplug/unplug with newer QEMU
    
    * src/qemu_driver.c: Try new monitor syntax for hotplug first. If
      that fails fallback to old KVM specific syntax

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 2e55045..5a0ab12 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -4004,6 +4004,7 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
     char *cmd, *reply, *s;
     char *safe_path;
     const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
+    int tryOldSyntax = 0;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
         if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
@@ -4018,14 +4019,15 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
         return -1;
     }
 
+try_command:
     safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
     if (!safe_path) {
         virReportOOMError(conn);
         return -1;
     }
 
-    ret = virAsprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
-                      safe_path, type);
+    ret = virAsprintf(&cmd, "pci_add %s storage file=%s,if=%s",
+                      (tryOldSyntax ? "0": "pci_addr=auto"), safe_path, type);
     VIR_FREE(safe_path);
     if (ret == -1) {
         virReportOOMError(conn);
@@ -4041,17 +4043,27 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
 
     DEBUG ("%s: pci_add reply: %s", vm->def->name, reply);
     /* If the command succeeds qemu prints:
-     * OK bus 0... */
-#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
-    if ((s=strstr(reply, PCI_ATTACH_OK_MSG))) {
-        char* dummy = s;
-        s += strlen(PCI_ATTACH_OK_MSG);
+     * OK bus 0, slot XXX...
+     * or
+     * OK domain 0, bus 0, slot XXX
+     */
+    if ((s = strstr(reply, "OK ")) &&
+        (s = strstr(s, "slot "))) {
+        char *dummy = s;
+        s += strlen("slot ");
 
         if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1)
             VIR_WARN("%s", _("Unable to parse slot number\n"));
+        /* XXX not neccessarily always going to end up in domain 0 / bus 0 :-( */
+        /* XXX this slotnum is not persistant across restarts :-( */
+    } else if (!tryOldSyntax && strstr(reply, "invalid char in expression")) {
+        VIR_FREE(reply);
+        VIR_FREE(cmd);
+        tryOldSyntax = 1;
+        goto try_command;
     } else {
         qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
-                          _("adding %s disk failed"), type);
+                          _("adding %s disk failed: %s"), type, reply);
         VIR_FREE(reply);
         VIR_FREE(cmd);
         return -1;
@@ -4268,6 +4280,7 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
     char *cmd = NULL;
     char *reply = NULL;
     virDomainDiskDefPtr detach = NULL;
+    int tryOldSyntax = 0;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
         if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
@@ -4289,9 +4302,17 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
         goto cleanup;
     }
 
-    if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
-        virReportOOMError(conn);
-        goto cleanup;
+try_command:
+    if (tryOldSyntax) {
+        if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
+            virReportOOMError(conn);
+            goto cleanup;
+        }
+    } else {
+        if (virAsprintf(&cmd, "pci_del pci_addr=0:0:%d", detach->slotnum) < 0) {
+            virReportOOMError(conn);
+            goto cleanup;
+        }
     }
 
     if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
@@ -4301,12 +4322,19 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
     }
 
     DEBUG ("%s: pci_del reply: %s",vm->def->name,  reply);
+
+    if (!tryOldSyntax &&
+        strstr(reply, "extraneous characters")) {
+        tryOldSyntax = 1;
+        goto try_command;
+    }
     /* If the command fails due to a wrong slot qemu prints: invalid slot,
      * nothing is printed on success */
-    if (strstr(reply, "invalid slot")) {
+    if (strstr(reply, "invalid slot") ||
+        strstr(reply, "Invalid pci address")) {
         qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
-                          _("failed to detach disk %s: invalid slot %d"),
-                          detach->dst, detach->slotnum);
+                          _("failed to detach disk %s: invalid slot %d: %s"),
+                          detach->dst, detach->slotnum, reply);
         goto cleanup;
     }