[libvirt] [PATCH v2 05/11] qemu: switch PCI address set from hash table to an array

Ján Tomko jtomko at redhat.com
Wed Apr 17 19:00:27 UTC 2013


Each bus is represented as an array of 32 8-bit integers
where each bit represents a PCI function and each byte represents
a PCI slot.

Uses just one bus so far.
---
 src/qemu/qemu_command.c | 152 ++++++++++++++----------------------------------
 1 file changed, 45 insertions(+), 107 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8f766c5..c51c336 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1187,8 +1187,14 @@ cleanup:
 
 #define QEMU_PCI_ADDRESS_SLOT_LAST 32
 #define QEMU_PCI_ADDRESS_FUNCTION_LAST 8
+
+/*
+ * Each bit represents a function
+ * Each byte represents a slot
+ */
+typedef uint8_t qemuDomainPCIAddressBus[QEMU_PCI_ADDRESS_SLOT_LAST];
 struct _qemuDomainPCIAddressSet {
-    virHashTablePtr used;
+    qemuDomainPCIAddressBus *used;
     virDevicePCIAddress lastaddr;
 };
 
@@ -1268,7 +1274,7 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
     if (!(str = qemuPCIAddressAsString(addr)))
         goto cleanup;
 
-    if (virHashLookup(addrs->used, str)) {
+    if (addrs->used[addr->bus][addr->slot] & 1 << addr->function) {
         if (info->addr.pci.function != 0) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("Attempted double use of PCI Address '%s' "
@@ -1281,35 +1287,22 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
         goto cleanup;
     }
 
-    VIR_DEBUG("Remembering PCI addr %s", str);
-    if (virHashAddEntry(addrs->used, str, str) < 0)
-        goto cleanup;
-    str = NULL;
-
     if ((info->addr.pci.function == 0) &&
         (info->addr.pci.multi != VIR_DEVICE_ADDRESS_PCI_MULTI_ON)) {
         /* a function 0 w/o multifunction=on must reserve the entire slot */
-        virDevicePCIAddress tmp_addr = *addr;
-        unsigned int *func = &tmp_addr.function;
-
-        for (*func = 1; *func < QEMU_PCI_ADDRESS_FUNCTION_LAST; (*func)++) {
-            if (!(str = qemuPCIAddressAsString(&tmp_addr)))
-                goto cleanup;
-
-            if (virHashLookup(addrs->used, str)) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("Attempted double use of PCI Address '%s' "
-                                 "(need \"multifunction='off'\" for device "
-                                 "on function 0)"),
-                               str);
-                goto cleanup;
-            }
-
-            VIR_DEBUG("Remembering PCI addr %s (multifunction=off for function 0)", str);
-            if (virHashAddEntry(addrs->used, str, str))
-                goto cleanup;
-            str = NULL;
+        if (addrs->used[addr->bus][addr->slot]) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Attempted double use of PCI Address on slot '%s' "
+                             "(need \"multifunction='off'\" for device "
+                             "on function 0)"),
+                           str);
+            goto cleanup;
         }
+        addrs->used[addr->bus][addr->slot] = 0xFF;
+        VIR_DEBUG("Remembering PCI slot: %s (multifunction=off)", str);
+    } else {
+        VIR_DEBUG("Remembering PCI addr: %s", str);
+        addrs->used[addr->bus][addr->slot] |= 1 << addr->function;
     }
     ret = 0;
 cleanup:
@@ -1373,13 +1366,6 @@ int qemuDomainAssignAddresses(virDomainDefPtr def,
     return qemuDomainAssignPCIAddresses(def, qemuCaps, obj);
 }
 
-static void
-qemuDomainPCIAddressSetFreeEntry(void *payload,
-                                 const void *name ATTRIBUTE_UNUSED)
-{
-    VIR_FREE(payload);
-}
-
 qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def)
 {
     qemuDomainPCIAddressSetPtr addrs;
@@ -1387,8 +1373,8 @@ qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def)
     if (VIR_ALLOC(addrs) < 0)
         goto no_memory;
 
-    if (!(addrs->used = virHashCreate(10, qemuDomainPCIAddressSetFreeEntry)))
-        goto error;
+    if (VIR_ALLOC_N(addrs->used, 1) < 0)
+        goto no_memory;
 
     if (virDomainDeviceInfoIterate(def, qemuCollectPCIAddress, addrs) < 0)
         goto error;
@@ -1409,24 +1395,7 @@ error:
 static int qemuDomainPCIAddressCheckSlot(qemuDomainPCIAddressSetPtr addrs,
                                          virDevicePCIAddressPtr addr)
 {
-    char *str;
-    virDevicePCIAddress tmp_addr = *addr;
-    unsigned int *func = &(tmp_addr.function);
-
-    for (*func = 0; *func < QEMU_PCI_ADDRESS_FUNCTION_LAST; (*func)++) {
-        str = qemuPCIAddressAsString(&tmp_addr);
-        if (!str)
-            return -1;
-
-        if (virHashLookup(addrs->used, str)) {
-            VIR_FREE(str);
-            return -1;
-        }
-
-        VIR_FREE(str);
-    }
-
-    return 0;
+    return addrs->used[addr->bus][addr->slot] ? -1 : 0;
 }
 
 int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
@@ -1434,48 +1403,47 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
 {
     char *str;
 
-    str = qemuPCIAddressAsString(addr);
-    if (!str)
+    if (!(str = qemuPCIAddressAsString(addr)))
         return -1;
 
     VIR_DEBUG("Reserving PCI addr %s", str);
 
-    if (virHashLookup(addrs->used, str)) {
+    if (addrs->used[addr->bus][addr->slot] & 1 << addr->function) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unable to reserve PCI address %s"), str);
         VIR_FREE(str);
         return -1;
     }
 
-    if (virHashAddEntry(addrs->used, str, str)) {
-        VIR_FREE(str);
-        return -1;
-    }
+    VIR_FREE(str);
 
     addrs->lastaddr = *addr;
     addrs->lastaddr.function = 0;
     addrs->lastaddr.multi = 0;
+    addrs->used[addr->bus][addr->slot] |= 1 << addr->function;
     return 0;
 }
 
 int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
                                     virDevicePCIAddressPtr addr)
 {
-    virDevicePCIAddress tmp_addr = *addr;
-    unsigned int *func = &tmp_addr.function;
-    unsigned int last;
+    char *str;
 
-    for (*func = 0; *func < QEMU_PCI_ADDRESS_FUNCTION_LAST; (*func)++) {
-        if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr) < 0)
-            goto cleanup;
+    if (!(str = qemuPCIAddressAsString(addr)))
+        return -1;
+
+    VIR_DEBUG("Reserving PCI slot %s", str);
+
+    if (addrs->used[addr->bus][addr->slot]) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unable to reserve PCI slot %s"), str);
+        VIR_FREE(str);
+        return -1;
     }
 
+    VIR_FREE(str);
+    addrs->used[addr->bus][addr->slot] = 0xFF;
     return 0;
-
-cleanup:
-    for (last = *func, *func = 0; *func < last; (*func)++)
-        qemuDomainPCIAddressReleaseAddr(addrs, &tmp_addr);
-    return -1;
 }
 
 int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
@@ -1507,48 +1475,18 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
 int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
                                     virDevicePCIAddressPtr addr)
 {
-    char *str;
-    int ret;
-
-    str = qemuPCIAddressAsString(addr);
-    if (!str)
-        return -1;
-
-    ret = virHashRemoveEntry(addrs->used, str);
-
-    VIR_FREE(str);
-
-    return ret;
+    addrs->used[addr->bus][addr->slot] &= ~(1 << addr->function);
+    return 0;
 }
 
 int qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs,
                                     virDevicePCIAddressPtr addr)
 {
-    char *str;
-    int ret = 0;
-    virDevicePCIAddress tmp_addr = *addr;
-    unsigned int *func = &tmp_addr.function;
-
     if (!qemuPCIAddressValidate(addrs, addr))
         return -1;
 
-    for (*func = 0; *func < QEMU_PCI_ADDRESS_FUNCTION_LAST; (*func)++) {
-        str = qemuPCIAddressAsString(&tmp_addr);
-        if (!str)
-            return -1;
-
-        if (!virHashLookup(addrs->used, str)) {
-            VIR_FREE(str);
-            continue;
-        }
-
-        VIR_FREE(str);
-
-        if (qemuDomainPCIAddressReleaseAddr(addrs, &tmp_addr) < 0)
-            ret = -1;
-    }
-
-    return ret;
+    addrs->used[addr->bus][addr->slot] = 0;
+    return 0;
 }
 
 void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
@@ -1556,7 +1494,7 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
     if (!addrs)
         return;
 
-    virHashFree(addrs->used);
+    VIR_FREE(addrs->used);
     VIR_FREE(addrs);
 }
 
-- 
1.8.1.5




More information about the libvir-list mailing list