Chunyan Liu wrote:
Support hot attach/detach a USB host device to guest.
Curretnly libxl only supports xen PV guest, and only
s/Curretnly/Currently/
supports specifying USB host device by 'bus number'
and 'device number'.
Signed-off-by: Chunyan Liu <cyliu(a)suse.com>
---
src/libxl/libxl_driver.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 129 insertions(+), 1 deletion(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 18a0891..8900644 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -3024,6 +3024,55 @@ libxlDomainAttachHostPCIDevice(libxlDriverPrivatePtr driver,
}
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);
Move the init below the check for hostdev->mode and hostdev->source.subsys.type,
otherwise it is not disposed if the check fails.
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+ hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
+ return ret;
+
+ 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 error;
+
+ 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 error;
+ }
+
+ vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
+ ret = 0;
+ goto cleanup;
+
+ error:
I think 'reattach' is a better name for this label.
+ virHostdevReAttachUSBDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
+ vm->def->name, &hostdev, 1);
+
+ cleanup:
+ virObjectUnref(cfg);
+ libxl_device_usbdev_dispose(&usbdev);
+ return ret;
+}
+
+
+static int
libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
@@ -3041,6 +3090,11 @@ libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
return -1;
break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ if (libxlDomainAttachHostUSBDevice(driver, vm, hostdev) < 0)
+ return -1;
+ break;
+
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("hostdev subsys type '%s' not supported"),
@@ -3266,7 +3320,8 @@ 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_USB ||
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI))
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB ||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
return -1;
if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) {
@@ -3385,6 +3440,76 @@ libxlDomainDetachHostPCIDevice(libxlDriverPrivatePtr driver,
}
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"),
Space after Busnum, but not Devnum.
+ 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"),
Same here.
+ 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"),
And here.
+ usbsrc->bus, usbsrc->device);
+ goto error;
+ }
+
+ virDomainHostdevRemove(vm->def, idx);
+
+ virHostdevReAttachUSBDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
+ vm->def->name, &hostdev, 1);
+
+ ret = 0;
+
+ error:
+ virDomainHostdevDefFree(detach);
The error label will be hit on success of the function. Should
virDomainHostdevDefFree() be called in 'cleanup' and 'error' dropped?
Regards,
Jim
+
+ cleanup:
+ virObjectUnref(cfg);
+ libxl_device_usbdev_dispose(&usbdev);
+ return ret;
+}
+
+static int
libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
@@ -3402,6 +3527,9 @@ libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
return libxlDomainDetachHostPCIDevice(driver, vm, hostdev);
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ return libxlDomainDetachHostUSBDevice(driver, vm, hostdev);
+
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected hostdev type %d"), subsys->type);