mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
libxl: support hotplug USB host device
Support hot attach/detach a USB host device to guest. Currently 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@suse.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com>
This commit is contained in:
parent
2a58ed0bce
commit
fc21d1065b
@ -3004,6 +3004,56 @@ libxlDomainAttachHostPCIDevice(libxlDriverPrivatePtr driver,
|
|||||||
return ret;
|
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
|
static int
|
||||||
libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
|
libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
@ -3022,6 +3072,13 @@ libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
|
|||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef LIBXL_HAVE_PVUSB
|
||||||
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
||||||
|
if (libxlDomainAttachHostUSBDevice(driver, vm, hostdev) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
_("hostdev subsys type '%s' not supported"),
|
_("hostdev subsys type '%s' not supported"),
|
||||||
@ -3214,7 +3271,6 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
|
|||||||
virDomainNetDefPtr net;
|
virDomainNetDefPtr net;
|
||||||
virDomainHostdevDefPtr hostdev;
|
virDomainHostdevDefPtr hostdev;
|
||||||
virDomainHostdevDefPtr found;
|
virDomainHostdevDefPtr found;
|
||||||
virDomainHostdevSubsysPCIPtr pcisrc;
|
|
||||||
char mac[VIR_MAC_STRING_BUFLEN];
|
char mac[VIR_MAC_STRING_BUFLEN];
|
||||||
|
|
||||||
switch (dev->type) {
|
switch (dev->type) {
|
||||||
@ -3247,16 +3303,18 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
|
|||||||
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
||||||
hostdev = dev->data.hostdev;
|
hostdev = dev->data.hostdev;
|
||||||
|
|
||||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
switch (hostdev->source.subsys.type) {
|
||||||
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
|
||||||
|
#ifndef LIBXL_HAVE_PVUSB
|
||||||
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
||||||
|
#endif
|
||||||
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) {
|
if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) {
|
||||||
pcisrc = &hostdev->source.subsys.u.pci;
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
_("device is already in the domain configuration"));
|
||||||
_("target pci device %.4x:%.2x:%.2x.%.1x\
|
|
||||||
already exists"),
|
|
||||||
pcisrc->addr.domain, pcisrc->addr.bus,
|
|
||||||
pcisrc->addr.slot, pcisrc->addr.function);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3365,6 +3423,76 @@ libxlDomainDetachHostPCIDevice(libxlDriverPrivatePtr driver,
|
|||||||
return ret;
|
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
|
static int
|
||||||
libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
|
libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
@ -3383,6 +3511,11 @@ libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
|
|||||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
||||||
return libxlDomainDetachHostPCIDevice(driver, vm, hostdev);
|
return libxlDomainDetachHostPCIDevice(driver, vm, hostdev);
|
||||||
|
|
||||||
|
#ifdef LIBXL_HAVE_PVUSB
|
||||||
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
||||||
|
return libxlDomainDetachHostUSBDevice(driver, vm, hostdev);
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("unexpected hostdev type %d"), subsys->type);
|
_("unexpected hostdev type %d"), subsys->type);
|
||||||
|
Loading…
Reference in New Issue
Block a user