[libvirt] [PATCH v2 10/21] qemu: Prepare hostdevs when starting a domain

Michal Privoznik mprivozn at redhat.com
Wed Dec 7 08:36:17 UTC 2016


When starting a domain and separate mount namespace is used, we
have to create all the /dev entries that are configured for the
domain.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/qemu/qemu_domain.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 161 insertions(+)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 2d9b2d647..c6c3cb377 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6909,6 +6909,164 @@ qemuDomainSetupAllDisks(virQEMUDriverPtr driver,
 }
 
 
+static int
+qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,
+                         char **path)
+{
+    int ret = -1;
+    virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
+    virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
+    virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
+    virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host;
+    virPCIDevicePtr pci = NULL;
+    virUSBDevicePtr usb = NULL;
+    virSCSIDevicePtr scsi = NULL;
+    virSCSIVHostDevicePtr host = NULL;
+    char *tmpPath = NULL;
+    bool freeTmpPath = false;
+
+    *path = NULL;
+
+    switch ((virDomainHostdevMode) dev->mode) {
+    case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
+        switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+            if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+                pci = virPCIDeviceNew(pcisrc->addr.domain,
+                                      pcisrc->addr.bus,
+                                      pcisrc->addr.slot,
+                                      pcisrc->addr.function);
+                if (!pci)
+                    goto cleanup;
+
+                if (!(tmpPath = virPCIDeviceGetIOMMUGroupDev(pci)))
+                    goto cleanup;
+                freeTmpPath = true;
+            }
+            break;
+
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+            if (dev->missing)
+                break;
+            usb = virUSBDeviceNew(usbsrc->bus,
+                                  usbsrc->device,
+                                  NULL);
+            if (!usb)
+                goto cleanup;
+
+            if (!(tmpPath = (char *) virUSBDeviceGetPath(usb)))
+                goto cleanup;
+            break;
+
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+            if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
+                virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
+                /* Follow qemuSetupDiskCgroup() and qemuSetImageCgroupInternal()
+                 * which does nothing for non local storage
+                 */
+                VIR_DEBUG("Not updating /dev for hostdev iSCSI path '%s'", iscsisrc->path);
+            } else {
+                virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
+                scsi = virSCSIDeviceNew(NULL,
+                                        scsihostsrc->adapter,
+                                        scsihostsrc->bus,
+                                        scsihostsrc->target,
+                                        scsihostsrc->unit,
+                                        dev->readonly,
+                                        dev->shareable);
+
+                if (!scsi)
+                    goto cleanup;
+
+                if (!(tmpPath = (char *) virSCSIDeviceGetPath(scsi)))
+                    goto cleanup;
+            }
+            break;
+
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: {
+            if (hostsrc->protocol ==
+                VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) {
+                if (!(host = virSCSIVHostDeviceNew(hostsrc->wwpn)))
+                    goto cleanup;
+
+                if (!(tmpPath = (char *) virSCSIVHostDeviceGetPath(host)))
+                    goto cleanup;
+            }
+            break;
+        }
+
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
+            break;
+        }
+        break;
+
+    case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
+    case VIR_DOMAIN_HOSTDEV_MODE_LAST:
+        /* nada */
+        break;
+    }
+
+    if (VIR_STRDUP(*path, tmpPath) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virPCIDeviceFree(pci);
+    virUSBDeviceFree(usb);
+    virSCSIDeviceFree(scsi);
+    virSCSIVHostDeviceFree(host);
+    if (freeTmpPath)
+        VIR_FREE(tmpPath);
+    return ret;
+}
+
+
+static int
+qemuDomainSetupHostdev(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
+                       virDomainHostdevDefPtr dev,
+                       const char *devPath)
+{
+    int ret = -1;
+    char *path = NULL;
+
+    if (qemuDomainGetHostdevPath(dev, &path) < 0)
+        goto cleanup;
+
+    if (!path) {
+        /* There's no /dev device that we need to create. Claim success. */
+        ret = 0;
+        goto cleanup;
+    }
+
+    if (qemuDomainCreateDevice(path, devPath, false) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(path);
+    return ret;
+}
+
+
+static int
+qemuDomainSetupAllHostdevs(virQEMUDriverPtr driver,
+                           virDomainObjPtr vm,
+                           const char *devPath)
+{
+    size_t i;
+
+    VIR_DEBUG("Setting up hostdevs");
+    for (i = 0; i < vm->def->nhostdevs; i++) {
+        if (qemuDomainSetupHostdev(driver,
+                                   vm->def->hostdevs[i],
+                                   devPath) < 0)
+            return -1;
+    }
+    VIR_DEBUG("Setup all hostdevs");
+    return 0;
+}
+
+
 int
 qemuDomainBuildNamespace(virQEMUDriverPtr driver,
                          virDomainObjPtr vm)
@@ -6944,6 +7102,9 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
     if (qemuDomainSetupAllDisks(driver, vm, devPath) < 0)
         goto cleanup;
 
+    if (qemuDomainSetupAllHostdevs(driver, vm, devPath) < 0)
+        goto cleanup;
+
     if (mount(devPath, "/dev", NULL, mount_flags, NULL) < 0) {
         virReportSystemError(errno,
                              _("Failed to mount %s on /dev"),
-- 
2.11.0




More information about the libvir-list mailing list