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