* src/util/pci.c, src/util/pci.h: Make the pciDeviceList struct opaque to callers of the API. Add accessor methods for managing devices in the list * src/qemu/qemu_driver.c: Update to use APIs instead of directly accessing pciDeviceList fields --- src/libvirt_private.syms | 5 +++ src/qemu/qemu_driver.c | 74 +++++++++++++++++++++++++++------------------ src/util/pci.c | 46 +++++++++++++++++++++++++--- src/util/pci.h | 12 ++++--- 4 files changed, 97 insertions(+), 40 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 15d75fd..1e4a3dd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -356,6 +356,11 @@ pciDeviceListFree; pciDeviceListAdd; pciDeviceListDel; pciDeviceFileIterate; +pciDeviceListCount; +pciDeviceListGet; +pciDeviceListLock; +pciDeviceListUnlock; +pciDeviceListSteal; # qparams.h diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2b8b550..3bbbb6d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1367,7 +1367,7 @@ qemuUpdateActivePciHostdevs(struct qemud_driver *driver, virDomainDefPtr def) { pciDeviceList *pcidevs; - int i, ret; + int ret = -1; if (!def->nhostdevs) return 0; @@ -1375,18 +1375,19 @@ qemuUpdateActivePciHostdevs(struct qemud_driver *driver, if (!(pcidevs = qemuGetPciHostDeviceList(NULL, def))) return -1; - ret = 0; - - for (i = 0; i < pcidevs->count; i++) { + while (pciDeviceListCount(pcidevs) > 0) { + pciDevice *dev = pciDeviceListSteal(NULL, pcidevs, 0); if (pciDeviceListAdd(NULL, driver->activePciHostdevs, - pcidevs->devs[i]) < 0) { - ret = -1; - break; + dev) < 0) { + pciFreeDevice(NULL, dev); + goto cleanup; } - pcidevs->devs[i] = NULL; } + ret = 0; + +cleanup: pciDeviceListFree(NULL, pcidevs); return ret; } @@ -1398,6 +1399,7 @@ qemuPrepareHostDevices(virConnectPtr conn, { pciDeviceList *pcidevs; int i; + int ret = -1; if (!def->nhostdevs) return 0; @@ -1417,33 +1419,39 @@ qemuPrepareHostDevices(virConnectPtr conn, * to pci-stub.ko */ - for (i = 0; i < pcidevs->count; i++) - if (pciDeviceGetManaged(pcidevs->devs[i]) && - pciDettachDevice(conn, pcidevs->devs[i]) < 0) - goto error; + for (i = 0; i < pciDeviceListCount(pcidevs); i++) { + pciDevice *dev = pciDeviceListGet(pcidevs, i); + if (pciDeviceGetManaged(dev) && + pciDettachDevice(conn, dev) < 0) + goto cleanup; + } /* Now that all the PCI hostdevs have be dettached, we can safely * reset them */ - for (i = 0; i < pcidevs->count; i++) - if (pciResetDevice(conn, pcidevs->devs[i], + for (i = 0; i < pciDeviceListCount(pcidevs); i++) { + pciDevice *dev = pciDeviceListGet(pcidevs, i); + if (pciResetDevice(conn, dev, driver->activePciHostdevs) < 0) - goto error; + goto cleanup; + } /* Now mark all the devices as active */ - for (i = 0; i < pcidevs->count; i++) { + for (i = 0; i < pciDeviceListCount(pcidevs); i++) { + pciDevice *dev = pciDeviceListGet(pcidevs, i); + pciDeviceListSteal(NULL, pcidevs, dev); if (pciDeviceListAdd(conn, driver->activePciHostdevs, - pcidevs->devs[i]) < 0) - goto error; - pcidevs->devs[i] = NULL; + dev) < 0) { + pciFreeDevice(NULL, dev); + goto cleanup; + } } - pciDeviceListFree(conn, pcidevs); - return 0; + ret = 0; -error: +cleanup: pciDeviceListFree(conn, pcidevs); - return -1; + return ret; } static void @@ -1468,26 +1476,32 @@ qemuDomainReAttachHostDevices(virConnectPtr conn, /* Again 3 loops; mark all devices as inactive before reset * them and reset all the devices before re-attach */ - for (i = 0; i < pcidevs->count; i++) - pciDeviceListDel(conn, driver->activePciHostdevs, pcidevs->devs[i]); + for (i = 0; i < pciDeviceListCount(pcidevs); i++) { + pciDevice *dev = pciDeviceListGet(pcidevs, i); + pciDeviceListDel(conn, driver->activePciHostdevs, dev); + } - for (i = 0; i < pcidevs->count; i++) - if (pciResetDevice(conn, pcidevs->devs[i], + for (i = 0; i < pciDeviceListCount(pcidevs); i++) { + pciDevice *dev = pciDeviceListGet(pcidevs, i); + if (pciResetDevice(conn, dev, driver->activePciHostdevs) < 0) { virErrorPtr err = virGetLastError(); VIR_ERROR(_("Failed to reset PCI device: %s\n"), err ? err->message : ""); virResetError(err); } + } - for (i = 0; i < pcidevs->count; i++) - if (pciDeviceGetManaged(pcidevs->devs[i]) && - pciReAttachDevice(conn, pcidevs->devs[i]) < 0) { + for (i = 0; i < pciDeviceListCount(pcidevs); i++) { + pciDevice *dev = pciDeviceListGet(pcidevs, i); + if (pciDeviceGetManaged(dev) && + pciReAttachDevice(NULL, dev) < 0) { virErrorPtr err = virGetLastError(); VIR_ERROR(_("Failed to re-attach PCI device: %s\n"), err ? err->message : ""); virResetError(err); } + } pciDeviceListFree(conn, pcidevs); } diff --git a/src/util/pci.c b/src/util/pci.c index feaa6e8..1e003c2 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -66,6 +66,12 @@ struct _pciDevice { unsigned managed : 1; }; +struct _pciDeviceList { + unsigned count; + pciDevice **devs; +}; + + /* For virReportOOMError() and virReportSystemError() */ #define VIR_FROM_THIS VIR_FROM_NONE @@ -980,11 +986,30 @@ pciDeviceListAdd(virConnectPtr conn, return 0; } -void -pciDeviceListDel(virConnectPtr conn ATTRIBUTE_UNUSED, - pciDeviceList *list, - pciDevice *dev) +pciDevice * +pciDeviceListGet(pciDeviceList *list, + int idx) +{ + if (idx >= list->count) + return NULL; + if (idx < 0) + return NULL; + + return list->devs[idx]; +} + +int +pciDeviceListCount(pciDeviceList *list) { + return list->count; +} + +pciDevice * +pciDeviceListSteal(virConnectPtr conn ATTRIBUTE_UNUSED, + pciDeviceList *list, + pciDevice *dev) +{ + pciDevice *ret = NULL; int i; for (i = 0; i < list->count; i++) { @@ -994,7 +1019,7 @@ pciDeviceListDel(virConnectPtr conn ATTRIBUTE_UNUSED, list->devs[i]->function != dev->function) continue; - pciFreeDevice(conn, list->devs[i]); + ret = list->devs[i]; if (i != --list->count) memmove(&list->devs[i], @@ -1007,6 +1032,17 @@ pciDeviceListDel(virConnectPtr conn ATTRIBUTE_UNUSED, break; } + return ret; +} + +void +pciDeviceListDel(virConnectPtr conn, + pciDeviceList *list, + pciDevice *dev) +{ + pciDevice *ret = pciDeviceListSteal(conn, list, dev); + if (ret) + pciFreeDevice(conn, ret); } pciDevice * diff --git a/src/util/pci.h b/src/util/pci.h index 047955f..1f0b9d2 100644 --- a/src/util/pci.h +++ b/src/util/pci.h @@ -25,11 +25,7 @@ #include "internal.h" typedef struct _pciDevice pciDevice; - -typedef struct { - unsigned count; - pciDevice **devs; -} pciDeviceList; +typedef struct _pciDeviceList pciDeviceList; pciDevice *pciGetDevice (virConnectPtr conn, unsigned domain, @@ -55,6 +51,12 @@ void pciDeviceListFree (virConnectPtr conn, int pciDeviceListAdd (virConnectPtr conn, pciDeviceList *list, pciDevice *dev); +pciDevice * pciDeviceListGet (pciDeviceList *list, + int idx); +int pciDeviceListCount (pciDeviceList *list); +pciDevice * pciDeviceListSteal (virConnectPtr conn, + pciDeviceList *list, + pciDevice *dev); void pciDeviceListDel (virConnectPtr conn, pciDeviceList *list, pciDevice *dev); -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list