[libvirt] [PATCH 18/27] Add API for issugin 'pci_add host' monitor command

Daniel P. Berrange berrange at redhat.com
Thu Sep 24 15:00:20 UTC 2009


* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new
  API qemuMonitorAddPCIHostDevice()
* src/qemu/qemu_driver.c: Switch to using qemuMonitorAddPCIHostDevice()
  for PCI host device hotplug
---
 src/qemu/qemu_driver.c       |   46 +++-------------
 src/qemu/qemu_monitor_text.c |  121 ++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_text.h |   11 ++++
 3 files changed, 140 insertions(+), 38 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f33c24e..e9e7543 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4903,8 +4903,6 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
                                           virDomainDeviceDefPtr dev)
 {
     virDomainHostdevDefPtr hostdev = dev->data.hostdev;
-    char *cmd, *reply;
-    unsigned domain, bus, slot;
     pciDevice *pci;
 
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
@@ -4931,51 +4929,23 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
         return -1;
     }
 
-    cmd = reply = NULL;
-
-    if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x",
-                    hostdev->source.subsys.u.pci.bus,
-                    hostdev->source.subsys.u.pci.slot,
-                    hostdev->source.subsys.u.pci.function) < 0) {
-        virReportOOMError(conn);
-        goto error;
-    }
-
-    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
-        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
-                         "%s", _("cannot attach host pci device"));
+    if (qemuMonitorAddPCIHostDevice(vm,
+                                    hostdev->source.subsys.u.pci.domain,
+                                    hostdev->source.subsys.u.pci.bus,
+                                    hostdev->source.subsys.u.pci.slot,
+                                    hostdev->source.subsys.u.pci.function,
+                                    &hostdev->source.subsys.u.pci.guest_addr.domain,
+                                    &hostdev->source.subsys.u.pci.guest_addr.bus,
+                                    &hostdev->source.subsys.u.pci.guest_addr.slot) < 0)
         goto error;
-    }
-
-    if (strstr(reply, "invalid type: host")) {
-        qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
-                         _("PCI device assignment is not supported by this version of qemu"));
-        goto error;
-    }
-
-    if (qemudParsePciAddReply(vm, reply, &domain, &bus, &slot) < 0) {
-        qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
-                         _("parsing pci_add reply failed: %s"), reply);
-        goto error;
-    }
-
-    hostdev->source.subsys.u.pci.guest_addr.domain = domain;
-    hostdev->source.subsys.u.pci.guest_addr.bus    = bus;
-    hostdev->source.subsys.u.pci.guest_addr.slot   = slot;
 
     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
 
-    VIR_FREE(reply);
-    VIR_FREE(cmd);
-
     return 0;
 
 error:
     pciDeviceListDel(conn, driver->activePciHostdevs, pci);
 
-    VIR_FREE(reply);
-    VIR_FREE(cmd);
-
     return -1;
 }
 
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 0e0334c..ca84fc6 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -1315,3 +1315,124 @@ int qemuMonitorAddUSBDeviceMatch(const virDomainObjPtr vm,
     VIR_FREE(addr);
     return ret;
 }
+
+
+static int
+qemuMonitorParsePciAddReply(virDomainObjPtr vm,
+                            const char *reply,
+                            unsigned *domain,
+                            unsigned *bus,
+                            unsigned *slot)
+{
+    char *s, *e;
+
+    DEBUG("%s: pci_add reply: %s", vm->def->name, reply);
+
+    /* If the command succeeds qemu prints:
+     * OK bus 0, slot XXX...
+     * or
+     * OK domain 0, bus 0, slot XXX
+     */
+    if (!(s = strstr(reply, "OK ")))
+        return -1;
+
+    s += 3;
+
+    if (STRPREFIX(s, "domain ")) {
+        s += strlen("domain ");
+
+        if (virStrToLong_ui(s, &e, 10, domain) == -1) {
+            VIR_WARN(_("Unable to parse domain number '%s'\n"), s);
+            return -1;
+        }
+
+        if (!STRPREFIX(e, ", ")) {
+            VIR_WARN(_("Expected ', ' parsing pci_add reply '%s'\n"), s);
+            return -1;
+        }
+        s = e + 2;
+    }
+
+    if (!STRPREFIX(s, "bus ")) {
+        VIR_WARN(_("Expected 'bus ' parsing pci_add reply '%s'\n"), s);
+        return -1;
+    }
+    s += strlen("bus ");
+
+    if (virStrToLong_ui(s, &e, 10, bus) == -1) {
+        VIR_WARN(_("Unable to parse bus number '%s'\n"), s);
+        return -1;
+    }
+
+    if (!STRPREFIX(e, ", ")) {
+        VIR_WARN(_("Expected ', ' parsing pci_add reply '%s'\n"), s);
+        return -1;
+    }
+    s = e + 2;
+
+    if (!STRPREFIX(s, "slot ")) {
+        VIR_WARN(_("Expected 'slot ' parsing pci_add reply '%s'\n"), s);
+        return -1;
+    }
+    s += strlen("slot ");
+
+    if (virStrToLong_ui(s, &e, 10, slot) == -1) {
+        VIR_WARN(_("Unable to parse slot number '%s'\n"), s);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+int qemuMonitorAddPCIHostDevice(const virDomainObjPtr vm,
+                                unsigned hostDomain ATTRIBUTE_UNUSED,
+                                unsigned hostBus,
+                                unsigned hostSlot,
+                                unsigned hostFunction,
+                                unsigned *guestDomain,
+                                unsigned *guestBus,
+                                unsigned *guestSlot)
+{
+    char *cmd;
+    char *reply = NULL;
+    int ret = -1;
+
+    *guestDomain = *guestBus = *guestSlot = 0;
+
+    /* XXX hostDomain */
+    if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x",
+                    hostBus, hostSlot, hostFunction) < 0) {
+        virReportOOMError(NULL);
+        goto cleanup;
+    }
+
+    if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
+        qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "%s", _("cannot attach host pci device"));
+        goto cleanup;
+    }
+
+    if (strstr(reply, "invalid type: host")) {
+        qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_SUPPORT, "%s",
+                         _("PCI device assignment is not supported by this version of qemu"));
+        goto cleanup;
+    }
+
+    if (qemuMonitorParsePciAddReply(vm, reply,
+                                    guestDomain,
+                                    guestBus,
+                                    guestSlot) < 0) {
+        qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         _("parsing pci_add reply failed: %s"), reply);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(cmd);
+    VIR_FREE(reply);
+    return ret;
+}
+
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 4153090..0e1b27b 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -147,4 +147,15 @@ int qemuMonitorAddUSBDeviceMatch(const virDomainObjPtr vm,
                                  int vendor,
                                  int product);
 
+
+int qemuMonitorAddPCIHostDevice(const virDomainObjPtr vm,
+                                unsigned hostDomain,
+                                unsigned hostBus,
+                                unsigned hostSlot,
+                                unsigned hostFunction,
+                                unsigned *guestDomain,
+                                unsigned *guestBus,
+                                unsigned *guestSlot);
+
+
 #endif /* QEMU_MONITOR_TEXT_H */
-- 
1.6.2.5




More information about the libvir-list mailing list