mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
qemu: Implement support for hotplugging evdev input devices
Unlike other input types, evdev is not a true device since it's backed by '-object'. We must use object-add/object-del monitor commands instead of device-add/device-del in this particular case. This patch adds support for handling live attachment and detachment of evdev type devices. Resolves: https://gitlab.com/libvirt/libvirt/-/issues/529 Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
94108cdd59
commit
57f29f675d
@ -4367,7 +4367,7 @@ qemuBuildInputUSBDevProps(const virDomainDef *def,
|
||||
}
|
||||
|
||||
|
||||
static virJSONValue *
|
||||
virJSONValue *
|
||||
qemuBuildInputEvdevProps(virDomainInputDef *dev)
|
||||
{
|
||||
g_autoptr(virJSONValue) props = NULL;
|
||||
|
@ -233,6 +233,9 @@ virJSONValue *
|
||||
qemuBuildInputUSBDevProps(const virDomainDef *def,
|
||||
virDomainInputDef *dev);
|
||||
|
||||
virJSONValue *
|
||||
qemuBuildInputEvdevProps(virDomainInputDef *dev);
|
||||
|
||||
virJSONValue *
|
||||
qemuBuildVsockDevProps(virDomainDef *def,
|
||||
virDomainVsockDef *vsock,
|
||||
|
@ -3016,36 +3016,40 @@ qemuDomainAttachInputDevice(virDomainObj *vm,
|
||||
bool teardowncgroup = false;
|
||||
|
||||
qemuAssignDeviceInputAlias(vm->def, input, -1);
|
||||
if (input->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) {
|
||||
if (!(devprops = qemuBuildInputEvdevProps(input)))
|
||||
goto cleanup;
|
||||
} else {
|
||||
switch ((virDomainInputBus) input->bus) {
|
||||
case VIR_DOMAIN_INPUT_BUS_USB:
|
||||
if (virDomainUSBAddressEnsure(priv->usbaddrs, &input->info) < 0)
|
||||
return -1;
|
||||
|
||||
switch ((virDomainInputBus) input->bus) {
|
||||
case VIR_DOMAIN_INPUT_BUS_USB:
|
||||
if (virDomainUSBAddressEnsure(priv->usbaddrs, &input->info) < 0)
|
||||
releaseaddr = true;
|
||||
|
||||
if (!(devprops = qemuBuildInputUSBDevProps(vm->def, input)))
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_INPUT_BUS_VIRTIO:
|
||||
if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!(devprops = qemuBuildInputVirtioDevProps(vm->def, input, priv->qemuCaps)))
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_INPUT_BUS_DEFAULT:
|
||||
case VIR_DOMAIN_INPUT_BUS_PS2:
|
||||
case VIR_DOMAIN_INPUT_BUS_XEN:
|
||||
case VIR_DOMAIN_INPUT_BUS_PARALLELS:
|
||||
case VIR_DOMAIN_INPUT_BUS_NONE:
|
||||
case VIR_DOMAIN_INPUT_BUS_LAST:
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||
_("input device on bus '%1$s' cannot be hot plugged."),
|
||||
virDomainInputBusTypeToString(input->bus));
|
||||
return -1;
|
||||
|
||||
releaseaddr = true;
|
||||
|
||||
if (!(devprops = qemuBuildInputUSBDevProps(vm->def, input)))
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_INPUT_BUS_VIRTIO:
|
||||
if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!(devprops = qemuBuildInputVirtioDevProps(vm->def, input, priv->qemuCaps)))
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_INPUT_BUS_DEFAULT:
|
||||
case VIR_DOMAIN_INPUT_BUS_PS2:
|
||||
case VIR_DOMAIN_INPUT_BUS_XEN:
|
||||
case VIR_DOMAIN_INPUT_BUS_PARALLELS:
|
||||
case VIR_DOMAIN_INPUT_BUS_NONE:
|
||||
case VIR_DOMAIN_INPUT_BUS_LAST:
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||
_("input device on bus '%1$s' cannot be hot plugged."),
|
||||
virDomainInputBusTypeToString(input->bus));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (qemuDomainNamespaceSetupInput(vm, input, &teardowndevice) < 0)
|
||||
@ -3066,9 +3070,14 @@ qemuDomainAttachInputDevice(virDomainObj *vm,
|
||||
if (qemuDomainAttachExtensionDevice(priv->mon, &input->info) < 0)
|
||||
goto exit_monitor;
|
||||
|
||||
if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0) {
|
||||
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &input->info));
|
||||
goto exit_monitor;
|
||||
if (input->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) {
|
||||
if (qemuMonitorAddObject(priv->mon, &devprops, NULL) < 0)
|
||||
goto exit_monitor;
|
||||
} else {
|
||||
if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0) {
|
||||
ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &input->info));
|
||||
goto exit_monitor;
|
||||
}
|
||||
}
|
||||
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
@ -6093,6 +6102,29 @@ qemuDomainDetachDeviceLease(virQEMUDriver *driver,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuDomainDetachDeviceInputEvdev(virQEMUDriver *driver,
|
||||
virDomainObj *vm,
|
||||
virDomainDeviceDef *detach)
|
||||
{
|
||||
int rc;
|
||||
virDomainInputDef *input = detach->data.input;
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
|
||||
qemuDomainObjEnterMonitor(vm);
|
||||
rc = qemuMonitorDelObject(priv->mon, input->info.alias, true);
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
|
||||
if (rc < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuDomainRemoveDevice(driver, vm, detach) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuDomainDetachDeviceLive(virDomainObj *vm,
|
||||
virDomainDeviceDef *match,
|
||||
@ -6176,6 +6208,13 @@ qemuDomainDetachDeviceLive(virDomainObj *vm,
|
||||
&detach.data.input) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Input devices of type 'evdev' are regular QOM objects
|
||||
* (-object instead of -device), so it must be handled differently.
|
||||
*/
|
||||
if (detach.data.input->type == VIR_DOMAIN_INPUT_TYPE_EVDEV)
|
||||
return qemuDomainDetachDeviceInputEvdev(driver, vm, &detach);
|
||||
break;
|
||||
case VIR_DOMAIN_DEVICE_REDIRDEV:
|
||||
if (qemuDomainDetachPrepRedirdev(vm, match->data.redirdev,
|
||||
|
Loading…
Reference in New Issue
Block a user