[libvirt] [PATCH 4/7] Make hotplug use new device_add where possible

Daniel P. Berrange berrange at redhat.com
Wed Jan 27 19:22:57 UTC 2010


Since QEMU startup uses the new -device argument, the hotplug
code needs todo the same.

* src/qemu/qemu_driver.c: Use new device_add monitor APIs
  whereever possible
---
 src/qemu/qemu_driver.c |  222 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 169 insertions(+), 53 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bf21923..4608a69 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5185,12 +5185,14 @@ error:
 static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
                                           struct qemud_driver *driver,
                                           virDomainObjPtr vm,
-                                          virDomainDiskDefPtr disk)
+                                          virDomainDiskDefPtr disk,
+                                          int qemuCmdFlags)
 {
     int i, ret;
     const char* type = virDomainDiskBusTypeToString(disk->bus);
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    virDomainDevicePCIAddress guestAddr;
+    char *devstr = NULL;
+    char *drivestr = NULL;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
         if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
@@ -5205,28 +5207,52 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
         driver->securityDriver->domainSetSecurityImageLabel(conn, vm, disk) < 0)
         return -1;
 
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+        if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
+            goto error;
+
+        if (!(devstr = qemuBuildDriveDevStr(NULL, disk)))
+            goto error;
+    }
+
     if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
         virReportOOMError(conn);
         goto error;
     }
 
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
-    ret = qemuMonitorAddPCIDisk(priv->mon,
-                                disk->src,
-                                type,
-                                &guestAddr);
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+        ret = qemuMonitorAddDrive(priv->mon, drivestr);
+        if (ret == 0)
+            qemuMonitorAddDevice(priv->mon, devstr);
+            /* XXX remove the drive upon fail */
+    } else {
+        virDomainDevicePCIAddress guestAddr;
+        ret = qemuMonitorAddPCIDisk(priv->mon,
+                                    disk->src,
+                                    type,
+                                    &guestAddr);
+        if (ret == 0) {
+            disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+            memcpy(&disk->info.addr.pci, &guestAddr, sizeof(guestAddr));
+        }
+    }
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
     if (ret < 0)
         goto error;
 
-    disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-    memcpy(&disk->info.addr.pci, &guestAddr, sizeof(guestAddr));
     virDomainDiskInsertPreAlloced(vm->def, disk);
 
+    VIR_FREE(devstr);
+    VIR_FREE(drivestr);
+
     return 0;
 
 error:
+    VIR_FREE(devstr);
+    VIR_FREE(drivestr);
+
     if (driver->securityDriver &&
         driver->securityDriver->domainRestoreSecurityImageLabel &&
         driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm, disk) < 0)
@@ -5239,10 +5265,13 @@ error:
 static int qemudDomainAttachPciControllerDevice(virConnectPtr conn,
                                                 struct qemud_driver *driver,
                                                 virDomainObjPtr vm,
-                                                virDomainControllerDefPtr controller)
+                                                virDomainControllerDefPtr controller,
+                                                int qemuCmdFlags)
 {
-    int i, ret;
+    int i;
+    int ret = -1;
     const char* type = virDomainControllerTypeToString(controller->type);
+    char *devstr = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
 
     for (i = 0 ; i < vm->def->ncontrollers ; i++) {
@@ -5255,15 +5284,24 @@ static int qemudDomainAttachPciControllerDevice(virConnectPtr conn,
         }
     }
 
+    if (!(devstr = qemuBuildControllerDevStr(controller))) {
+        virReportOOMError(NULL);
+        goto cleanup;
+    }
+
     if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers+1) < 0) {
-        virReportOOMError(conn);
-        return -1;
+        virReportOOMError(NULL);
+        goto cleanup;
     }
 
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
-    ret = qemuMonitorAttachPCIDiskController(priv->mon,
-                                             type,
-                                             &controller->info.addr.pci);
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+        ret = qemuMonitorAddDevice(priv->mon, devstr);
+    } else {
+        ret = qemuMonitorAttachPCIDiskController(priv->mon,
+                                                 type,
+                                                 &controller->info.addr.pci);
+    }
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
     if (ret == 0) {
@@ -5271,6 +5309,8 @@ static int qemudDomainAttachPciControllerDevice(virConnectPtr conn,
         virDomainControllerInsertPreAlloced(vm->def, controller);
     }
 
+cleanup:
+    VIR_FREE(devstr);
     return ret;
 }
 
@@ -5279,7 +5319,8 @@ static virDomainControllerDefPtr
 qemuDomainFindOrCreateSCSIDiskController(virConnectPtr conn,
                                          struct qemud_driver *driver,
                                          virDomainObjPtr vm,
-                                         int controller)
+                                         int controller,
+                                         int qemuCmdFlags)
 {
     int i;
     virDomainControllerDefPtr cont;
@@ -5304,7 +5345,7 @@ qemuDomainFindOrCreateSCSIDiskController(virConnectPtr conn,
 
     VIR_INFO0("No SCSI controller present, hotplugging one");
     if (qemudDomainAttachPciControllerDevice(conn, driver,
-                                             vm, cont) < 0) {
+                                             vm, cont, qemuCmdFlags) < 0) {
         VIR_FREE(cont);
         return NULL;
     }
@@ -5320,9 +5361,9 @@ static int qemudDomainAttachSCSIDisk(virConnectPtr conn,
 {
     int i;
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    virDomainDeviceDriveAddress driveAddr;
     virDomainControllerDefPtr cont;
     char *drivestr = NULL;
+    char *devstr = NULL;
     int ret = -1;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
@@ -5345,6 +5386,9 @@ static int qemudDomainAttachSCSIDisk(virConnectPtr conn,
     if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
         goto error;
 
+    if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
+        !(devstr = qemuBuildDriveDevStr(NULL, disk)))
+        goto error;
 
     /* We should have an adddress now, so make sure */
     if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
@@ -5355,7 +5399,7 @@ static int qemudDomainAttachSCSIDisk(virConnectPtr conn,
     }
 
     for (i = 0 ; i <= disk->info.addr.drive.controller ; i++) {
-        cont = qemuDomainFindOrCreateSCSIDiskController(conn, driver, vm, i);
+        cont = qemuDomainFindOrCreateSCSIDiskController(conn, driver, vm, i, qemuCmdFlags);
         if (!cont)
             goto error;
     }
@@ -5372,26 +5416,42 @@ static int qemudDomainAttachSCSIDisk(virConnectPtr conn,
     }
 
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
-    ret = qemuMonitorAttachDrive(priv->mon,
-                                 drivestr,
-                                 &cont->info.addr.pci,
-                                 &driveAddr);
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+        ret = qemuMonitorAddDrive(priv->mon,
+                                  drivestr);
+        if (ret == 0)
+            ret = qemuMonitorAddDevice(priv->mon,
+                                       devstr);
+            /* XXX should call 'drive_del' on error but this does not exist yet */
+    } else {
+        virDomainDeviceDriveAddress driveAddr;
+        ret = qemuMonitorAttachDrive(priv->mon,
+                                     drivestr,
+                                     &cont->info.addr.pci,
+                                     &driveAddr);
+        if (ret == 0) {
+            /* XXX we should probably validate that the addr matches
+             * our existing defined addr instead of overwriting */
+            disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
+            memcpy(&disk->info.addr.drive, &driveAddr, sizeof(driveAddr));
+        }
+    }
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
     if (ret < 0)
         goto error;
 
-    /* XXX we should probably validate that the addr matches
-     * our existing defined addr instead of overwriting */
-    disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
-    memcpy(&disk->info.addr.drive, &driveAddr, sizeof(driveAddr));
     virDomainDiskInsertPreAlloced(vm->def, disk);
+
+    VIR_FREE(devstr);
     VIR_FREE(drivestr);
 
     return 0;
 
 error:
+    VIR_FREE(devstr);
     VIR_FREE(drivestr);
+
     if (driver->securityDriver &&
         driver->securityDriver->domainRestoreSecurityImageLabel &&
         driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm, disk) < 0)
@@ -5404,10 +5464,13 @@ error:
 static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
                                                  struct qemud_driver *driver,
                                                  virDomainObjPtr vm,
-                                                 virDomainDiskDefPtr disk)
+                                                 virDomainDiskDefPtr disk,
+                                                 int qemuCmdFlags)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int i, ret;
+    char *drivestr = NULL;
+    char *devstr = NULL;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
         if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
@@ -5428,13 +5491,29 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
         goto error;
     }
 
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+        if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
+            goto error;
+        if (!(devstr = qemuBuildDriveDevStr(NULL, disk)))
+            goto error;
+    }
+
     if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
         virReportOOMError(conn);
         goto error;
     }
 
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
-    ret = qemuMonitorAddUSBDisk(priv->mon, disk->src);
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+        ret = qemuMonitorAddDrive(priv->mon,
+                                  drivestr);
+        if (ret == 0)
+            ret = qemuMonitorAddDevice(priv->mon,
+                                       devstr);
+            /* XXX should call 'drive_del' on error but this does not exist yet */
+    } else {
+        ret = qemuMonitorAddUSBDisk(priv->mon, disk->src);
+    }
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
     if (ret < 0)
@@ -5442,9 +5521,15 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
 
     virDomainDiskInsertPreAlloced(vm->def, disk);
 
+    VIR_FREE(devstr);
+    VIR_FREE(drivestr);
+
     return 0;
 
 error:
+    VIR_FREE(devstr);
+    VIR_FREE(drivestr);
+
     if (driver->securityDriver &&
         driver->securityDriver->domainRestoreSecurityImageLabel &&
         driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm, disk) < 0)
@@ -5587,12 +5672,14 @@ no_memory:
 static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
                                           struct qemud_driver *driver,
                                           virDomainObjPtr vm,
-                                          virDomainHostdevDefPtr hostdev)
+                                          virDomainHostdevDefPtr hostdev,
+                                          int qemuCmdFlags)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     pciDevice *pci;
     int ret;
     virDomainDevicePCIAddress guestAddr;
+    char *devstr = NULL;
 
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
         virReportOOMError(conn);
@@ -5619,10 +5706,17 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
         return -1;
     }
 
+    if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
+        !(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
+        goto error;
+
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
-    ret = qemuMonitorAddPCIHostDevice(priv->mon,
-                                      &hostdev->source.subsys.u.pci,
-                                      &guestAddr);
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
+        ret = qemuMonitorAddDevice(priv->mon, devstr);
+    else
+        ret = qemuMonitorAddPCIHostDevice(priv->mon,
+                                          &hostdev->source.subsys.u.pci,
+                                          &guestAddr);
     qemuDomainObjExitMonitorWithDriver(driver, vm);
     if (ret < 0)
         goto error;
@@ -5631,9 +5725,12 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
 
     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
 
+    VIR_FREE(devstr);
+
     return 0;
 
 error:
+    VIR_FREE(devstr);
     pciDeviceListDel(conn, driver->activePciHostdevs, pci);
 
     return -1;
@@ -5643,39 +5740,50 @@ error:
 static int qemudDomainAttachHostUsbDevice(virConnectPtr conn,
                                           struct qemud_driver *driver,
                                           virDomainObjPtr vm,
-                                          virDomainHostdevDefPtr hostdev)
+                                          virDomainHostdevDefPtr hostdev,
+                                          int qemuCmdFlags)
 {
     int ret;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    char *devstr = NULL;
+
+    if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
+        !(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
+        goto error;
 
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
         virReportOOMError(conn);
-        return -1;
+        goto error;
     }
 
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
-    if (hostdev->source.subsys.u.usb.vendor) {
-        ret = qemuMonitorAddUSBDeviceMatch(priv->mon,
-                                           hostdev->source.subsys.u.usb.vendor,
-                                           hostdev->source.subsys.u.usb.product);
-    } else {
+    if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
+        ret = qemuMonitorAddDevice(priv->mon, devstr);
+    else
         ret = qemuMonitorAddUSBDeviceExact(priv->mon,
                                            hostdev->source.subsys.u.usb.bus,
                                            hostdev->source.subsys.u.usb.device);
-    }
     qemuDomainObjExitMonitorWithDriver(driver, vm);
+    if (ret < 0)
+        goto error;
 
-    if (ret == 0)
-        vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
+    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
 
-    return ret;
+    VIR_FREE(devstr);
+
+    return 0;
+
+error:
+    VIR_FREE(devstr);
+    return -1;
 }
 
 
 static int qemudDomainAttachHostDevice(virConnectPtr conn,
                                        struct qemud_driver *driver,
                                        virDomainObjPtr vm,
-                                       virDomainHostdevDefPtr hostdev)
+                                       virDomainHostdevDefPtr hostdev,
+                                       int qemuCmdFlags)
 {
     if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
         qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
@@ -5691,12 +5799,14 @@ static int qemudDomainAttachHostDevice(virConnectPtr conn,
 
     switch (hostdev->source.subsys.type) {
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
-        if (qemudDomainAttachHostPciDevice(conn, driver, vm, hostdev) < 0)
+        if (qemudDomainAttachHostPciDevice(conn, driver, vm,
+                                           hostdev, qemuCmdFlags) < 0)
             goto error;
         break;
 
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
-        if (qemudDomainAttachHostUsbDevice(conn, driver, vm, hostdev) < 0)
+        if (qemudDomainAttachHostUsbDevice(conn, driver, vm,
+                                           hostdev, qemuCmdFlags) < 0)
             goto error;
         break;
 
@@ -5787,15 +5897,18 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
 
         case VIR_DOMAIN_DISK_DEVICE_DISK:
             if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
-                ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, driver, vm, dev->data.disk);
+                ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, driver, vm,
+                                                            dev->data.disk, qemuCmdFlags);
                 if (ret == 0)
                     dev->data.disk = NULL;
             } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
-                ret = qemudDomainAttachPciDiskDevice(dom->conn, driver, vm, dev->data.disk);
+                ret = qemudDomainAttachPciDiskDevice(dom->conn, driver, vm,
+                                                     dev->data.disk, qemuCmdFlags);
                 if (ret == 0)
                     dev->data.disk = NULL;
             } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
-                ret = qemudDomainAttachSCSIDisk(dom->conn, driver, vm, dev->data.disk, qemuCmdFlags);
+                ret = qemudDomainAttachSCSIDisk(dom->conn, driver, vm,
+                                                dev->data.disk, qemuCmdFlags);
                 if (ret == 0)
                     dev->data.disk = NULL;
             } else {
@@ -5818,7 +5931,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
         }
     } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) {
         if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
-            ret = qemudDomainAttachPciControllerDevice(dom->conn, driver, vm, dev->data.controller);
+            ret = qemudDomainAttachPciControllerDevice(dom->conn, driver, vm,
+                                                       dev->data.controller, qemuCmdFlags);
         } else {
             qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
                              _("disk controller bus '%s' cannot be hotplugged."),
@@ -5826,11 +5940,13 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
             /* fallthrough */
         }
     } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
-        ret = qemudDomainAttachNetDevice(dom->conn, driver, vm, dev->data.net, qemuCmdFlags);
+        ret = qemudDomainAttachNetDevice(dom->conn, driver, vm,
+                                         dev->data.net, qemuCmdFlags);
         if (ret == 0)
             dev->data.net = NULL;
     } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
-        ret = qemudDomainAttachHostDevice(dom->conn, driver, vm, dev->data.hostdev);
+        ret = qemudDomainAttachHostDevice(dom->conn, driver, vm,
+                                          dev->data.hostdev, qemuCmdFlags);
         if (ret == 0)
             dev->data.hostdev = NULL;
     } else {
-- 
1.6.5.2




More information about the libvir-list mailing list