From bc9ffafcc776fd84bb0bdaa7e621572e48e81841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Wed, 4 Oct 2017 11:09:27 +0200 Subject: [PATCH] qemu: implement input device hotplug For both virtio input devices and USB input devices. https://bugzilla.redhat.com/show_bug.cgi?id=1379603 --- src/libvirt_private.syms | 2 ++ src/qemu/qemu_driver.c | 9 ++++- src/qemu/qemu_hotplug.c | 73 ++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_hotplug.h | 5 +++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 3246cfbba1..3456439159 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -157,6 +157,7 @@ virDomainAuditDisk; virDomainAuditFS; virDomainAuditHostdev; virDomainAuditInit; +virDomainAuditInput; virDomainAuditIOThread; virDomainAuditMemory; virDomainAuditNet; @@ -386,6 +387,7 @@ virDomainHubTypeFromString; virDomainHubTypeToString; virDomainHypervTypeFromString; virDomainHypervTypeToString; +virDomainInputBusTypeToString; virDomainInputDefFind; virDomainInputDefFree; virDomainIOMMUModelTypeFromString; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a9724f0098..51880fc12a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7664,9 +7664,16 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, } break; + case VIR_DOMAIN_DEVICE_INPUT: + ret = qemuDomainAttachInputDevice(driver, vm, dev->data.input); + if (ret == 0) { + alias = dev->data.input->info.alias; + dev->data.input = NULL; + } + break; + case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_FS: - case VIR_DOMAIN_DEVICE_INPUT: case VIR_DOMAIN_DEVICE_SOUND: case VIR_DOMAIN_DEVICE_VIDEO: case VIR_DOMAIN_DEVICE_GRAPHICS: diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index c65e7e5001..b32acb71e1 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2905,6 +2905,79 @@ qemuDomainAttachWatchdog(virQEMUDriverPtr driver, } +int +qemuDomainAttachInputDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainInputDefPtr input) +{ + int ret = -1; + char *devstr = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_INPUT, + { .input = input } }; + bool releaseaddr = false; + + if (input->bus != VIR_DOMAIN_INPUT_BUS_USB && + input->bus != VIR_DOMAIN_INPUT_BUS_VIRTIO) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("input device on bus '%s' cannot be hot plugged."), + virDomainInputBusTypeToString(input->bus)); + return -1; + } + + if (input->bus == VIR_DOMAIN_INPUT_BUS_VIRTIO) { + if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev, "input") < 0) + return -1; + } else if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) { + if (priv->usbaddrs) { + if (virDomainUSBAddressEnsure(priv->usbaddrs, &input->info) < 0) + goto cleanup; + releaseaddr = true; + } + } + + if (qemuAssignDeviceInputAlias(vm->def, input, -1) < 0) + goto cleanup; + + if (qemuBuildInputDevStr(&devstr, vm->def, input, priv->qemuCaps) < 0) + goto cleanup; + + if (VIR_REALLOC_N(vm->def->inputs, vm->def->ninputs + 1) < 0) + goto cleanup; + + qemuDomainObjEnterMonitor(driver, vm); + if (qemuMonitorAddDevice(priv->mon, devstr) < 0) + goto exit_monitor; + + if (qemuDomainObjExitMonitor(driver, vm) < 0) { + releaseaddr = false; + goto cleanup; + } + + VIR_APPEND_ELEMENT_COPY_INPLACE(vm->def->inputs, vm->def->ninputs, input); + + ret = 0; + releaseaddr = false; + + audit: + virDomainAuditInput(vm, input, "attach", ret == 0); + + cleanup: + if (releaseaddr) + qemuDomainReleaseDeviceAddress(vm, &input->info, NULL); + + VIR_FREE(devstr); + return ret; + + exit_monitor: + if (qemuDomainObjExitMonitor(driver, vm) < 0) { + releaseaddr = false; + goto cleanup; + } + goto audit; +} + + static int qemuDomainChangeNetBridge(virDomainObjPtr vm, virDomainNetDefPtr olddev, diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index 3455832d69..985b7495ba 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -125,6 +125,11 @@ int qemuDomainDetachShmemDevice(virQEMUDriverPtr driver, int qemuDomainDetachWatchdog(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainWatchdogDefPtr watchdog); + +int qemuDomainAttachInputDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainInputDefPtr input); + int qemuDomainAttachLease(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainLeaseDefPtr lease);