提交 011cf7ad 编写于 作者: D Daniel P. Berrange

Protect USB/PCI device list access in QEMU with dedicated locks

Currently the activePciHostdevs, inactivePciHostdevsd and
activeUsbHostdevs lists are all implicitly protected by the
QEMU driver lock. Now that the lists all inherit from the
virObjectLockable, we can make the locking explicit, removing
the dependency on the QEMU driver lock for correctness.
Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
上级 0f9ef558
...@@ -10034,6 +10034,8 @@ qemuNodeDeviceDettach(virNodeDevicePtr dev) ...@@ -10034,6 +10034,8 @@ qemuNodeDeviceDettach(virNodeDevicePtr dev)
return -1; return -1;
qemuDriverLock(driver); qemuDriverLock(driver);
virObjectLock(driver->activePciHostdevs);
virObjectLock(driver->inactivePciHostdevs);
in_inactive_list = virPCIDeviceListFind(driver->inactivePciHostdevs, pci); in_inactive_list = virPCIDeviceListFind(driver->inactivePciHostdevs, pci);
if (virPCIDeviceDetach(pci, driver->activePciHostdevs, if (virPCIDeviceDetach(pci, driver->activePciHostdevs,
...@@ -10042,6 +10044,8 @@ qemuNodeDeviceDettach(virNodeDevicePtr dev) ...@@ -10042,6 +10044,8 @@ qemuNodeDeviceDettach(virNodeDevicePtr dev)
ret = 0; ret = 0;
out: out:
virObjectUnlock(driver->inactivePciHostdevs);
virObjectUnlock(driver->activePciHostdevs);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
if (in_inactive_list) if (in_inactive_list)
virPCIDeviceFree(pci); virPCIDeviceFree(pci);
...@@ -10064,6 +10068,9 @@ qemuNodeDeviceReAttach(virNodeDevicePtr dev) ...@@ -10064,6 +10068,9 @@ qemuNodeDeviceReAttach(virNodeDevicePtr dev)
if (!pci) if (!pci)
return -1; return -1;
qemuDriverLock(driver);
virObjectLock(driver->activePciHostdevs);
virObjectLock(driver->inactivePciHostdevs);
other = virPCIDeviceListFind(driver->activePciHostdevs, pci); other = virPCIDeviceListFind(driver->activePciHostdevs, pci);
if (other) { if (other) {
const char *other_name = virPCIDeviceGetUsedBy(other); const char *other_name = virPCIDeviceGetUsedBy(other);
...@@ -10076,17 +10083,19 @@ qemuNodeDeviceReAttach(virNodeDevicePtr dev) ...@@ -10076,17 +10083,19 @@ qemuNodeDeviceReAttach(virNodeDevicePtr dev)
virReportError(VIR_ERR_OPERATION_INVALID, virReportError(VIR_ERR_OPERATION_INVALID,
_("PCI device %s is still in use"), _("PCI device %s is still in use"),
virPCIDeviceGetName(pci)); virPCIDeviceGetName(pci));
goto out;
} }
virPCIDeviceReattachInit(pci); virPCIDeviceReattachInit(pci);
qemuDriverLock(driver);
if (virPCIDeviceReattach(pci, driver->activePciHostdevs, if (virPCIDeviceReattach(pci, driver->activePciHostdevs,
driver->inactivePciHostdevs, "pci-stub") < 0) driver->inactivePciHostdevs, "pci-stub") < 0)
goto out; goto out;
ret = 0; ret = 0;
out: out:
virObjectUnlock(driver->inactivePciHostdevs);
virObjectUnlock(driver->activePciHostdevs);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
virPCIDeviceFree(pci); virPCIDeviceFree(pci);
return ret; return ret;
...@@ -10108,6 +10117,8 @@ qemuNodeDeviceReset(virNodeDevicePtr dev) ...@@ -10108,6 +10117,8 @@ qemuNodeDeviceReset(virNodeDevicePtr dev)
return -1; return -1;
qemuDriverLock(driver); qemuDriverLock(driver);
virObjectLock(driver->activePciHostdevs);
virObjectLock(driver->inactivePciHostdevs);
if (virPCIDeviceReset(pci, driver->activePciHostdevs, if (virPCIDeviceReset(pci, driver->activePciHostdevs,
driver->inactivePciHostdevs) < 0) driver->inactivePciHostdevs) < 0)
...@@ -10115,6 +10126,8 @@ qemuNodeDeviceReset(virNodeDevicePtr dev) ...@@ -10115,6 +10126,8 @@ qemuNodeDeviceReset(virNodeDevicePtr dev)
ret = 0; ret = 0;
out: out:
virObjectUnlock(driver->inactivePciHostdevs);
virObjectUnlock(driver->activePciHostdevs);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
virPCIDeviceFree(pci); virPCIDeviceFree(pci);
return ret; return ret;
......
...@@ -72,6 +72,9 @@ qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs) ...@@ -72,6 +72,9 @@ qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs)
return list; return list;
} }
/*
* Pre-condition: driver->activePciHostdevs is locked
*/
static virPCIDeviceListPtr static virPCIDeviceListPtr
qemuGetActivePciHostDeviceList(virQEMUDriverPtr driver, qemuGetActivePciHostDeviceList(virQEMUDriverPtr driver,
virDomainHostdevDefPtr *hostdevs, virDomainHostdevDefPtr *hostdevs,
...@@ -121,10 +124,14 @@ int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, ...@@ -121,10 +124,14 @@ int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver,
{ {
virDomainHostdevDefPtr hostdev = NULL; virDomainHostdevDefPtr hostdev = NULL;
int i; int i;
int ret = -1;
if (!def->nhostdevs) if (!def->nhostdevs)
return 0; return 0;
virObjectLock(driver->activePciHostdevs);
virObjectLock(driver->inactivePciHostdevs);
for (i = 0; i < def->nhostdevs; i++) { for (i = 0; i < def->nhostdevs; i++) {
virPCIDevicePtr dev = NULL; virPCIDevicePtr dev = NULL;
hostdev = def->hostdevs[i]; hostdev = def->hostdevs[i];
...@@ -140,7 +147,7 @@ int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, ...@@ -140,7 +147,7 @@ int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver,
hostdev->source.subsys.u.pci.function); hostdev->source.subsys.u.pci.function);
if (!dev) if (!dev)
return -1; goto cleanup;
virPCIDeviceSetManaged(dev, hostdev->managed); virPCIDeviceSetManaged(dev, hostdev->managed);
virPCIDeviceSetUsedBy(dev, def->name); virPCIDeviceSetUsedBy(dev, def->name);
...@@ -152,11 +159,14 @@ int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver, ...@@ -152,11 +159,14 @@ int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver,
if (virPCIDeviceListAdd(driver->activePciHostdevs, dev) < 0) { if (virPCIDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
virPCIDeviceFree(dev); virPCIDeviceFree(dev);
return -1; goto cleanup;
} }
} }
return 0; cleanup:
virObjectUnlock(driver->activePciHostdevs);
virObjectUnlock(driver->inactivePciHostdevs);
return ret;
} }
int int
...@@ -165,10 +175,12 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, ...@@ -165,10 +175,12 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver,
{ {
virDomainHostdevDefPtr hostdev = NULL; virDomainHostdevDefPtr hostdev = NULL;
int i; int i;
int ret = -1;
if (!def->nhostdevs) if (!def->nhostdevs)
return 0; return 0;
virObjectLock(driver->activeUsbHostdevs);
for (i = 0; i < def->nhostdevs; i++) { for (i = 0; i < def->nhostdevs; i++) {
virUSBDevicePtr usb = NULL; virUSBDevicePtr usb = NULL;
hostdev = def->hostdevs[i]; hostdev = def->hostdevs[i];
...@@ -193,11 +205,13 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, ...@@ -193,11 +205,13 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver,
if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) { if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) {
virUSBDeviceFree(usb); virUSBDeviceFree(usb);
return -1; goto cleanup;
} }
} }
ret = 0;
return 0; cleanup:
virObjectUnlock(driver->activeUsbHostdevs);
return ret;
} }
static int static int
...@@ -412,6 +426,9 @@ int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, ...@@ -412,6 +426,9 @@ int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
int ret = -1; int ret = -1;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virObjectLock(driver->activePciHostdevs);
virObjectLock(driver->inactivePciHostdevs);
if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs))) if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs)))
goto cleanup; goto cleanup;
...@@ -580,19 +597,13 @@ reattachdevs: ...@@ -580,19 +597,13 @@ reattachdevs:
} }
cleanup: cleanup:
virObjectUnlock(driver->activePciHostdevs);
virObjectUnlock(driver->inactivePciHostdevs);
virObjectUnref(pcidevs); virObjectUnref(pcidevs);
virObjectUnref(cfg); virObjectUnref(cfg);
return ret; return ret;
} }
static int
qemuPrepareHostPCIDevices(virQEMUDriverPtr driver,
virDomainDefPtr def)
{
return qemuPrepareHostdevPCIDevices(driver, def->name, def->uuid,
def->hostdevs, def->nhostdevs);
}
int int
qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver,
const char *name, const char *name,
...@@ -602,6 +613,7 @@ qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, ...@@ -602,6 +613,7 @@ qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver,
unsigned int count; unsigned int count;
virUSBDevicePtr tmp; virUSBDevicePtr tmp;
virObjectLock(driver->activeUsbHostdevs);
count = virUSBDeviceListCount(list); count = virUSBDeviceListCount(list);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
...@@ -631,6 +643,8 @@ qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, ...@@ -631,6 +643,8 @@ qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver,
if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0)
goto error; goto error;
} }
virObjectUnlock(driver->activeUsbHostdevs);
return 0; return 0;
error: error:
...@@ -638,6 +652,7 @@ error: ...@@ -638,6 +652,7 @@ error:
tmp = virUSBDeviceListGet(list, i); tmp = virUSBDeviceListGet(list, i);
virUSBDeviceListSteal(driver->activeUsbHostdevs, tmp); virUSBDeviceListSteal(driver->activeUsbHostdevs, tmp);
} }
virObjectUnlock(driver->activeUsbHostdevs);
return -1; return -1;
} }
...@@ -803,7 +818,8 @@ int qemuPrepareHostDevices(virQEMUDriverPtr driver, ...@@ -803,7 +818,8 @@ int qemuPrepareHostDevices(virQEMUDriverPtr driver,
if (!def->nhostdevs) if (!def->nhostdevs)
return 0; return 0;
if (qemuPrepareHostPCIDevices(driver, def) < 0) if (qemuPrepareHostdevPCIDevices(driver, def->name, def->uuid,
def->hostdevs, def->nhostdevs) < 0)
return -1; return -1;
if (qemuPrepareHostUSBDevices(driver, def, coldBoot) < 0) if (qemuPrepareHostUSBDevices(driver, def, coldBoot) < 0)
...@@ -813,6 +829,10 @@ int qemuPrepareHostDevices(virQEMUDriverPtr driver, ...@@ -813,6 +829,10 @@ int qemuPrepareHostDevices(virQEMUDriverPtr driver,
} }
/*
* Pre-condition: driver->inactivePciHostdevs & driver->activePciHostdevs
* are locked
*/
void qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver) void qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver)
{ {
int retries = 100; int retries = 100;
...@@ -852,6 +872,9 @@ void qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, ...@@ -852,6 +872,9 @@ void qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver,
int i; int i;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virObjectLock(driver->activePciHostdevs);
virObjectLock(driver->inactivePciHostdevs);
if (!(pcidevs = qemuGetActivePciHostDeviceList(driver, if (!(pcidevs = qemuGetActivePciHostDeviceList(driver,
hostdevs, hostdevs,
nhostdevs))) { nhostdevs))) {
...@@ -918,6 +941,8 @@ void qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver, ...@@ -918,6 +941,8 @@ void qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver,
virObjectUnref(pcidevs); virObjectUnref(pcidevs);
cleanup: cleanup:
virObjectUnlock(driver->activePciHostdevs);
virObjectUnlock(driver->inactivePciHostdevs);
virObjectUnref(cfg); virObjectUnref(cfg);
} }
...@@ -929,6 +954,7 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, ...@@ -929,6 +954,7 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver,
{ {
int i; int i;
virObjectLock(driver->activeUsbHostdevs);
for (i = 0; i < nhostdevs; i++) { for (i = 0; i < nhostdevs; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i]; virDomainHostdevDefPtr hostdev = hostdevs[i];
virUSBDevicePtr usb, tmp; virUSBDevicePtr usb, tmp;
...@@ -980,6 +1006,7 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, ...@@ -980,6 +1006,7 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver,
virUSBDeviceListDel(driver->activeUsbHostdevs, tmp); virUSBDeviceListDel(driver->activeUsbHostdevs, tmp);
} }
} }
virObjectUnlock(driver->activeUsbHostdevs);
} }
void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver, void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver,
......
...@@ -2368,6 +2368,8 @@ qemuDomainDetachHostPciDevice(virQEMUDriverPtr driver, ...@@ -2368,6 +2368,8 @@ qemuDomainDetachHostPciDevice(virQEMUDriverPtr driver,
if (detach->parent.data.net) if (detach->parent.data.net)
qemuDomainHostdevNetConfigRestore(detach, cfg->stateDir); qemuDomainHostdevNetConfigRestore(detach, cfg->stateDir);
virObjectLock(driver->activePciHostdevs);
virObjectLock(driver->inactivePciHostdevs);
pci = virPCIDeviceNew(subsys->u.pci.domain, subsys->u.pci.bus, pci = virPCIDeviceNew(subsys->u.pci.domain, subsys->u.pci.bus,
subsys->u.pci.slot, subsys->u.pci.function); subsys->u.pci.slot, subsys->u.pci.function);
if (pci) { if (pci) {
...@@ -2383,6 +2385,8 @@ qemuDomainDetachHostPciDevice(virQEMUDriverPtr driver, ...@@ -2383,6 +2385,8 @@ qemuDomainDetachHostPciDevice(virQEMUDriverPtr driver,
} }
virPCIDeviceFree(pci); virPCIDeviceFree(pci);
} }
virObjectUnlock(driver->activePciHostdevs);
virObjectUnlock(driver->inactivePciHostdevs);
if (qemuCapsGet(priv->caps, QEMU_CAPS_DEVICE) && if (qemuCapsGet(priv->caps, QEMU_CAPS_DEVICE) &&
qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
...@@ -2425,7 +2429,9 @@ qemuDomainDetachHostUsbDevice(virQEMUDriverPtr driver, ...@@ -2425,7 +2429,9 @@ qemuDomainDetachHostUsbDevice(virQEMUDriverPtr driver,
usb = virUSBDeviceNew(subsys->u.usb.bus, subsys->u.usb.device, NULL); usb = virUSBDeviceNew(subsys->u.usb.bus, subsys->u.usb.device, NULL);
if (usb) { if (usb) {
virObjectLock(driver->activeUsbHostdevs);
virUSBDeviceListDel(driver->activeUsbHostdevs, usb); virUSBDeviceListDel(driver->activeUsbHostdevs, usb);
virObjectUnlock(driver->activeUsbHostdevs);
virUSBDeviceFree(usb); virUSBDeviceFree(usb);
} else { } else {
VIR_WARN("Unable to find device %03d.%03d in list of used USB devices", VIR_WARN("Unable to find device %03d.%03d in list of used USB devices",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册