qemu: Rollback on used USB devices

One of our latest USB device handling patches
05abd1507d introduced a regression.
That is, we first create a temporary list of all USB devices that
are to be used by domain just starting up. Then we iterate over and
check if a device from the list is in the global list of currently
assigned devices (activeUsbHostdevs). If not, we add it there and
continue with next iteration then. But if a device from temporary
list is either taken already or adding to the activeUsbHostdevs fails,
we remove all devices in temp list from the activeUsbHostdevs list.
Therefore, if a device is already taken we remove it from
activeUsbHostdevs even if we should not. Thus, next time we allow
the device to be assigned to another domain.
(cherry picked from commit 2f5fdc886e)
This commit is contained in:
Michal Privoznik 2012-05-16 16:42:02 +02:00 committed by Cole Robinson
parent f9ff58276f
commit 5b66c62d47

View File

@ -567,7 +567,7 @@ qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
const char *name,
usbDeviceList *list)
{
int i;
int i, j;
unsigned int count;
usbDevice *tmp;
@ -586,7 +586,7 @@ qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
qemuReportError(VIR_ERR_OPERATION_INVALID,
_("USB device %s is already in use"),
usbDeviceGetName(tmp));
return -1;
goto error;
}
usbDeviceSetUsedBy(usb, name);
@ -598,9 +598,16 @@ qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
* perform rollback on failure.
*/
if (usbDeviceListAdd(driver->activeUsbHostdevs, usb) < 0)
return -1;
goto error;
}
return 0;
error:
for (j = 0; j < i; j++) {
tmp = usbDeviceListGet(list, i);
usbDeviceListSteal(driver->activeUsbHostdevs, tmp);
}
return -1;
}
static int
@ -621,8 +628,7 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver,
if (!(list = usbDeviceListNew()))
goto cleanup;
/* Loop 1: build temporary list and validate no usb device
* is already taken
/* Loop 1: build temporary list
*/
for (i = 0 ; i < nhostdevs ; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i];
@ -678,7 +684,7 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver,
* wrong, perform rollback.
*/
if (qemuPrepareHostdevUSBDevices(driver, def->name, list) < 0)
goto inactivedevs;
goto cleanup;
/* Loop 2: Temporary list was successfully merged with
* driver list, so steal all items to avoid freeing them
@ -690,16 +696,6 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver,
}
ret = 0;
goto cleanup;
inactivedevs:
/* Steal devices from driver->activeUsbHostdevs.
* We will free them later.
*/
for (i = 0; i < usbDeviceListCount(list); i++) {
tmp = usbDeviceListGet(list, i);
usbDeviceListSteal(driver->activeUsbHostdevs, tmp);
}
cleanup:
usbDeviceListFree(list);