[PATCHv2] qemu: Fix PCI address allocation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jiri Denemark <jdenemar@xxxxxxxxxx>

When attaching a PCI device which doesn't explicitly set its PCI
address, libvirt allocates the address automatically. The problem is
that when checking which PCI address is unused, we only check for those
with slot number higher than the highest slot number ever used.

Thus attaching/detaching such device several times in a row (31 is the
theoretical limit, less then 30 tries are enough in practise) makes any
further device attachment fail. Furthermore, attaching a device with
predefined PCI address to 0:0:31 immediately forbids attachment of any
PCI device without explicit address.

This patch changes the logic so that we always check all PCI addresses
before we say there is no PCI address available.

Signed-off-by: Eric Blake <eblake@xxxxxxxxxx>
---

Modifications from v1: revert back to remembering the last slot
reserved, but allow wraparound to not be limited by the end.
In this way, slots are still assigned in the same order as
before the patch, rather than filling in the gaps closest to
0 and risking making windows guests mad.

 src/qemu/qemu_conf.c |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 57bc02f..5397997 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2056,7 +2056,6 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long qemuCmdFlags)
 struct _qemuDomainPCIAddressSet {
     virHashTablePtr used;
     int nextslot;
-    /* XXX add domain, bus later when QEMU allows > 1 */
 };


@@ -2148,8 +2147,11 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
         return -1;
     }

-    if (dev->addr.pci.slot > addrs->nextslot)
+    if (dev->addr.pci.slot > addrs->nextslot) {
         addrs->nextslot = dev->addr.pci.slot + 1;
+        if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
+            addrs->nextslot = 0;
+    }

     return 0;
 }
@@ -2216,11 +2218,15 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
                                     virDomainDeviceInfoPtr dev)
 {
     int i;
+    int iteration;

-    for (i = addrs->nextslot ; i <= QEMU_PCI_ADDRESS_LAST_SLOT ; i++) {
+    for (i = addrs->nextslot, iteration = 0;
+         iteration <= QEMU_PCI_ADDRESS_LAST_SLOT; i++, iteration++) {
         virDomainDeviceInfo maybe;
         char *addr;

+        if (QEMU_PCI_ADDRESS_LAST_SLOT < i)
+            i = 0;
         memset(&maybe, 0, sizeof(maybe));
         maybe.addr.pci.domain = 0;
         maybe.addr.pci.bus = 0;
@@ -2228,13 +2234,14 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,

         addr = qemuPCIAddressAsString(&maybe);

-        VIR_DEBUG("Allocating PCI addr %s", addr);
-
         if (virHashLookup(addrs->used, addr)) {
+            VIR_DEBUG("PCI addr %s already in use", addr);
             VIR_FREE(addr);
             continue;
         }

+        VIR_DEBUG("Allocating PCI addr %s", addr);
+
         if (virHashAddEntry(addrs->used, addr, addr) < 0) {
             VIR_FREE(addr);
             return -1;
@@ -2246,6 +2253,8 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
         dev->addr.pci.slot = i;

         addrs->nextslot = i + 1;
+        if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
+            addrs->nextslot = 0;

         return 0;
     }
-- 
1.7.2

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]