Make pciDeviceList struct opaque

* 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
This commit is contained in:
Daniel P. Berrange 2009-10-27 17:30:16 +00:00
parent 790f0b3057
commit dd9e9c3b54
4 changed files with 101 additions and 44 deletions

View File

@ -365,6 +365,11 @@ pciDeviceListFree;
pciDeviceListAdd;
pciDeviceListDel;
pciDeviceFileIterate;
pciDeviceListCount;
pciDeviceListGet;
pciDeviceListLock;
pciDeviceListUnlock;
pciDeviceListSteal;
# qparams.h

View File

@ -1365,7 +1365,7 @@ qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
virDomainDefPtr def)
{
pciDeviceList *pcidevs;
int i, ret;
int ret = -1;
if (!def->nhostdevs)
return 0;
@ -1373,18 +1373,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;
}
@ -1396,6 +1397,7 @@ qemuPrepareHostDevices(virConnectPtr conn,
{
pciDeviceList *pcidevs;
int i;
int ret = -1;
if (!def->nhostdevs)
return 0;
@ -1415,33 +1417,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;
/* Now mark all the devices as active */
for (i = 0; i < pcidevs->count; i++) {
if (pciDeviceListAdd(conn,
driver->activePciHostdevs,
pcidevs->devs[i]) < 0)
goto error;
pcidevs->devs[i] = NULL;
goto cleanup;
}
pciDeviceListFree(conn, pcidevs);
return 0;
/* Now mark all the devices as active */
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i);
pciDeviceListSteal(NULL, pcidevs, dev);
if (pciDeviceListAdd(conn,
driver->activePciHostdevs,
dev) < 0) {
pciFreeDevice(NULL, dev);
goto cleanup;
}
}
error:
ret = 0;
cleanup:
pciDeviceListFree(conn, pcidevs);
return -1;
return ret;
}
static void
@ -1466,26 +1474,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);
}

View File

@ -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 *

View File

@ -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);