Allow unplugging USB and virtio USB devices.
https://bugzilla.redhat.com/show_bug.cgi?id=1379603
---
src/qemu/qemu_driver.c | 4 ++-
src/qemu/qemu_hotplug.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_hotplug.h | 3 ++
3 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 75a0e42aa..a9d3ba778 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7764,9 +7764,11 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
case VIR_DOMAIN_DEVICE_WATCHDOG:
ret = qemuDomainDetachWatchdog(driver, vm, dev->data.watchdog);
break;
+ case VIR_DOMAIN_DEVICE_INPUT:
+ ret = qemuDomainDetachInputDevice(vm, dev->data.input);
+ break;
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 b32acb71e..85faa2a46 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4430,6 +4430,31 @@ qemuDomainRemoveWatchdog(virQEMUDriverPtr driver,
}
+static int
+qemuDomainRemoveInputDevice(virDomainObjPtr vm,
+ virDomainInputDefPtr dev)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virQEMUDriverPtr driver = priv->driver;
+ virObjectEventPtr event = NULL;
+ size_t i;
+
+ VIR_DEBUG("Removing input device %s from domain %p %s",
+ dev->info.alias, vm, vm->def->name);
+
+ event = virDomainEventDeviceRemovedNewFromObj(vm, dev->info.alias);
+ qemuDomainEventQueue(driver, event);
+ for (i = 0; i < vm->def->ninputs; i++) {
+ if (vm->def->inputs[i] == dev)
+ break;
+ }
+ qemuDomainReleaseDeviceAddress(vm, &dev->info, NULL);
+ virDomainInputDefFree(vm->def->inputs[i]);
+ VIR_DELETE_ELEMENT(vm->def->inputs, i, vm->def->ninputs);
+ return 0;
+}
+
+
int
qemuDomainRemoveDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -6184,3 +6209,54 @@ qemuDomainSetVcpuInternal(virQEMUDriverPtr driver,
virObjectUnref(cfg);
return ret;
}
+
+
+int
+qemuDomainDetachInputDevice(virDomainObjPtr vm,
+ virDomainInputDefPtr def)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virQEMUDriverPtr driver = priv->driver;
+ virDomainInputDefPtr input;
+ int ret = -1;
+ int idx;
+
+ if ((idx = virDomainInputDefFind(vm->def, def)) < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("matching input device not found"));
+ return -1;
+ }
+ input = vm->def->inputs[idx];
+
+ switch ((virDomainInputBus) input->bus) {
+ case VIR_DOMAIN_INPUT_BUS_PS2:
+ case VIR_DOMAIN_INPUT_BUS_XEN:
+ case VIR_DOMAIN_INPUT_BUS_PARALLELS:
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("input device on bus '%s' cannot be
detached"),
+ virDomainInputBusTypeToString(input->bus));
+ return -1;
+
+ case VIR_DOMAIN_INPUT_BUS_LAST:
+ case VIR_DOMAIN_INPUT_BUS_USB:
+ case VIR_DOMAIN_INPUT_BUS_VIRTIO:
+ break;
+ }
+
+ qemuDomainMarkDeviceForRemoval(vm, &input->info);
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ if (qemuMonitorDelDevice(priv->mon, input->info.alias)) {
+ ignore_value(qemuDomainObjExitMonitor(driver, vm));
+ goto cleanup;
+ }
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ goto cleanup;
+
+ if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+ ret = qemuDomainRemoveInputDevice(vm, input);
+
+ cleanup:
+ qemuDomainResetDeviceRemoval(vm);
+ return ret;
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 985b7495b..3e0d618e0 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -184,4 +184,7 @@ int qemuDomainSetVcpuInternal(virQEMUDriverPtr driver,
virBitmapPtr vcpus,
bool state);
+int qemuDomainDetachInputDevice(virDomainObjPtr vm,
+ virDomainInputDefPtr def);
+
#endif /* __QEMU_HOTPLUG_H__ */
--
2.13.0