We have enough patches for hotunplug RNG device, maybe we can
implement live hotunplug of a RNG device.
Signed-off-by: Luyao Huang <lhuang(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 4 +-
src/qemu/qemu_hotplug.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_hotplug.h | 4 +-
4 files changed, 103 insertions(+), 3 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4947401..a1a72e3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -377,6 +377,7 @@ virDomainPMSuspendedReasonTypeToString;
virDomainRedirdevBusTypeFromString;
virDomainRedirdevBusTypeToString;
virDomainRNGBackendTypeToString;
+virDomainRNGDefFree;
virDomainRNGEquals;
virDomainRNGFind;
virDomainRNGInsert;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f9d404b..86bed7e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7033,6 +7033,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:
@@ -7043,7 +7046,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 afa9618..60b1818 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2930,6 +2930,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,
@@ -2953,6 +2999,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:
@@ -2967,7 +3016,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:
@@ -3839,3 +3887,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