Support hot attach/detach a USB host device to guest. Curretnly libxl only supports xen PV guest, and only supports specifying USB host device by 'bus number' and 'device number'. For example: usb.xml: <hostdev mode='subsystem' type='usb' managed='no'> <source> <address bus='1' device='3'/> </source> </hostdev> #xl attach-device dom usb.xml #xl detach-device dom usb.xml Signed-off-by: Chunyan Liu <cyliu@xxxxxxxx> --- Changes: * add LIBXL_HAVE_PVUSB check * fix Jim's comments src/libxl/libxl_driver.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 1 deletion(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 960673f..a171efe 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -3028,6 +3028,56 @@ libxlDomainAttachHostPCIDevice(libxlDriverPrivatePtr driver, return ret; } +#ifdef LIBXL_HAVE_PVUSB +static int +libxlDomainAttachHostUSBDevice(libxlDriverPrivatePtr driver, + virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev) +{ + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + libxl_device_usbdev usbdev; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + int ret = -1; + + libxl_device_usbdev_init(&usbdev); + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + goto cleanup; + + if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0) + goto cleanup; + + if (virHostdevPrepareUSBDevices(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def->name, &hostdev, 1, 0) < 0) + goto cleanup; + + if (libxlMakeUSB(hostdev, &usbdev) < 0) + goto reattach; + + if (libxl_device_usbdev_add(cfg->ctx, vm->def->id, &usbdev, 0) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to attach usb device Busnum:%3x, Devnum:%3x"), + hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device); + goto reattach; + } + + vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; + ret = 0; + goto cleanup; + + reattach: + virHostdevReAttachUSBDevices(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def->name, &hostdev, 1); + + cleanup: + virObjectUnref(cfg); + libxl_device_usbdev_dispose(&usbdev); + return ret; +} +#endif + static int libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver, virDomainObjPtr vm, @@ -3046,6 +3096,13 @@ libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver, return -1; break; +#ifdef LIBXL_HAVE_PVUSB + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: + if (libxlDomainAttachHostUSBDevice(driver, vm, hostdev) < 0) + return -1; + break; +#endif + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("hostdev subsys type '%s' not supported"), @@ -3271,7 +3328,9 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) case VIR_DOMAIN_DEVICE_HOSTDEV: hostdev = dev->data.hostdev; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + if (hostdev->source.subsys.type != + (VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI || + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)) return -1; if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) { @@ -3389,6 +3448,76 @@ libxlDomainDetachHostPCIDevice(libxlDriverPrivatePtr driver, return ret; } +#ifdef LIBXL_HAVE_PVUSB +static int +libxlDomainDetachHostUSBDevice(libxlDriverPrivatePtr driver, + virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev) +{ + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys; + virDomainHostdevSubsysUSBPtr usbsrc = &subsys->u.usb; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + libxl_device_usbdev usbdev; + libxl_device_usbdev *usbdevs = NULL; + int num = 0; + virDomainHostdevDefPtr detach; + int idx; + size_t i; + bool found = false; + int ret = -1; + + libxl_device_usbdev_init(&usbdev); + + idx = virDomainHostdevFind(vm->def, hostdev, &detach); + if (idx < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("host USB device Busnum: %3x, Devnum: %3x not found"), + usbsrc->bus, usbsrc->device); + goto cleanup; + } + + usbdevs = libxl_device_usbdev_list(cfg->ctx, vm->def->id, &num); + for (i = 0; i < num; i++) { + if (usbdevs[i].u.hostdev.hostbus == usbsrc->bus && + usbdevs[i].u.hostdev.hostaddr == usbsrc->device) { + libxl_device_usbdev_copy(cfg->ctx, &usbdev, &usbdevs[i]); + found = true; + break; + } + } + libxl_device_usbdev_list_free(usbdevs, num); + + if (!found) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("host USB device Busnum: %3x, Devnum: %3x not found"), + usbsrc->bus, usbsrc->device); + goto cleanup; + } + + if (libxl_device_usbdev_remove(cfg->ctx, vm->def->id, &usbdev, 0) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to detach USB device\ + Busnum: %3x, Devnum: %3x"), + usbsrc->bus, usbsrc->device); + goto cleanup; + } + + virDomainHostdevRemove(vm->def, idx); + + virHostdevReAttachUSBDevices(hostdev_mgr, LIBXL_DRIVER_NAME, + vm->def->name, &hostdev, 1); + + ret = 0; + + cleanup: + virDomainHostdevDefFree(detach); + virObjectUnref(cfg); + libxl_device_usbdev_dispose(&usbdev); + return ret; +} +#endif + static int libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver, virDomainObjPtr vm, @@ -3407,6 +3536,11 @@ libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver, case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: return libxlDomainDetachHostPCIDevice(driver, vm, hostdev); +#ifdef LIBXL_HAVE_PVUSB + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: + return libxlDomainDetachHostUSBDevice(driver, vm, hostdev); +#endif + default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected hostdev type %d"), subsys->type); -- 2.1.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list