BZ#
https://bugzilla.redhat.com/show_bug.cgi?id=736214
The problem is caused by the original info of domain's PCI dev is
maintained by qemu_driver->activePciHostdevs list, (E.g. dev->reprobe,
which stands for whether need to reprobe driver for the dev when do
reattachment). The fields (dev->reprobe, dev->unbind_from_stub, and
dev->remove_slot) are initialized properly when preparing the PCI
device for managed attachment. However, when do reattachment, it
construct a complete new "pciDevice" without honoring the original
dev info, and thus the dev won't get the original driver or can get
other problem.
This patch is to fix the problem by get the dev from list
driver->activePciHostdevs if it's in the list, though it's unlikely
the dev to be reattached is not in the list, as any PCI dev is added
to the list when do preparation (qemuPrepareHostdevPCIDevices),
the patch doesn't completely desert the old design so the device
can be reattached even if it's not in list driver->activePciHostdevs.
--
v1 patch to fix this problem is:
http://www.redhat.com/archives/libvir-list/2011-September/msg01101.html
But the patch title is complete different, so I don't send this and
a v2.
---
src/qemu/qemu_hostdev.c | 23 +++++++++++++++++++++--
1 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index 6f77717..73cadc5 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -262,6 +262,7 @@ void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
int nhostdevs)
{
pciDeviceList *pcidevs;
+ pciDeviceList *pci_list = NULL;
int i;
if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs))) {
@@ -272,12 +273,23 @@ void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
return;
}
+ if (!(pci_list = pciDeviceListNew()))
+ return;
+
/* Again 3 loops; mark all devices as inactive before reset
* them and reset all the devices before re-attach */
-
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i);
- pciDeviceListDel(driver->activePciHostdevs, dev);
+ pciDevice *pci = NULL;
+ pci = pciDeviceListSteal(driver->activePciHostdevs, dev);
+
+ if (pci) {
+ pciDeviceListDel(pcidevs, dev);
+ if (pciDeviceListAdd(pci_list, pci) < 0) {
+ pciFreeDevice(pci);
+ goto cleanup;
+ }
+ }
}
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
@@ -290,11 +302,18 @@ void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
}
}
+ for (i = 0; i < pciDeviceListCount(pci_list); i++) {
+ pciDevice *dev = pciDeviceListGet(pci_list, i);
+ qemuReattachPciDevice(dev, driver);
+ }
+
for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i);
qemuReattachPciDevice(dev, driver);
}
+cleanup:
+ pciDeviceListFree(pci_list);
pciDeviceListFree(pcidevs);
}
--
1.7.6