* virPCIDeviceFindByIDs - find a device on a list w/o creating an object
This makes searching for an existing device on a list lighter weight.
* virPCIDeviceCopy - make a copy of an existing virPCIDevice object.
* virPCIDeviceGetDriverPathAndName - construct new strings containing
1) the name of the driver bound to this device.
2) the full path to the sysfs config for that driver.
(This code was lifted from virPCIDeviceUnbindFromStub, and replaced
there with a call to this new function).
---
src/libvirt_private.syms | 2 +
src/util/virpci.c | 113 ++++++++++++++++++++++++++++++++++++++++-------
src/util/virpci.h | 7 +++
3 files changed, 105 insertions(+), 17 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7ac6fdc..2fdb185 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1648,6 +1648,7 @@ virObjectUnref;
# util/virpci.h
virPCIDeviceAddressGetSysfsFile;
+virPCIDeviceCopy;
virPCIDeviceDetach;
virPCIDeviceFileIterate;
virPCIDeviceFree;
@@ -1664,6 +1665,7 @@ virPCIDeviceListAdd;
virPCIDeviceListCount;
virPCIDeviceListDel;
virPCIDeviceListFind;
+virPCIDeviceListFindByIDs;
virPCIDeviceListFindIndex;
virPCIDeviceListGet;
virPCIDeviceListNew;
diff --git a/src/util/virpci.c b/src/util/virpci.c
index d00c3ee..10e95bd 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -880,6 +880,54 @@ virPCIFile(char **buffer, const char *device, const char *file)
return 0;
}
+
+/* virPCIDeviceGetDriverPathAndName - put the path to the driver
+ * directory of the driver in use for this device in @path and the
+ * name of the driver in @name. Both could be NULL if it's not bound
+ * to any driver.
+ *
+ * Return 0 for success, -1 for error.
+ */
+static int
+virPCIDeviceGetDriverPathAndName(virPCIDevicePtr dev, char **path, char **name)
+{
+ int ret = -1;
+ char *drvlink = NULL;
+
+ *path = *name = NULL;
+ /* drvlink = "/sys/bus/pci/dddd:bb:ss.ff/driver" */
+ if (virPCIFile(&drvlink, dev->name, "driver") < 0)
+ goto cleanup;
+
+ if (virFileIsLink(drvlink) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid device %s driver file %s is not a symlink"),
+ dev->name, drvlink);
+ goto cleanup;
+ }
+ if (virFileResolveLink(drvlink, path) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to resolve device %s driver symlink %s"),
+ dev->name, drvlink);
+ goto cleanup;
+ }
+ /* path = "/sys/bus/pci/drivers/${drivername}" */
+
+ if (VIR_STRDUP(*name, last_component(*path)) < 0)
+ goto cleanup;
+ /* name = "${drivername}" */
+
+ ret = 0;
+cleanup:
+ VIR_FREE(drvlink);
+ if (ret < 0) {
+ VIR_FREE(*path);
+ VIR_FREE(*name);
+ }
+ return ret;
+}
+
+
static int
virPCIProbeStubDriver(const char *driver)
{
@@ -931,23 +979,7 @@ virPCIDeviceUnbindFromStub(virPCIDevicePtr dev)
/* If the device is currently bound to one of the "well known"
* stub drivers, then unbind it, otherwise ignore it.
*/
- if (virPCIFile(&path, dev->name, "driver") < 0)
- goto cleanup;
- /* path = "/sys/bus/pci/dddd:bb:ss.ff/driver" */
- if (virFileIsLink(path) != 1) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Invalid device %s driver file %s is not a symlink"),
- dev->name, path);
- goto cleanup;
- }
- if (virFileResolveLink(path, &drvdir) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unable to resolve device %s driver symlink %s"),
- dev->name, path);
- goto cleanup;
- }
- /* drvdir = "/sys/bus/pci/drivers/${drivername}" */
- if (VIR_STRDUP(driver, last_component(drvdir)) < 0)
+ if (virPCIDeviceGetDriverPathAndName(dev, &drvdir, &driver) < 0)
goto cleanup;
if (!dev->unbind_from_stub)
@@ -1473,6 +1505,32 @@ error:
goto cleanup;
}
+
+virPCIDevicePtr
+virPCIDeviceCopy(virPCIDevicePtr dev)
+{
+ virPCIDevicePtr copy;
+
+ if (VIR_ALLOC(copy) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ /* shallow copy to take care of most attributes */
+ *copy = *dev;
+ copy->path = copy->stubDriver = NULL;
+ if (VIR_STRDUP(copy->path, dev->path) < 0 ||
+ VIR_STRDUP(copy->stubDriver, dev->stubDriver) < 0) {
+ goto error;
+ }
+ return copy;
+
+error:
+ virPCIDeviceFree(copy);
+ return NULL;
+}
+
+
void
virPCIDeviceFree(virPCIDevicePtr dev)
{
@@ -1690,6 +1748,27 @@ virPCIDeviceListFindIndex(virPCIDeviceListPtr list, virPCIDevicePtr
dev)
return -1;
}
+
+virPCIDevicePtr
+virPCIDeviceListFindByIDs(virPCIDeviceListPtr list,
+ unsigned int domain,
+ unsigned int bus,
+ unsigned int slot,
+ unsigned int function)
+{
+ int i;
+
+ for (i = 0; i < list->count; i++) {
+ if (list->devs[i]->domain == domain &&
+ list->devs[i]->bus == bus &&
+ list->devs[i]->slot == slot &&
+ list->devs[i]->function == function)
+ return list->devs[i];
+ }
+ return NULL;
+}
+
+
virPCIDevicePtr
virPCIDeviceListFind(virPCIDeviceListPtr list, virPCIDevicePtr dev)
{
diff --git a/src/util/virpci.h b/src/util/virpci.h
index 17b15fe..d069adb 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -45,6 +45,7 @@ virPCIDevicePtr virPCIDeviceNew(unsigned int domain,
unsigned int bus,
unsigned int slot,
unsigned int function);
+virPCIDevicePtr virPCIDeviceCopy(virPCIDevicePtr dev);
void virPCIDeviceFree(virPCIDevicePtr dev);
const char *virPCIDeviceGetName(virPCIDevicePtr dev);
@@ -94,6 +95,12 @@ void virPCIDeviceListDel(virPCIDeviceListPtr list,
virPCIDevicePtr dev);
virPCIDevicePtr virPCIDeviceListFind(virPCIDeviceListPtr list,
virPCIDevicePtr dev);
+virPCIDevicePtr
+virPCIDeviceListFindByIDs(virPCIDeviceListPtr list,
+ unsigned int domain,
+ unsigned int bus,
+ unsigned int slot,
+ unsigned int function);
int virPCIDeviceListFindIndex(virPCIDeviceListPtr list,
virPCIDevicePtr dev);
--
1.7.11.7