Since previous patches has prepared everything for us, we may now
implement live hotplug of a character device.
---
src/qemu/qemu_driver.c | 10 +++++
src/qemu/qemu_hotplug.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_hotplug.h | 6 +++
3 files changed, 113 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1900c4a..c7481ea 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5807,6 +5807,13 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
dev->data.redirdev = NULL;
break;
+ case VIR_DOMAIN_DEVICE_CHR:
+ ret = qemuDomainAttachChrDevice(driver, vm,
+ dev->data.chr);
+ if (!ret)
+ dev->data.chr = NULL;
+ break;
+
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("device type '%s' cannot be attached"),
@@ -5894,6 +5901,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
case VIR_DOMAIN_DEVICE_HOSTDEV:
ret = qemuDomainDetachHostDevice(driver, vm, dev);
break;
+ case VIR_DOMAIN_DEVICE_CHR:
+ ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr);
+ break;
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("This type of device cannot be hot
unplugged"));
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index a4f48b0..0535ef6 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1132,6 +1132,63 @@ error:
}
+int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainChrDefPtr chr)
+{
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virDomainDefPtr vmdef = vm->def;
+ char *devstr = NULL;
+ char *charAlias = NULL;
+
+ if (virDomainChrFind(vmdef, chr)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("chardev already exists"));
+ return ret;
+ }
+
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("qemu does not support -device"));
+ return ret;
+ }
+
+ if (qemuAssignDeviceChrAlias(vmdef, chr, -1) < 0)
+ return ret;
+
+ if (qemuBuildChrDeviceStr(&devstr, vm->def, chr, priv->qemuCaps) < 0)
+ return ret;
+
+ if (virAsprintf(&charAlias, "char%s", chr->info.alias) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ if (qemuMonitorAttachCharDev(priv->mon, charAlias, &chr->source) < 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+ goto cleanup;
+ }
+
+ if (devstr && qemuMonitorAddDevice(priv->mon, devstr) < 0) {
+ /* detach associated chardev on error */
+ qemuMonitorDetachCharDev(priv->mon, charAlias);
+ qemuDomainObjExitMonitor(driver, vm);
+ goto cleanup;
+ }
+ qemuDomainObjExitMonitor(driver, vm);
+
+ if (virDomainChrInsert(vmdef, chr) < 0)
+ goto cleanup;
+
+ ret = 0;
+cleanup:
+ VIR_FREE(charAlias);
+ VIR_FREE(devstr);
+ return ret;
+}
+
int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
@@ -2828,3 +2885,43 @@ int qemuDomainDetachLease(virQEMUDriverPtr driver,
virDomainLeaseDefFree(det_lease);
return 0;
}
+
+int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainChrDefPtr chr)
+{
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virDomainDefPtr vmdef = vm->def;
+ virDomainChrDefPtr tmpChr;
+ char *charAlias = NULL;
+
+ if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("device not present in domain configuration"));
+ return ret;
+ }
+
+ if (virAsprintf(&charAlias, "char%s", tmpChr->info.alias) < 0) {
+ virReportOOMError();
+ return ret;
+ }
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ if (qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+ goto cleanup;
+ }
+
+ if (qemuMonitorDetachCharDev(priv->mon, charAlias) < 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+ goto cleanup;
+ }
+ qemuDomainObjExitMonitor(driver, vm);
+
+ ret = virDomainChrRemove(vmdef, tmpChr);
+
+cleanup:
+ VIR_FREE(charAlias);
+ return ret;
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index da20eb1..46cd129 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -104,6 +104,12 @@ int qemuDomainAttachLease(virQEMUDriverPtr driver,
int qemuDomainDetachLease(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainLeaseDefPtr lease);
+int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainChrDefPtr chr);
+int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainChrDefPtr chr);
#endif /* __QEMU_HOTPLUG_H__ */
--
1.8.1.5