[libvirt] [PATCH 5/8] Reset and re-attach PCI host devices on guest shutdown

Daniel P. Berrange berrange at redhat.com
Thu Aug 13 18:42:38 UTC 2009


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 :|




More information about the libvir-list mailing list