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

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


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

Signed-off-by: Luyao Huang <lhuang at redhat.com>
---
 src/libvirt_private.syms |   1 +
 src/qemu/qemu_driver.c   |   4 +-
 src/qemu/qemu_hotplug.c  | 112 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_hotplug.h  |   4 +-
 4 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d3754af..6c76786 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -378,6 +378,7 @@ virDomainPMSuspendedReasonTypeToString;
 virDomainRedirdevBusTypeFromString;
 virDomainRedirdevBusTypeToString;
 virDomainRNGBackendTypeToString;
+virDomainRNGDefFree;
 virDomainRNGEquals;
 virDomainRNGFind;
 virDomainRNGInsert;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 28fbf15..b3d9613 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7057,6 +7057,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
     case VIR_DOMAIN_DEVICE_CHR:
         ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr);
         break;
+    case VIR_DOMAIN_DEVICE_RNG:
+        ret = qemuDomainDetachRNGDevice(driver, vm, dev->data.rng);
+        break;
     case VIR_DOMAIN_DEVICE_FS:
     case VIR_DOMAIN_DEVICE_INPUT:
     case VIR_DOMAIN_DEVICE_SOUND:
@@ -7067,7 +7070,6 @@ qemuDomainDetachDeviceLive(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_REDIRDEV:
     case VIR_DOMAIN_DEVICE_NONE:
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index c20a4ee..2f90534 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1510,6 +1510,21 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
     return ret;
 }
 
+static virDomainRNGDefPtr
+qemuDomainRNGRemove(virDomainDefPtr vmdef,
+                    virDomainRNGDefPtr rng)
+{
+    virDomainRNGDefPtr ret;
+
+    if (!(ret = virDomainRNGRemove(vmdef, rng))) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("device not present in domain configuration"));
+        return NULL;
+    }
+
+    return ret;
+}
+
 int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               virDomainRNGDefPtr rng)
@@ -2922,6 +2937,52 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
     return ret;
 }
 
+static int
+qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver,
+                          virDomainObjPtr vm,
+                          virDomainRNGDefPtr rng)
+{
+    virObjectEventPtr event;
+    char *charAlias = NULL;
+    char *objAlias = NULL;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    int ret = -1;
+    int rc;
+
+    VIR_DEBUG("Removing RNG device %s from domain %p %s",
+              rng->info.alias, vm, vm->def->name);
+
+    if (virAsprintf(&objAlias, "obj%s", rng->info.alias) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&charAlias, "char%s", rng->info.alias) < 0)
+        goto cleanup;
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    rc = qemuMonitorDetachRNGDev(priv->mon, objAlias);
+    if (rc == 0 && rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD)
+        ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
+    qemuDomainObjExitMonitor(driver, vm);
+
+    virDomainAuditRNG(vm, rng, NULL, "detach", rc == 0);
+
+    if (rc < 0)
+        goto cleanup;
+
+    event = virDomainEventDeviceRemovedNewFromObj(vm, rng->info.alias);
+    if (event)
+        qemuDomainEventQueue(driver, event);
+
+    qemuDomainRNGRemove(vm->def, rng);
+    qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL);
+    virDomainRNGDefFree(rng);
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(charAlias);
+    VIR_FREE(objAlias);
+    return ret;
+}
 
 void
 qemuDomainRemoveDevice(virQEMUDriverPtr driver,
@@ -2945,6 +3006,9 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
     case VIR_DOMAIN_DEVICE_CHR:
         qemuDomainRemoveChrDevice(driver, vm, dev->data.chr);
         break;
+    case VIR_DOMAIN_DEVICE_RNG:
+        qemuDomainRemoveRNGDevice(driver, vm, dev->data.rng);
+        break;
 
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_LEASE:
@@ -2959,7 +3023,6 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
     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:
@@ -3831,3 +3894,50 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
     VIR_FREE(devstr);
     return ret;
 }
+
+int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
+                              virDomainObjPtr vm,
+                              virDomainRNGDefPtr rng)
+{
+    int ret = -1;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainDefPtr vmdef = vm->def;
+    virDomainRNGDefPtr tmpRNG;
+    int rc;
+
+    if (!(tmpRNG = virDomainRNGFind(vmdef, rng))) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("device not present in domain configuration"));
+        return ret;
+    }
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("qemu does not support -device"));
+        return ret;
+    }
+
+    if (!tmpRNG->info.alias && qemuAssignDeviceRNGAlias(vmdef, tmpRNG, -1) < 0)
+        return ret;
+
+    sa_assert(tmpRNG->info.alias);
+
+    qemuDomainMarkDeviceForRemoval(vm, &tmpRNG->info);
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    if (qemuMonitorDelDevice(priv->mon, tmpRNG->info.alias) < 0) {
+        qemuDomainObjExitMonitor(driver, vm);
+        goto cleanup;
+    }
+    qemuDomainObjExitMonitor(driver, vm);
+
+    rc = qemuDomainWaitForDeviceRemoval(vm);
+    if (rc == 0 || rc == 1)
+        ret = qemuDomainRemoveRNGDevice(driver, vm, tmpRNG);
+    else
+        ret = 0;
+
+ cleanup:
+    qemuDomainResetDeviceRemoval(vm);
+    return ret;
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index d66853b..202c5a2 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -101,7 +101,9 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
 int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               virDomainRNGDefPtr rng);
-
+int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
+                              virDomainObjPtr vm,
+                              virDomainRNGDefPtr rng);
 
 int
 qemuDomainChrInsert(virDomainDefPtr vmdef,
-- 
1.8.3.1




More information about the libvir-list mailing list