[libvirt] [PATCH v2 7/8] qemu: Remove devices only after DEVICE_DELETED event

Daniel P. Berrange berrange at redhat.com
Thu Jul 18 10:41:38 UTC 2013


On Thu, Jul 18, 2013 at 12:03:49PM +0200, Jiri Denemark wrote:
> ---
> 
> Notes:
>     Version 2:
>     - DEVICE_DELETED event handler always removes the device
>     - wait for up to 5 seconds after device_del returns to make
>       async removal synchronous in normal cases
> 
>  src/qemu/qemu_domain.c  |   4 ++
>  src/qemu/qemu_domain.h  |   3 +
>  src/qemu/qemu_hotplug.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++--
>  src/qemu/qemu_hotplug.h |   7 +++
>  src/qemu/qemu_process.c |  32 ++++++++++
>  5 files changed, 199 insertions(+), 6 deletions(-)

> +static void
> +qemuDomainMarkDeviceForRemoval(virDomainObjPtr vm,
> +                               virDomainDeviceInfoPtr info)
> +{
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +
> +    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
> +        priv->unpluggingDevice = info->alias;
> +    else
> +        priv->unpluggingDevice = NULL;
> +}

Ok, this is safe because the callers have locked 'vm'.

> +static void
> +qemuDomainResetDeviceRemoval(virDomainObjPtr vm)
> +{
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    priv->unpluggingDevice = NULL;
> +}

likewise here

> +
> +/* Returns:
> + *  -1 on error
> + *   0 when DEVICE_DELETED event is unsupported
> + *   1 when device removal finished
> + *   2 device removal did not finish in QEMU_REMOVAL_WAIT_TIME
> + */
> +static int
> +qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
> +{
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    unsigned long long until;
> +
> +    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
> +        return 0;
> +
> +    if (virTimeMillisNow(&until) < 0)
> +        return -1;
> +    until += QEMU_REMOVAL_WAIT_TIME;
> +
> +    while (priv->unpluggingDevice) {
> +        if (virCondWaitUntil(&priv->unplugFinished,
> +                             &vm->parent.lock, until) < 0) {
> +            if (errno == ETIMEDOUT) {
> +                return 2;
> +            } else {
> +                virReportSystemError(errno, "%s",
> +                                     _("Unable to wait on unplug condition"));
> +                return -1;
> +            }
> +        }
> +    }
> +
> +    return 1;
> +}

and virCondWaitUntil is unlocking the 'vm', but this is
safe too, since we're inside a BeginJob block which holds
an extra reference.

> +static int
> +qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> +                               virDomainObjPtr vm,
> +                               const char *devAlias)
> +{
> +    virQEMUDriverPtr driver = qemu_driver;
> +    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
> +    virDomainDeviceDef dev;
> +
> +    virObjectLock(vm);
> +
> +    VIR_DEBUG("Device %s removed from domain %p %s",
> +              devAlias, vm, vm->def->name);
> +
> +    qemuDomainSignalDeviceRemoval(vm, devAlias);
> +
> +    if (virDomainDefFindDevice(vm->def, devAlias, &dev) < 0)
> +        goto cleanup;
> +
> +    qemuDomainRemoveDevice(driver, vm, &dev);
> +
> +    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
> +        VIR_WARN("unable to save domain status with balloon change");
> +
> +cleanup:
> +    virObjectUnlock(vm);
> +    virObjectUnref(cfg);
> +    return 0;
> +}

Ok, and this holds the lock too. So this all looks correctly synchronized


ACK

Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list