mirror of https://gitee.com/openkylin/libvirt.git
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;
|
||||
}
|
||||
|
||||
#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,
|
||||
|
@ -3022,6 +3072,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"),
|
||||
|
@ -3214,7 +3271,6 @@ libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
|
|||
virDomainNetDefPtr net;
|
||||
virDomainHostdevDefPtr hostdev;
|
||||
virDomainHostdevDefPtr found;
|
||||
virDomainHostdevSubsysPCIPtr pcisrc;
|
||||
char mac[VIR_MAC_STRING_BUFLEN];
|
||||
|
||||
switch (dev->type) {
|
||||
|
@ -3247,16 +3303,18 @@ 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)
|
||||
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;
|
||||
}
|
||||
|
||||
if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) {
|
||||
pcisrc = &hostdev->source.subsys.u.pci;
|
||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("target pci device %.4x:%.2x:%.2x.%.1x\
|
||||
already exists"),
|
||||
pcisrc->addr.domain, pcisrc->addr.bus,
|
||||
pcisrc->addr.slot, pcisrc->addr.function);
|
||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||
_("device is already in the domain configuration"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -3365,6 +3423,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,
|
||||
|
@ -3383,6 +3511,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);
|
||||
|
|
Loading…
Reference in New Issue