Currently, PCI devices will not be rebound to host drivers but
attached to the stub driver when:
1) use libvirt to start a virtual machine with PCI devices assigned,
then stop libvirtd process and shutdown the virtual machine. Finally,
PCI devices are still bound to the stub driver instead of host drivers
after libvirt start again.
2) use libvirt to shutdown a virtual machine wtih PCI devices assigned,
then stop libvirtd process before libvirt try to rebind PCI devices to
host drivers. Finally, PCI devices are still bound to the stub driver
after libvirt start again.
Notice that the comment on the top of virPCIDeviceDetach as follows:
activeDevs should be a list of all PCI devices currently in use by a
domain.inactiveDevs is a list of all PCI devices that libvirt has
detached from the host driver + attached to the stub driver, but
hasn't yet assigned to a domain.
It's not reasonable that libvirt filter out devices that are either not
active or not used by the current domain and driver. For devices belong
to domains that has been shutdown before libvirt start, we should put
them into inactiveDevs if then meet the condition that PCI devices have
been detached from the host driver + attached to the stub driver.
Moreover, we set orignal states of PCI devices when build PCI devices
list in virHostdevGetPCIHostDeviceList if states has been set in struct
virDomainHostdevDefPtr.
Signed-off-by: Wu Zongyong <cordius.wu(a)huawei.com>
---
src/util/virhostdev.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index ca79c37..ecf95e3 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -235,6 +235,7 @@ virHostdevGetPCIHostDeviceList(virDomainHostdevDefPtr *hostdevs, int
nhostdevs)
for (i = 0; i < nhostdevs; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i];
virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
+ virDomainHostdevOrigStatesPtr origstates = &hostdev->origstates;
virPCIDevicePtr pci;
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
@@ -262,6 +263,10 @@ virHostdevGetPCIHostDeviceList(virDomainHostdevDefPtr *hostdevs, int
nhostdevs)
virPCIDeviceSetStubDriver(pci, VIR_PCI_STUB_DRIVER_XEN);
else
virPCIDeviceSetStubDriver(pci, VIR_PCI_STUB_DRIVER_KVM);
+
+ virPCIDeviceSetUnbindFromStub(pci, origstates->states.pci.unbind_from_stub);
+ virPCIDeviceSetRemoveSlot(pci, origstates->states.pci.remove_slot);
+ virPCIDeviceSetReprobe(pci, origstates->states.pci.reprobe);
}
return pcidevs;
@@ -1008,8 +1013,19 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr mgr,
continue;
}
} else {
- virPCIDeviceListDel(pcidevs, pci);
- continue;
+ int stub = virPCIDeviceGetStubDriver(pci);
+ if (stub > VIR_PCI_STUB_DRIVER_NONE &&
+ stub < VIR_PCI_STUB_DRIVER_LAST) {
+ /* The device is bound to a known stub driver: add a copy
+ * to the inactive list */
+ VIR_DEBUG("Adding PCI device %s to inactive list",
+ virPCIDeviceGetName(pci));
+ if (virPCIDeviceListAddCopy(mgr->inactivePCIHostdevs, pci) < 0) {
+ VIR_ERROR(_("Failed to add PCI device %s to the inactive
list"),
+ virGetLastErrorMessage());
+ virResetLastError();
+ }
+ }
}
i++;
--
1.9.1