mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-13 08:05:16 +00:00
Support hot-unplug for USB devices in QEMU
Previously hot-unplug could not be supported for USB devices in QEMU, since usb_del required the guest visible address which libvirt never knows. With 'device_del' command we can now unplug based on device alias, so support that. * src/qemu/qemu_driver.c: Use device_del to remove USB devices
This commit is contained in:
parent
b70a1f455c
commit
8c82479d83
@ -7001,9 +7001,81 @@ static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qemudDomainDetachHostUsbDevice(struct qemud_driver *driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainDeviceDefPtr dev,
|
||||||
|
unsigned long long qemuCmdFlags)
|
||||||
|
{
|
||||||
|
virDomainHostdevDefPtr detach = NULL;
|
||||||
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
for (i = 0 ; i < vm->def->nhostdevs ; i++) {
|
||||||
|
if (vm->def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
|
||||||
|
vm->def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unsigned bus = vm->def->hostdevs[i]->source.subsys.u.usb.bus;
|
||||||
|
unsigned device = vm->def->hostdevs[i]->source.subsys.u.usb.device;
|
||||||
|
|
||||||
|
if (dev->data.hostdev->source.subsys.u.usb.bus == bus &&
|
||||||
|
dev->data.hostdev->source.subsys.u.usb.device == device) {
|
||||||
|
detach = vm->def->hostdevs[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!detach) {
|
||||||
|
qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
|
_("host usb device %03d.%03d not found"),
|
||||||
|
dev->data.hostdev->source.subsys.u.usb.bus,
|
||||||
|
dev->data.hostdev->source.subsys.u.usb.device);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!detach->info.alias) {
|
||||||
|
qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
|
"%s", _("device cannot be detached without a device alias"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
|
||||||
|
qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
|
"%s", _("device cannot be detached with this QEMU version"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemuDomainObjEnterMonitorWithDriver(driver, vm);
|
||||||
|
if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
|
||||||
|
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
if (vm->def->nhostdevs > 1) {
|
||||||
|
memmove(vm->def->hostdevs + i,
|
||||||
|
vm->def->hostdevs + i + 1,
|
||||||
|
sizeof(*vm->def->hostdevs) *
|
||||||
|
(vm->def->nhostdevs - (i + 1)));
|
||||||
|
vm->def->nhostdevs--;
|
||||||
|
if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs) < 0) {
|
||||||
|
/* ignore, harmless */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VIR_FREE(vm->def->hostdevs);
|
||||||
|
vm->def->nhostdevs = 0;
|
||||||
|
}
|
||||||
|
virDomainHostdevDefFree(detach);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int qemudDomainDetachHostDevice(struct qemud_driver *driver,
|
static int qemudDomainDetachHostDevice(struct qemud_driver *driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainDeviceDefPtr dev)
|
virDomainDeviceDefPtr dev,
|
||||||
|
unsigned long long qemuCmdFlags)
|
||||||
{
|
{
|
||||||
virDomainHostdevDefPtr hostdev = dev->data.hostdev;
|
virDomainHostdevDefPtr hostdev = dev->data.hostdev;
|
||||||
int ret;
|
int ret;
|
||||||
@ -7019,6 +7091,9 @@ static int qemudDomainDetachHostDevice(struct qemud_driver *driver,
|
|||||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
||||||
ret = qemudDomainDetachHostPciDevice(driver, vm, dev);
|
ret = qemudDomainDetachHostPciDevice(driver, vm, dev);
|
||||||
break;
|
break;
|
||||||
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
||||||
|
ret = qemudDomainDetachHostUsbDevice(driver, vm, dev, qemuCmdFlags);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
qemuReportError(VIR_ERR_NO_SUPPORT,
|
qemuReportError(VIR_ERR_NO_SUPPORT,
|
||||||
_("hostdev subsys type '%s' not supported"),
|
_("hostdev subsys type '%s' not supported"),
|
||||||
@ -7088,7 +7163,7 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
|
|||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
}
|
}
|
||||||
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
|
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
|
||||||
ret = qemudDomainDetachHostDevice(driver, vm, dev);
|
ret = qemudDomainDetachHostDevice(driver, vm, dev, qemuCmdFlags);
|
||||||
} else {
|
} else {
|
||||||
qemuReportError(VIR_ERR_NO_SUPPORT,
|
qemuReportError(VIR_ERR_NO_SUPPORT,
|
||||||
"%s", _("This type of device cannot be hot unplugged"));
|
"%s", _("This type of device cannot be hot unplugged"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user