[libvirt] [PATCHv2 02/15] blockjob: wire up qemu async virDomainBlockJobAbort

Adam Litke agl at us.ibm.com
Fri Apr 6 13:14:46 UTC 2012


On Thu, Apr 05, 2012 at 10:36:48PM -0600, Eric Blake wrote:
> From: Adam Litke <agl at us.ibm.com>
> 
> Without the VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC flag, libvirt will internally poll
> using qemu's "query-block-jobs" API and will not return until the operation has
> been completed.  API users are advised that this operation is unbounded and
> further interaction with the domain during this period may block.  Future
> patches may refactor things to allow other queries in parallel with this
> polling.  Unfortunately, there's no good way to tell if qemu will emit the
> new event, so this implementation always polls to deal with older qemu.
> 
> Signed-off-by: Adam Litke <agl at us.ibm.com>
> Cc: Stefan Hajnoczi <stefanha at gmail.com>
> Signed-off-by: Eric Blake <eblake at redhat.com>

Tested-by: Adam Litke <agl at us.ibm.com>

> ---
>  src/qemu/qemu_driver.c |   55 +++++++++++++++++++++++++++++++++++++++++------
>  1 files changed, 48 insertions(+), 7 deletions(-)
> 
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 0456b34..455fa30 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -11602,7 +11602,7 @@ cleanup:
>  static int
>  qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base,
>                         unsigned long bandwidth, virDomainBlockJobInfoPtr info,
> -                       int mode)
> +                       int mode, unsigned int flags)
>  {
>      struct qemud_driver *driver = dom->conn->privateData;
>      virDomainObjPtr vm = NULL;
> @@ -11644,6 +11644,45 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base,
>      ret = qemuMonitorBlockJob(priv->mon, device, base, bandwidth, info, mode);
>      qemuDomainObjExitMonitorWithDriver(driver, vm);
> 
> +    /* Qemu provides asynchronous block job cancellation, but without
> +     * the VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC flag libvirt guarantees a
> +     * synchronous operation.  Provide this behavior by waiting here,
> +     * so we don't get confused by newly scheduled block jobs.
> +     */
> +    if (ret == 0 && mode == BLOCK_JOB_ABORT &&
> +        !(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC)) {
> +        ret = 1;
> +        while (1) {
> +            /* Poll every 50ms */
> +            struct timespec ts = { .tv_sec = 0,
> +                                   .tv_nsec = 50 * 1000 * 1000ull };
> +            virDomainBlockJobInfo dummy;
> +
> +            qemuDomainObjEnterMonitorWithDriver(driver, vm);
> +            ret = qemuMonitorBlockJob(priv->mon, device, NULL, 0, &dummy,
> +                                      BLOCK_JOB_INFO);
> +            qemuDomainObjExitMonitorWithDriver(driver, vm);
> +
> +            if (ret <= 0)
> +                break;
> +
> +            virDomainObjUnlock(vm);
> +            qemuDriverUnlock(driver);
> +
> +            nanosleep(&ts, NULL);
> +
> +            qemuDriverLock(driver);
> +            virDomainObjLock(vm);
> +
> +            if (!virDomainObjIsActive(vm)) {
> +                qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                                _("domain is not running"));
> +                ret = -1;
> +                break;
> +            }
> +        }
> +    }
> +
>  endjob:
>      if (qemuDomainObjEndJob(driver, vm) == 0) {
>          vm = NULL;
> @@ -11661,8 +11700,9 @@ cleanup:
>  static int
>  qemuDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int flags)
>  {
> -    virCheckFlags(0, -1);
> -    return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT);
> +    virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC, -1);
> +    return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT,
> +                                  flags);
>  }
> 
>  static int
> @@ -11670,7 +11710,8 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path,
>                             virDomainBlockJobInfoPtr info, unsigned int flags)
>  {
>      virCheckFlags(0, -1);
> -    return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO);
> +    return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO,
> +                                  flags);
>  }
> 
>  static int
> @@ -11679,7 +11720,7 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path,
>  {
>      virCheckFlags(0, -1);
>      return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
> -                                  BLOCK_JOB_SPEED);
> +                                  BLOCK_JOB_SPEED, flags);
>  }
> 
>  static int
> @@ -11690,10 +11731,10 @@ qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
> 
>      virCheckFlags(0, -1);
>      ret = qemuDomainBlockJobImpl(dom, path, base, bandwidth, NULL,
> -                                 BLOCK_JOB_PULL);
> +                                 BLOCK_JOB_PULL, flags);
>      if (ret == 0 && bandwidth != 0)
>          ret = qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
> -                                     BLOCK_JOB_SPEED);
> +                                     BLOCK_JOB_SPEED, flags);
>      return ret;
>  }
> 
> -- 
> 1.7.7.6
> 

-- 
Adam Litke <agl at us.ibm.com>
IBM Linux Technology Center




More information about the libvir-list mailing list