Each bus (just one so far) is represented by an array
with 32 slots where each slot is stored as an 8-bit integer
where each bit represents a function.
This makes operations with whole slots easier.
---
src/qemu/qemu_command.c | 152 +++++++++++++++---------------------------------
1 file changed, 48 insertions(+), 104 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a16d5f1..e221c82 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1187,8 +1187,14 @@ cleanup:
#define QEMU_PCI_ADDRESS_LAST_SLOT 32
#define QEMU_PCI_ADDRESS_LAST_FUNCTION 8
+
+/*
+ * Each bit represents a function
+ * Each byte represents a slot
+ */
+typedef uint8_t _qemuDomainPCIAddressBus[QEMU_PCI_ADDRESS_LAST_SLOT];
struct _qemuDomainPCIAddressSet {
- virHashTablePtr used;
+ _qemuDomainPCIAddressBus *used;
virDevicePCIAddress lastaddr;
};
@@ -1269,7 +1275,7 @@ static int qemuCollectPCIAddress(virDomainDefPtr def
ATTRIBUTE_UNUSED,
if (!str)
goto cleanup;
- if (virHashLookup(addrs->used, str)) {
+ if (qemuDomainPCIAddressReserveAddr(addrs, addr) < 0) {
if (info->addr.pci.function != 0) {
virReportError(VIR_ERR_XML_ERROR,
_("Attempted double use of PCI Address '%s'
"
@@ -1282,36 +1288,21 @@ 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_LAST_FUNCTION; (*func)++) {
- str = qemuPCIAddressAsString(&tmp_addr);
- if (!str)
- 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;
+ ignore_value(qemuDomainPCIAddressReleaseAddr(addrs, addr));
+ if (qemuDomainPCIAddressReserveSlot(addrs, addr) < 0) {
+ 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 slot: %s (multifunction=off)", str);
+ } else {
+ VIR_DEBUG("Remembering PCI addr: %s", str);
}
ret = 0;
cleanup:
@@ -1375,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;
@@ -1389,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;
@@ -1411,25 +1395,11 @@ error:
static int qemuDomainPCIAddressCheckSlot(qemuDomainPCIAddressSetPtr addrs,
virDevicePCIAddressPtr addr)
{
- char *str;
- virDevicePCIAddress tmp_addr = *addr;
- unsigned int *func = &(tmp_addr.function);
-
if (qemuPCIAddressCheck(addrs, addr) < 0)
return -1;
- for (*func = 0; *func < QEMU_PCI_ADDRESS_LAST_FUNCTION; (*func)++) {
- str = qemuPCIAddressAsString(&tmp_addr);
- if (!str)
- return -1;
-
- if (virHashLookup(addrs->used, str)) {
- VIR_FREE(str);
- return -1;
- }
-
- VIR_FREE(str);
- }
+ if (addrs->used[addr->bus][addr->slot])
+ return -1;
return 0;
}
@@ -1448,42 +1418,46 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr
addrs,
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_LAST_FUNCTION; (*func)++) {
- if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr) < 0)
- goto cleanup;
+ if (qemuPCIAddressCheck(addrs, addr) < 0)
+ return -1;
+
+ str = qemuPCIAddressAsString(addr);
+ if (!str)
+ 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,
@@ -1512,51 +1486,21 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr
addrs,
int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
virDevicePCIAddressPtr addr)
{
- char *str;
- int ret;
-
if (qemuPCIAddressCheck(addrs, addr) < 0)
return -1;
- 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 (qemuPCIAddressCheck(addrs, addr) < 0)
return -1;
- for (*func = 0; *func < QEMU_PCI_ADDRESS_LAST_FUNCTION; (*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)
@@ -1564,7 +1508,7 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
if (!addrs)
return;
- virHashFree(addrs->used);
+ VIR_FREE(addrs->used);
VIR_FREE(addrs);
}
--
1.8.1.5