529d097d28
- Allow PCI bus reset to reset other devices (#499678) - Fix stupid PCI reset error message (bug #499678) - Allow PM reset on multi-function PCI devices (bug #515689) - Re-attach PCI host devices after guest shuts down (bug #499561) - Fixes list corruption after disk hot-unplug - Fix minor 'virsh nodedev-list --tree' annoyance
125 lines
4.2 KiB
Diff
125 lines
4.2 KiB
Diff
From 1e44604c0d4c2d4c1347c2a1027f1ea02a6499f9 Mon Sep 17 00:00:00 2001
|
|
From: Mark McLoughlin <markmc@redhat.com>
|
|
Date: Fri, 14 Aug 2009 08:31:11 +0100
|
|
Subject: [PATCH] Reset and re-attach PCI host devices on guest shutdown
|
|
|
|
https://bugzilla.redhat.com/499561
|
|
|
|
When the guest shuts down, we should attempt to restore all PCI host
|
|
devices to a sane state.
|
|
|
|
In the case of managed hostdevs, we should reset and re-attach the
|
|
devices. In the case of unmanaged hostdevs, we should just reset them.
|
|
|
|
Note, KVM will already reset assigned devices when the guest shuts
|
|
down using whatever means it can, so we are only doing it to cover the
|
|
cases the kernel can't handle.
|
|
|
|
* src/qemu_driver.c: add qemuDomainReAttachHostDevices() and call
|
|
it from qemudShutdownVMDaemon()
|
|
|
|
(cherry picked from commit 4035152a8767e72fd4e26a91cb4d5afa75b72e61)
|
|
|
|
Fedora-patch: libvirt-reattach-pci-hostdevs-after-guest-shutdown.patch
|
|
---
|
|
src/qemu_driver.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 files changed, 76 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
|
|
index ce04beb..ddd3693 100644
|
|
--- a/src/qemu_driver.c
|
|
+++ b/src/qemu_driver.c
|
|
@@ -1282,6 +1282,80 @@ error:
|
|
return -1;
|
|
}
|
|
|
|
+static void
|
|
+qemuDomainReAttachHostDevices(virConnectPtr conn, virDomainDefPtr def)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ /* Again 2 loops; reset all the devices before re-attach */
|
|
+
|
|
+ for (i = 0 ; i < def->nhostdevs ; i++) {
|
|
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
|
|
+ pciDevice *dev;
|
|
+
|
|
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
+ continue;
|
|
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
+ continue;
|
|
+
|
|
+ dev = pciGetDevice(conn,
|
|
+ hostdev->source.subsys.u.pci.domain,
|
|
+ hostdev->source.subsys.u.pci.bus,
|
|
+ hostdev->source.subsys.u.pci.slot,
|
|
+ hostdev->source.subsys.u.pci.function);
|
|
+ if (!dev) {
|
|
+ virErrorPtr err = virGetLastError();
|
|
+ VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
|
|
+ err ? err->message : "");
|
|
+ virResetError(err);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (pciResetDevice(conn, dev) < 0) {
|
|
+ virErrorPtr err = virGetLastError();
|
|
+ VIR_ERROR(_("Failed to reset PCI device: %s\n"),
|
|
+ err ? err->message : "");
|
|
+ virResetError(err);
|
|
+ }
|
|
+
|
|
+ pciFreeDevice(conn, dev);
|
|
+ }
|
|
+
|
|
+ for (i = 0 ; i < def->nhostdevs ; i++) {
|
|
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
|
|
+ pciDevice *dev;
|
|
+
|
|
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
+ continue;
|
|
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
+ continue;
|
|
+ if (!hostdev->managed)
|
|
+ continue;
|
|
+
|
|
+ dev = pciGetDevice(conn,
|
|
+ hostdev->source.subsys.u.pci.domain,
|
|
+ hostdev->source.subsys.u.pci.bus,
|
|
+ hostdev->source.subsys.u.pci.slot,
|
|
+ hostdev->source.subsys.u.pci.function);
|
|
+ if (!dev) {
|
|
+ virErrorPtr err = virGetLastError();
|
|
+ VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
|
|
+ err ? err->message : "");
|
|
+ virResetError(err);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (pciDettachDevice(conn, dev) < 0) {
|
|
+ virErrorPtr err = virGetLastError();
|
|
+ VIR_ERROR(_("Failed to reset PCI device: %s\n"),
|
|
+ err ? err->message : "");
|
|
+ virResetError(err);
|
|
+ }
|
|
+
|
|
+ pciFreeDevice(conn, dev);
|
|
+ }
|
|
+}
|
|
+
|
|
static int qemudDomainSetSecurityLabel(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm)
|
|
{
|
|
if (vm->def->seclabel.label != NULL)
|
|
@@ -1560,6 +1634,8 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
VIR_FREE(vm->def->seclabel.imagelabel);
|
|
}
|
|
|
|
+ qemuDomainReAttachHostDevices(conn, vm->def);
|
|
+
|
|
if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
|
|
VIR_WARN(_("Failed to remove domain status for %s"),
|
|
vm->def->name);
|
|
--
|
|
1.6.2.5
|
|
|