On Thu, Aug 13, 2009 at 05:44:34PM +0100, Mark McLoughlin wrote: > 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() > --- > 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 041e3da..ed2f3c4 100644 > --- a/src/qemu_driver.c > +++ b/src/qemu_driver.c > @@ -1402,6 +1402,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 const char *const defaultDeviceACL[] = { > "/dev/null", "/dev/full", "/dev/zero", > "/dev/random", "/dev/urandom", > @@ -2109,6 +2183,8 @@ static void qemudShutdownVMDaemon(virConnectPtr conn, > VIR_WARN("Failed to restore all device ownership for %s", > vm->def->name); > > + qemuDomainReAttachHostDevices(conn, vm->def); > + > retry: > if ((ret = qemuRemoveCgroup(conn, driver, vm)) < 0) { > if (ret == -EBUSY && (retries++ < 5)) { ACk Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list