void virUSBDeviceListDel(virUSBDeviceListPtr list, virUSBDevicePtr dev) { virUSBDevicePtr ret = virUSBDeviceListSteal(list, dev); virUSBDeviceFree(ret); }
int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, const char *name, virUSBDeviceListPtr list) { int i, j; unsigned int count; virUSBDevicePtr tmp; virObjectLock(driver->activeUsbHostdevs); count = virUSBDeviceListCount(list); for (i = 0; i < count; i++) { virUSBDevicePtr usb = virUSBDeviceListGet(list, i); if ((tmp = virUSBDeviceListFind(driver->activeUsbHostdevs, usb))) { const char *other_name = virUSBDeviceGetUsedBy(tmp); if (other_name) virReportError(VIR_ERR_OPERATION_INVALID, _("USB device %s is in use by domain %s"), virUSBDeviceGetName(tmp), other_name); else virReportError(VIR_ERR_OPERATION_INVALID, _("USB device %s is already in use"), virUSBDeviceGetName(tmp)); goto error; } virUSBDeviceSetUsedBy(usb, name); VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs", virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), name); /* * The caller is responsible to steal these usb devices * from the virUSBDeviceList that passed in on success, * perform rollback on failure. */ if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) goto error; } virObjectUnlock(driver->activeUsbHostdevs); return 0; error: for (j = 0; j < i; j++) { tmp = virUSBDeviceListGet(list, i); virUSBDeviceListSteal(driver->activeUsbHostdevs, tmp); } virObjectUnlock(driver->activeUsbHostdevs); return -1; }
int virUSBDeviceFind(unsigned int vendor, unsigned int product, unsigned int bus, unsigned int devno, const char *vroot, bool mandatory, virUSBDevicePtr *usb) { virUSBDeviceListPtr list; unsigned int flags = USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BUS; if (!(list = virUSBDeviceSearch(vendor, product, bus, devno, vroot, flags))) return -1; if (list->count == 0) { virObjectUnref(list); if (!mandatory) { VIR_DEBUG("Did not find USB device %x:%x bus:%u device:%u", vendor, product, bus, devno); if (usb) *usb = NULL; return 0; } virReportError(VIR_ERR_INTERNAL_ERROR, _("Did not find USB device %x:%x bus:%u device:%u"), vendor, product, bus, devno); return -1; } if (usb) { *usb = virUSBDeviceListGet(list, 0); virUSBDeviceListSteal(list, *usb); } virObjectUnref(list); return 0; }
int virUSBDeviceFindByBus(unsigned int bus, unsigned int devno, const char *vroot, bool mandatory, virUSBDevicePtr *usb) { virUSBDeviceListPtr list; if (!(list = virUSBDeviceSearch(0, 0, bus, devno, vroot, USB_DEVICE_FIND_BY_BUS))) return -1; if (list->count == 0) { virObjectUnref(list); if (!mandatory) { VIR_DEBUG("Did not find USB device bus:%u device:%u", bus, devno); if (usb) *usb = NULL; return 0; } virReportError(VIR_ERR_INTERNAL_ERROR, _("Did not find USB device bus:%u device:%u"), bus, devno); return -1; } if (usb) { *usb = virUSBDeviceListGet(list, 0); virUSBDeviceListSteal(list, *usb); } virObjectUnref(list); return 0; }
static int virLXCPrepareHostUSBDevices(virLXCDriverPtr driver, virDomainDefPtr def) { size_t i; int ret = -1; virUSBDeviceList *list; virUSBDevicePtr tmp; virDomainHostdevDefPtr *hostdevs = def->hostdevs; int nhostdevs = def->nhostdevs; /* To prevent situation where USB device is assigned to two domains * we need to keep a list of currently assigned USB devices. * This is done in several loops which cannot be joined into one big * loop. See virLXCPrepareHostdevPCIDevices() */ if (!(list = virUSBDeviceListNew())) goto cleanup; /* Loop 1: build temporary list */ for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; bool required = true; virUSBDevicePtr usb; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) continue; if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) continue; if (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_OPTIONAL) required = false; if (virLXCFindHostdevUSBDevice(hostdev, required, &usb) < 0) goto cleanup; if (usb && virUSBDeviceListAdd(list, usb) < 0) { virUSBDeviceFree(usb); goto cleanup; } } /* Mark devices in temporary list as used by @name * and add them do driver list. However, if something goes * wrong, perform rollback. */ if (virLXCPrepareHostdevUSBDevices(driver, def->name, list) < 0) goto cleanup; /* Loop 2: Temporary list was successfully merged with * driver list, so steal all items to avoid freeing them * in cleanup label. */ while (virUSBDeviceListCount(list) > 0) { tmp = virUSBDeviceListGet(list, 0); virUSBDeviceListSteal(list, tmp); } ret = 0; cleanup: virObjectUnref(list); return ret; }
int virLXCFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, bool mandatory, virUSBDevicePtr *usb) { unsigned vendor = hostdev->source.subsys.u.usb.vendor; unsigned product = hostdev->source.subsys.u.usb.product; unsigned bus = hostdev->source.subsys.u.usb.bus; unsigned device = hostdev->source.subsys.u.usb.device; bool autoAddress = hostdev->source.subsys.u.usb.autoAddress; int rc; *usb = NULL; if (vendor && bus) { rc = virUSBDeviceFind(vendor, product, bus, device, NULL, autoAddress ? false : mandatory, usb); if (rc < 0) { return -1; } else if (!autoAddress) { goto out; } else { VIR_INFO("USB device %x:%x could not be found at previous" " address (bus:%u device:%u)", vendor, product, bus, device); } } /* When vendor is specified, its USB address is either unspecified or the * device could not be found at the USB device where it had been * automatically found before. */ if (vendor) { virUSBDeviceList *devs; rc = virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, &devs); if (rc < 0) return -1; if (rc == 1) { *usb = virUSBDeviceListGet(devs, 0); virUSBDeviceListSteal(devs, *usb); } virObjectUnref(devs); if (rc == 0) { goto out; } else if (rc > 1) { if (autoAddress) { virReportError(VIR_ERR_OPERATION_FAILED, _("Multiple USB devices for %x:%x were found," " but none of them is at bus:%u device:%u"), vendor, product, bus, device); } else { virReportError(VIR_ERR_OPERATION_FAILED, _("Multiple USB devices for %x:%x, " "use <address> to specify one"), vendor, product); } return -1; } hostdev->source.subsys.u.usb.bus = virUSBDeviceGetBus(*usb); hostdev->source.subsys.u.usb.device = virUSBDeviceGetDevno(*usb); hostdev->source.subsys.u.usb.autoAddress = true; if (autoAddress) { VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved" " from bus:%u device:%u)", vendor, product, hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device, bus, device); } } else if (!vendor && bus) { if (virUSBDeviceFindByBus(bus, device, NULL, mandatory, usb) < 0) return -1; } out: if (!*usb) hostdev->missing = true; return 0; }