[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