[libvirt] [PATCHv3 02/16] blockjob: wire up qemu async virDomainBlockJobAbort
Laine Stump
laine at laine.org
Mon Apr 9 21:26:26 UTC 2012
On 04/06/2012 02:29 PM, 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>
> ---
> 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 d9e35be..5f0eb05 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -11599,7 +11599,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;
> @@ -11641,6 +11641,45 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base,
> ret = qemuMonitorBlockJob(priv->mon, device, base, bandwidth, info, mode);
> qemuDomainObjExitMonitorWithDriver(driver, vm);
Do I understand correctly that qemu's abort was always asynchronous, and
prior to this, an abort call to libvirt would erroneously return
immediately? (I'm still trying to understand the code...)
>
> + /* 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;
Why is ret set to 1? It will be assigned the return value of
qemuMonitorBlockJob before it's ever used for anything, so this seems
unnecessary.
> + while (1) {
> + /* Poll every 50ms */
> + struct timespec ts = { .tv_sec = 0,
> + .tv_nsec = 50 * 1000 * 1000ull };
This timespec could just as well be static const, couldn't it? No big
deal one way or the other, though.
> + 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;
> @@ -11658,8 +11697,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
> @@ -11667,7 +11707,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
> @@ -11676,7 +11717,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
> @@ -11687,10 +11728,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;
> }
>
ACK once the items above are addressed (either by explaining, changing
code, or telling me why I'm wrong)
More information about the libvir-list
mailing list