During a block copy, we want to tweak the events that get output: - a successful block pull means we have transitioned to mirroring - a failed block pull affects what the next abort will do - a canceled block pull must not generate an event yet (that event gets delayed until after the drive-reopen) We also want to output a job info that indicates whether the job has transitioned to mirroring, even though qemu's 'query-block-jobs' quits giving information at that point. Of course, this patch does nothing until a later patch actually allows the creation of a block copy job. * src/qemu/qemu_process.c (qemuProcessHandleBlockJob): tweak event to reflect transition to mirroring * src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): provide info after event --- src/qemu/qemu_driver.c | 25 ++++++++++++++++++++++++- src/qemu/qemu_process.c | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 53189b5..1664e14 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11666,12 +11666,35 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base, ret = qemuMonitorBlockJob(priv->mon, device, base, bandwidth, info, mode); qemuDomainObjExitMonitorWithDriver(driver, vm); + if (ret < 0) + goto cleanup; + + /* A block copy operation must provide info back to the user, even + * when it has transitioned to the mirroring stage. */ + if (mode == BLOCK_JOB_INFO && vm->def->disks[idx]->mirror) { + if (!vm->def->disks[idx]->mirrorStage) { + qemuReportError(VIR_ERR_OPERATION_FAILED, _("copy to '%s' failed"), + vm->def->disks[idx]->mirror); + ret = -1; + goto cleanup; + } + if (ret == 0) { + vm->def->disks[idx]->mirrorStage = + VIR_DOMAIN_DISK_MIRROR_STAGE_MIRRORING; + info->bandwidth = 0; + info->cur = 1; + info->end = 1; + } + info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY; + ret = 1; + } + /* 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 && + if (mode == BLOCK_JOB_ABORT && !(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC)) { ret = 1; while (1) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9eed160..bd020b6 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -903,9 +903,28 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED, if (disk) { path = disk->src; + if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL) { + type = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY; + switch ((virConnectDomainEventBlockJobStatus) status) { + case VIR_DOMAIN_BLOCK_JOB_COMPLETED: + status = VIR_DOMAIN_BLOCK_JOB_MIRRORING; + disk->mirrorStage = VIR_DOMAIN_DISK_MIRROR_STAGE_MIRRORING; + break; + case VIR_DOMAIN_BLOCK_JOB_FAILED: + disk->mirrorStage = VIR_DOMAIN_DISK_MIRROR_STAGE_ERROR; + break; + case VIR_DOMAIN_BLOCK_JOB_CANCELED: + goto cleanup; + case VIR_DOMAIN_BLOCK_JOB_MIRRORING: + case VIR_DOMAIN_BLOCK_JOB_LAST: + VIR_DEBUG("should not reach here"); + goto cleanup; + } + } event = virDomainEventBlockJobNewFromObj(vm, path, type, status); } +cleanup: virDomainObjUnlock(vm); if (event) { -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list