Пример #1
0
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;
}
Пример #2
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;
}