[libvirt] [PATCH 11/18] virpcimock: Store PCI address as ints not string

Michal Privoznik mprivozn at redhat.com
Wed Aug 14 11:57:40 UTC 2019


In upcoming patches we will need only some portions of the PCI
address. To construct that easily, it's better if the PCI address
of a device is stored as four integers rather than one string.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 tests/virpcimock.c | 76 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 61 insertions(+), 15 deletions(-)

diff --git a/tests/virpcimock.c b/tests/virpcimock.c
index de365cdb78..c10764dcdd 100644
--- a/tests/virpcimock.c
+++ b/tests/virpcimock.c
@@ -118,8 +118,16 @@ struct pciDriver {
     unsigned int fail;  /* Bitwise-OR of driverActions that should fail */
 };
 
+struct pciDeviceAddress {
+    unsigned int domain;
+    unsigned int bus;
+    unsigned int device;
+    unsigned int function;
+};
+# define ADDR_STR_FMT "%04x:%02x:%02x.%d"
+
 struct pciDevice {
-    const char *id;
+    struct pciDeviceAddress addr;
     int vendor;
     int device;
     int klass;
@@ -145,7 +153,7 @@ static void init_env(void);
 
 static int pci_device_autobind(struct pciDevice *dev);
 static void pci_device_new_from_stub(const struct pciDevice *data);
-static struct pciDevice *pci_device_find_by_id(const char *id);
+static struct pciDevice *pci_device_find_by_id(struct pciDeviceAddress const *addr);
 static struct pciDevice *pci_device_find_by_content(const char *path);
 
 static void pci_driver_new(const char *name, int fail, ...);
@@ -337,6 +345,29 @@ remove_fd(int fd)
 /*
  * PCI Device functions
  */
+static char *
+pci_address_format(struct pciDeviceAddress const *addr)
+{
+    char *ret;
+
+    ignore_value(virAsprintfQuiet(&ret, ADDR_STR_FMT,
+                                  addr->domain, addr->bus,
+                                  addr->device, addr->function));
+    return ret;
+}
+
+static int
+pci_address_parse(struct pciDeviceAddress *addr,
+                  const char *buf)
+{
+    if (sscanf(buf, ADDR_STR_FMT,
+               &addr->domain, &addr->bus,
+               &addr->device, &addr->function) != 4)
+        return -1;
+    return 0;
+}
+
+
 static char *
 pci_device_get_path(const struct pciDevice *dev,
                     const char *file,
@@ -344,16 +375,20 @@ pci_device_get_path(const struct pciDevice *dev,
 {
     char *ret = NULL;
     const char *prefix = "";
+    VIR_AUTOFREE(char *) devid = NULL;
 
     if (faked)
         prefix = fakerootdir;
 
+    if (!(devid = pci_address_format(&dev->addr)))
+        return NULL;
+
     if (file) {
         ignore_value(virAsprintfQuiet(&ret, "%s" SYSFS_PCI_PREFIX "devices/%s/%s",
-                                      prefix, dev->id, file));
+                                      prefix, devid, file));
     } else {
         ignore_value(virAsprintfQuiet(&ret, "%s" SYSFS_PCI_PREFIX "devices/%s",
-                                      prefix, dev->id));
+                                      prefix, devid));
     }
 
     return ret;
@@ -366,13 +401,15 @@ pci_device_new_from_stub(const struct pciDevice *data)
     struct pciDevice *dev;
     VIR_AUTOFREE(char *) devpath = NULL;
     VIR_AUTOFREE(char *) id = NULL;
+    VIR_AUTOFREE(char *) devid = NULL;
     char *c;
     VIR_AUTOFREE(char *) configSrc = NULL;
     char tmp[256];
     struct stat sb;
     bool configSrcExists = false;
 
-    if (VIR_STRDUP_QUIET(id, data->id) < 0)
+    if (!(devid = pci_address_format(&data->addr)) ||
+        VIR_STRDUP_QUIET(id, devid) < 0)
         ABORT_OOM();
 
     /* Replace ':' with '-' to create the config filename from the
@@ -452,20 +489,20 @@ pci_device_new_from_stub(const struct pciDevice *data)
     make_symlink(devpath, "iommu_group", tmp);
 
     if (pci_device_autobind(dev) < 0)
-        ABORT("Unable to bind: %s", data->id);
+        ABORT("Unable to bind: %s", devid);
 
     if (VIR_APPEND_ELEMENT_QUIET(pciDevices, nPCIDevices, dev) < 0)
         ABORT_OOM();
 }
 
 static struct pciDevice *
-pci_device_find_by_id(const char *id)
+pci_device_find_by_id(struct pciDeviceAddress const *addr)
 {
     size_t i;
     for (i = 0; i < nPCIDevices; i++) {
         struct pciDevice *dev = pciDevices[i];
 
-        if (STREQ(dev->id, id))
+        if (!memcmp(&dev->addr, addr, sizeof(*addr)))
             return dev;
     }
 
@@ -476,11 +513,13 @@ static struct pciDevice *
 pci_device_find_by_content(const char *path)
 {
     char tmp[32];
+    struct pciDeviceAddress addr;
 
-    if (pci_read_file(path, tmp, sizeof(tmp), true) < 0)
+    if (pci_read_file(path, tmp, sizeof(tmp), true) < 0 ||
+        pci_address_parse(&addr, tmp) < 0)
         return NULL;
 
-    return pci_device_find_by_id(tmp);
+    return pci_device_find_by_id(&addr);
 }
 
 static int
@@ -607,6 +646,7 @@ pci_driver_find_by_path(const char *path)
 static struct pciDriver *
 pci_driver_find_by_driver_override(struct pciDevice *dev)
 {
+    VIR_AUTOFREE(char *) devid = NULL;
     VIR_AUTOFREE(char *) path = NULL;
     char tmp[32];
     size_t i;
@@ -631,6 +671,7 @@ static int
 pci_driver_bind(struct pciDriver *driver,
                 struct pciDevice *dev)
 {
+    VIR_AUTOFREE(char *) devid = NULL;
     VIR_AUTOFREE(char *) devpath = NULL;
     VIR_AUTOFREE(char *) driverpath = NULL;
 
@@ -653,8 +694,9 @@ pci_driver_bind(struct pciDriver *driver,
     /* Make symlink under driver tree */
     VIR_FREE(devpath);
     VIR_FREE(driverpath);
-    if (!(devpath = pci_device_get_path(dev, NULL, true)) ||
-        !(driverpath = pci_driver_get_path(driver, dev->id, true))) {
+    if (!(devid = pci_address_format(&dev->addr)) ||
+        !(devpath = pci_device_get_path(dev, NULL, true)) ||
+        !(driverpath = pci_driver_get_path(driver, devid, true))) {
         errno = ENOMEM;
         return -1;
     }
@@ -670,6 +712,7 @@ static int
 pci_driver_unbind(struct pciDriver *driver,
                   struct pciDevice *dev)
 {
+    VIR_AUTOFREE(char *) devid = NULL;
     VIR_AUTOFREE(char *) devpath = NULL;
     VIR_AUTOFREE(char *) driverpath = NULL;
 
@@ -680,8 +723,9 @@ pci_driver_unbind(struct pciDriver *driver,
     }
 
     /* Make symlink under device tree */
-    if (!(devpath = pci_device_get_path(dev, "driver", true)) ||
-        !(driverpath = pci_driver_get_path(driver, dev->id, true))) {
+    if (!(devid = pci_address_format(&dev->addr)) ||
+        !(devpath = pci_device_get_path(dev, "driver", true)) ||
+        !(driverpath = pci_driver_get_path(driver, devid, true))) {
         errno = ENOMEM;
         return -1;
     }
@@ -913,8 +957,10 @@ init_env(void)
 
 # define MAKE_PCI_DEVICE(Id, Vendor, Device, ...) \
     do { \
-        struct pciDevice dev = {.id = Id, .vendor = Vendor, \
+        struct pciDevice dev = {.vendor = Vendor, \
                                 .device = Device, __VA_ARGS__}; \
+        if (pci_address_parse(&dev.addr, Id) < 0) \
+            ABORT("Unable to parse PCI address " Id); \
         pci_device_new_from_stub(&dev); \
     } while (0)
 
-- 
2.21.0




More information about the libvir-list mailing list