diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 998b8433bc..16bdc3f89c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -294,6 +294,8 @@ pciDeviceListNew; pciDeviceListFree; pciDeviceListAdd; pciDeviceListDel; +pciDeviceFileIterate; + # qparams.h qparam_get_query; diff --git a/src/pci.c b/src/pci.c index 96e5d6dcc8..feaa6e8033 100644 --- a/src/pci.c +++ b/src/pci.c @@ -1022,3 +1022,55 @@ pciDeviceListFind(pciDeviceList *list, pciDevice *dev) return list->devs[i]; return NULL; } + + +int pciDeviceFileIterate(virConnectPtr conn, + pciDevice *dev, + pciDeviceFileActor actor, + void *opaque) +{ + char *pcidir = NULL; + char *file = NULL; + DIR *dir = NULL; + int ret = -1; + struct dirent *ent; + + if (virAsprintf(&pcidir, "/sys/bus/pci/devices/%04x:%02x:%02x.%x", + dev->domain, dev->bus, dev->slot, dev->function) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + if (!(dir = opendir(pcidir))) { + virReportSystemError(conn, errno, + _("cannot open %s"), pcidir); + goto cleanup; + } + + while ((ent = readdir(dir)) != NULL) { + /* Device assignment requires: + * $PCIDIR/config, $PCIDIR/resource, $PCIDIR/resourceNNN, $PCIDIR/rom + */ + if (STREQ(ent->d_name, "config") || + STRPREFIX(ent->d_name, "resource") || + STREQ(ent->d_name, "rom")) { + if (virAsprintf(&file, "%s/%s", pcidir, ent->d_name) < 0) { + virReportOOMError(conn); + goto cleanup; + } + if ((actor)(conn, dev, file, opaque) < 0) + goto cleanup; + + VIR_FREE(file); + } + } + + ret = 0; + +cleanup: + if (dir) + closedir(dir); + VIR_FREE(file); + VIR_FREE(pcidir); + return ret; +} diff --git a/src/pci.h b/src/pci.h index 685b0afc9d..047955f007 100644 --- a/src/pci.h +++ b/src/pci.h @@ -22,7 +22,6 @@ #ifndef __VIR_PCI_H__ #define __VIR_PCI_H__ -#include #include "internal.h" typedef struct _pciDevice pciDevice; @@ -62,4 +61,19 @@ void pciDeviceListDel (virConnectPtr conn, pciDevice * pciDeviceListFind (pciDeviceList *list, pciDevice *dev); +/* + * Callback that will be invoked once for each file + * associated with / used for PCI host device access. + * + * Should return 0 if successfully processed, or + * -1 to indicate error and abort iteration + */ +typedef int (*pciDeviceFileActor)(virConnectPtr conn, pciDevice *dev, + const char *path, void *opaque); + +int pciDeviceFileIterate(virConnectPtr conn, + pciDevice *dev, + pciDeviceFileActor actor, + void *opaque); + #endif /* __VIR_PCI_H__ */