[libvirt] [PATCH 4/7] qemu: hotplug: Add support for signalling device unplug failure

Cole Robinson crobinso at redhat.com
Tue Apr 12 23:44:17 UTC 2016


On 04/05/2016 11:09 AM, Peter Krempa wrote:
> Similarly to the DEVICE_DELETED event we will be able to tell when
> unplug of certain device types will be rejected by the guest OS. Wire up
> the device deletion signalling code to allow handling this.
> ---
>  src/qemu/qemu_domain.h  | 17 ++++++++++++++++-
>  src/qemu/qemu_hotplug.c | 30 +++++++++++++++++++++---------
>  src/qemu/qemu_hotplug.h |  3 ++-
>  src/qemu/qemu_process.c |  2 +-
>  4 files changed, 40 insertions(+), 12 deletions(-)
> 

There's a slight conflict here with git master but it should rebase cleanly,
git am --3way couldn't handle it for me for whatever reason

> diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
> index 2b92a90..84b4b16 100644
> --- a/src/qemu/qemu_domain.h
> +++ b/src/qemu/qemu_domain.h
> @@ -148,6 +148,20 @@ struct qemuDomainJobObj {
>  typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver,
>                                            virDomainObjPtr vm);
> 
> +/* helper data types for async device unplug */
> +typedef enum {
> +    QEMU_DOMAIN_UNPLUG_DEVICE_STATUS_NONE = 0,
> +    QEMU_DOMAIN_UNPLUG_DEVICE_STATUS_OK,
> +    QEMU_DOMAIN_UNPLUG_DEVICE_STATUS_GUEST_REJECTED,
> +} qemuDomainUnplugDeviceStatus;
> +
> +typedef struct _qemuDomainUnplugDevice qemuDomainUnplugDevice;
> +typedef qemuDomainUnplugDevice *qemuDomainUnplugDevicePtr;
> +struct _qemuDomainUnplugDevice {
> +    const char *alias;
> +    qemuDomainUnplugDeviceStatus status;
> +};
> +
>  typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
>  typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
>  struct _qemuDomainObjPrivate {
> @@ -198,7 +212,8 @@ struct _qemuDomainObjPrivate {
> 
>      virPerfPtr perf;
> 
> -    const char *unpluggingDevice; /* alias of the device that is being unplugged */
> +    qemuDomainUnplugDevice unplug;
> +

FWIW in isolation I'd think 'qemuDomainUnplugDevice' was a function name...
maybe stick with the UnpluggingDevice name. Not a NACK, just an idea if you're
motivated. Also lack Ptr use just looks weird, I'm so used to everything being
a Ptr in libvirt code :)

>      char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
> 
>      bool hookRun;  /* true if there was a hook run over this domain */
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index 134f458..bd0599f 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -3337,20 +3337,24 @@ qemuDomainMarkDeviceForRemoval(virDomainObjPtr vm,
>  {
>      qemuDomainObjPrivatePtr priv = vm->privateData;
> 
> -    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
> -        priv->unpluggingDevice = info->alias;
> -    else
> -        priv->unpluggingDevice = NULL;
> +    memset(&priv->unplug, 0, sizeof(priv->unplug));
> +
> +    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
> +        return;
> +
> +    priv->unplug.alias = info->alias;
>  }
> 
>  static void
>  qemuDomainResetDeviceRemoval(virDomainObjPtr vm)
>  {
>      qemuDomainObjPrivatePtr priv = vm->privateData;
> -    priv->unpluggingDevice = NULL;
> +    priv->unplug.alias = NULL;
>  }
> 
>  /* Returns:
> + *  -1 Unplug of the device failed
> + *
>   *   0 DEVICE_DELETED event is supported and removal of the device did not
>   *     finish in qemuDomainRemoveDeviceWaitTime
>   *
> @@ -3373,17 +3377,23 @@ qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
>          return 1;
>      until += qemuDomainRemoveDeviceWaitTime;
> 
> -    while (priv->unpluggingDevice) {
> +    while (priv->unplug.alias) {
>          if ((rc = virDomainObjWaitUntil(vm, until)) == 1)
>              return 0;
> 
>          if (rc < 0) {
>              VIR_WARN("Failed to wait on unplug condition for domain '%s' "
> -                     "device '%s'", vm->def->name, priv->unpluggingDevice);
> +                     "device '%s'", vm->def->name, priv->unplug.alias);
>              return 1;
>          }
>      }
> 
> +    if (priv->unplug.status == QEMU_DOMAIN_UNPLUG_DEVICE_STATUS_GUEST_REJECTED) {
> +        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                       _("unplug of device was rejected by the guest"));
> +        return -1;
> +    }
> +
>      return 1;
>  }
> 

Okay, so 0 == didn't succeed in time, 1 == definitely succeeded OR we have no
way of knowing so assume it worked, -1 == definitely failed. That's a lot of
semantics :) But this makes sense, now when the -1 trickles up the stack, it's
when we know for certain that the hotplug failed.

ACK

- Cole

> @@ -3395,12 +3405,14 @@ qemuDomainWaitForDeviceRemoval(virDomainObjPtr vm)
>   */
>  bool
>  qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
> -                              const char *devAlias)
> +                              const char *devAlias,
> +                              qemuDomainUnplugDeviceStatus status)
>  {
>      qemuDomainObjPrivatePtr priv = vm->privateData;
> 
> -    if (STREQ_NULLABLE(priv->unpluggingDevice, devAlias)) {
> +    if (STREQ_NULLABLE(priv->unplug.alias, devAlias)) {
>          qemuDomainResetDeviceRemoval(vm);
> +        priv->unplug.status = status;
>          virDomainObjBroadcast(vm);
>          return true;
>      }
> diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
> index 4140da3..e6833f0 100644
> --- a/src/qemu/qemu_hotplug.h
> +++ b/src/qemu/qemu_hotplug.h
> @@ -122,6 +122,7 @@ int qemuDomainRemoveDevice(virQEMUDriverPtr driver,
>                             virDomainDeviceDefPtr dev);
> 
>  bool qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
> -                                   const char *devAlias);
> +                                   const char *devAlias,
> +                                   qemuDomainUnplugDeviceStatus status);
> 
>  #endif /* __QEMU_HOTPLUG_H__ */
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index d9dca74..bbde32c 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -1359,7 +1359,7 @@ qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
>      VIR_DEBUG("Device %s removed from domain %p %s",
>                devAlias, vm, vm->def->name);
> 
> -    if (qemuDomainSignalDeviceRemoval(vm, devAlias))
> +    if (qemuDomainSignalDeviceRemoval(vm, devAlias, QEMU_DOMAIN_UNPLUG_DEVICE_STATUS_OK))
>          goto cleanup;
> 
>      if (VIR_ALLOC(processEvent) < 0)
> 




More information about the libvir-list mailing list