[libvirt] [PATCH v3 5/6] qemuMigrationDriveMirror: utilize blockJob condition
Jiri Denemark
jdenemar at redhat.com
Thu Feb 19 12:50:01 UTC 2015
On Fri, Feb 13, 2015 at 16:24:32 +0100, Michal Privoznik wrote:
> Instead of unlocking and locking the domain object every 50ms
> lets just wait on blockJob condition and run the loop body if and
> BLOCK_JOB even occurred.
>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
> src/qemu/qemu_migration.c | 15 +++++----------
> src/qemu/qemu_process.c | 4 ++++
> 2 files changed, 9 insertions(+), 10 deletions(-)
>
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index 14a4ec6..998e8f5 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -1768,9 +1768,6 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
>
> /* wait for completion */
> while (true) {
> - /* Poll every 500ms for progress & to allow cancellation */
> - struct timespec ts = { .tv_sec = 0, .tv_nsec = 500 * 1000 * 1000ull };
> -
> /* Explicitly check if domain is still alive. Maybe qemu
> * died meanwhile so we won't see any event at all. */
> if (!virDomainObjIsActive(vm)) {
> @@ -1800,13 +1797,11 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
> goto error;
> }
>
> - /* XXX Turn this into virCond someday. */
> -
> - virObjectUnlock(vm);
> -
> - nanosleep(&ts, NULL);
> -
> - virObjectLock(vm);
> + if (virCondWait(&priv->blockJob, &vm->parent.lock) < 0) {
Hmm, you'd also need to signal this condition on EOF, otherwise this
could be waiting forever when the domain dies during drive mirror job.
But see below...
> + virReportSystemError(errno, "%s",
> + _("Unable to wait on blockJob condition"));
> + goto error;
> + }
> }
> }
>
The main problem with this patch is hidden in the (missing) context:
if (priv->job.asyncAbort) {
priv->job.current->type = VIR_DOMAIN_JOB_CANCELLED;
virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
_("canceled by client"));
goto error;
}
The loop would never break when priv->job.asyncAbort is set because it
would still be waiting for priv->blockJob to be signalled. So we need to
somehow turn this into a condition too. And because there's no way we
could wait for more conditions at once, we'll need to think more what to
do. One possibility is to create a general jobCond which would be
signalled in several places: when asyncAbort is set, when block job
changes its state, on monitor EOF, ...
Jirka
More information about the libvir-list
mailing list