pci: new utility functions

* 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).
This commit is contained in:
Laine Stump 2013-05-31 11:06:32 -04:00
parent 53e52b4ac3
commit 50a8d85035
3 changed files with 105 additions and 17 deletions

View File

@ -1688,6 +1688,7 @@ virObjectUnref;
# util/virpci.h # util/virpci.h
virPCIDeviceAddressGetSysfsFile; virPCIDeviceAddressGetSysfsFile;
virPCIDeviceCopy;
virPCIDeviceDetach; virPCIDeviceDetach;
virPCIDeviceFileIterate; virPCIDeviceFileIterate;
virPCIDeviceFree; virPCIDeviceFree;
@ -1704,6 +1705,7 @@ virPCIDeviceListAdd;
virPCIDeviceListCount; virPCIDeviceListCount;
virPCIDeviceListDel; virPCIDeviceListDel;
virPCIDeviceListFind; virPCIDeviceListFind;
virPCIDeviceListFindByIDs;
virPCIDeviceListFindIndex; virPCIDeviceListFindIndex;
virPCIDeviceListGet; virPCIDeviceListGet;
virPCIDeviceListNew; virPCIDeviceListNew;

View File

@ -880,6 +880,54 @@ virPCIFile(char **buffer, const char *device, const char *file)
return 0; 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 static int
virPCIProbeStubDriver(const char *driver) virPCIProbeStubDriver(const char *driver)
{ {
@ -931,23 +979,7 @@ virPCIDeviceUnbindFromStub(virPCIDevicePtr dev)
/* If the device is currently bound to one of the "well known" /* If the device is currently bound to one of the "well known"
* stub drivers, then unbind it, otherwise ignore it. * stub drivers, then unbind it, otherwise ignore it.
*/ */
if (virPCIFile(&path, dev->name, "driver") < 0) if (virPCIDeviceGetDriverPathAndName(dev, &drvdir, &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)
goto cleanup; goto cleanup;
if (!dev->unbind_from_stub) if (!dev->unbind_from_stub)
@ -1473,6 +1505,32 @@ error:
goto cleanup; 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 void
virPCIDeviceFree(virPCIDevicePtr dev) virPCIDeviceFree(virPCIDevicePtr dev)
{ {
@ -1690,6 +1748,27 @@ virPCIDeviceListFindIndex(virPCIDeviceListPtr list, virPCIDevicePtr dev)
return -1; 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 virPCIDevicePtr
virPCIDeviceListFind(virPCIDeviceListPtr list, virPCIDevicePtr dev) virPCIDeviceListFind(virPCIDeviceListPtr list, virPCIDevicePtr dev)
{ {

View File

@ -45,6 +45,7 @@ virPCIDevicePtr virPCIDeviceNew(unsigned int domain,
unsigned int bus, unsigned int bus,
unsigned int slot, unsigned int slot,
unsigned int function); unsigned int function);
virPCIDevicePtr virPCIDeviceCopy(virPCIDevicePtr dev);
void virPCIDeviceFree(virPCIDevicePtr dev); void virPCIDeviceFree(virPCIDevicePtr dev);
const char *virPCIDeviceGetName(virPCIDevicePtr dev); const char *virPCIDeviceGetName(virPCIDevicePtr dev);
@ -94,6 +95,12 @@ void virPCIDeviceListDel(virPCIDeviceListPtr list,
virPCIDevicePtr dev); virPCIDevicePtr dev);
virPCIDevicePtr virPCIDeviceListFind(virPCIDeviceListPtr list, virPCIDevicePtr virPCIDeviceListFind(virPCIDeviceListPtr list,
virPCIDevicePtr dev); virPCIDevicePtr dev);
virPCIDevicePtr
virPCIDeviceListFindByIDs(virPCIDeviceListPtr list,
unsigned int domain,
unsigned int bus,
unsigned int slot,
unsigned int function);
int virPCIDeviceListFindIndex(virPCIDeviceListPtr list, int virPCIDeviceListFindIndex(virPCIDeviceListPtr list,
virPCIDevicePtr dev); virPCIDevicePtr dev);