[libvirt] [PATCH 12/13] blockjob: return appropriate event and info

Eric Blake eblake at redhat.com
Tue Apr 3 04:43:20 UTC 2012


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




More information about the libvir-list mailing list