qemu: implement input device hotunplug

Allow unplugging USB and virtio USB devices.

https://bugzilla.redhat.com/show_bug.cgi?id=1379603
This commit is contained in:
Ján Tomko 2017-10-17 16:44:24 +02:00
parent bc9ffafcc7
commit 67486bb295
3 changed files with 82 additions and 1 deletions

View File

@ -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:

View File

@ -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;
}

View File

@ -184,4 +184,7 @@ int qemuDomainSetVcpuInternal(virQEMUDriverPtr driver,
virBitmapPtr vcpus,
bool state);
int qemuDomainDetachInputDevice(virDomainObjPtr vm,
virDomainInputDefPtr def);
#endif /* __QEMU_HOTPLUG_H__ */