[libvirt] [PATCH v3 8/9] qemu: Implement RNG device hotplug on live level

Luyao Huang lhuang at redhat.com
Sat Jan 17 05:09:37 UTC 2015


We have enough patches for hotplug RNG device, maybe we can
implement live hotplug of a RNG device.

Signed-off-by: Luyao Huang <lhuang at redhat.com>
---
 src/qemu/qemu_driver.c  |   8 +++-
 src/qemu/qemu_hotplug.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_hotplug.h |   3 ++
 3 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9eed81d..28fbf15 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6976,6 +6976,13 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
             dev->data.chr = NULL;
         break;
 
+    case VIR_DOMAIN_DEVICE_RNG:
+        ret = qemuDomainAttachRNGDevice(driver, vm,
+                                        dev->data.rng);
+        if (!ret)
+            dev->data.rng = NULL;
+        break;
+
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_FS:
     case VIR_DOMAIN_DEVICE_INPUT:
@@ -6987,7 +6994,6 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
     case VIR_DOMAIN_DEVICE_SMARTCARD:
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
     case VIR_DOMAIN_DEVICE_NVRAM:
-    case VIR_DOMAIN_DEVICE_RNG:
     case VIR_DOMAIN_DEVICE_SHMEM:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 6f62345..c20a4ee 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1510,6 +1510,112 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
     return ret;
 }
 
+int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
+                              virDomainObjPtr vm,
+                              virDomainRNGDefPtr rng)
+{
+    int ret = -1;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainDefPtr vmdef = vm->def;
+    char *devstr = NULL;
+    char *charAlias = NULL;
+    char *objAlias = NULL;
+    bool remove_chardev = false;
+    bool releaseaddr = false;
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("qemu does not support -device"));
+        return ret;
+    }
+
+    if (rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM &&
+        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_RANDOM)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("this qemu doesn't support the rng-random "
+                         "backend"));
+        return ret;
+    } else if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
+               !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_EGD)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("this qemu doesn't support the rng-egd "
+                         "backend"));
+        return ret;
+    }
+
+    if (qemuAssignDeviceRNGAlias(vmdef, rng, -1) < 0)
+        return ret;
+
+    if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+        if (STRPREFIX(vm->def->os.machine, "s390-ccw") &&
+            virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) {
+            rng->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
+        } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) {
+            rng->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390;
+        }
+    }
+
+    if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
+        rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+        if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &rng->info) < 0)
+            return ret;
+    } else if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+        if (virDomainCCWAddressAssign(&rng->info, priv->ccwaddrs,
+                                      !rng->info.addr.ccw.assigned) < 0)
+            return ret;
+    }
+    releaseaddr = true;
+    if (!(devstr = qemuBuildRNGDevStr(vmdef, rng, priv->qemuCaps)))
+        goto cleanup;
+
+    if (virAsprintf(&objAlias, "obj%s", rng->info.alias) < 0)
+        goto cleanup;
+
+    if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD) {
+        if (virAsprintf(&charAlias, "char%s", rng->info.alias) < 0)
+            goto cleanup;
+
+        qemuDomainObjEnterMonitor(driver, vm);
+        if (qemuMonitorAttachCharDev(priv->mon, charAlias, rng->source.chardev) < 0) {
+            qemuDomainObjExitMonitor(driver, vm);
+            goto audit;
+        }
+        remove_chardev = true;
+    } else {
+        qemuDomainObjEnterMonitor(driver, vm);
+    }
+
+    if (qemuMonitorAttachRNGDev(priv->mon, charAlias, objAlias, rng) < 0) {
+        if (remove_chardev)
+            qemuMonitorDetachCharDev(priv->mon, charAlias);
+        qemuDomainObjExitMonitor(driver, vm);
+        goto audit;
+    }
+
+    if (devstr && qemuMonitorAddDevice(priv->mon, devstr) < 0) {
+        qemuMonitorDetachRNGDev(priv->mon, objAlias);
+        if (remove_chardev)
+            qemuMonitorDetachCharDev(priv->mon, charAlias);
+        qemuDomainObjExitMonitor(driver, vm);
+        goto audit;
+    }
+    qemuDomainObjExitMonitor(driver, vm);
+
+    if (virDomainRNGInsert(vmdef, rng) < 0)
+        goto audit;
+
+    ret = 0;
+ audit:
+    virDomainAuditRNG(vm, NULL, rng, "attach", ret == 0);
+ cleanup:
+    if (releaseaddr)
+        qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL);
+    VIR_FREE(charAlias);
+    VIR_FREE(objAlias);
+    VIR_FREE(devstr);
+    return ret;
+}
+
 static int
 qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index d13c532..d66853b 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -98,6 +98,9 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
 int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               virDomainChrDefPtr chr);
+int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
+                              virDomainObjPtr vm,
+                              virDomainRNGDefPtr rng);
 
 
 int
-- 
1.8.3.1




More information about the libvir-list mailing list