]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
qemu: Update state of block job to READY only if it actually is ready
authorPeter Krempa <pkrempa@redhat.com>
Wed, 15 Jul 2015 13:11:02 +0000 (15:11 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 21 Jul 2015 13:32:59 +0000 (15:32 +0200)
Few parts of the code looked at the current progress of and assumed that
a two phase blockjob is in the _READY state as soon as the progress
reached 100% (info.cur == info.end). In current versions of qemu this
assumption is invalid and qemu exposes a new flag 'ready' in the
query-block-jobs output that is set to true if the job is actually
finished.

This patch adds internal data handling for reading the 'ready' flag and
acting appropriately as long as the flag is present.

While this still doesn't fix the virsh client problem with two phase
block jobs and the --pivot option, it at least improves the error
message:

$ virsh blockcommit  --wait --verbose vm vda  --base vda[1] --active --pivot
Block commit: [100 %]error: failed to pivot job for disk vda
error: internal error: unable to execute QEMU command 'block-job-complete': The active block job for device 'drive-virtio-disk0' cannot be completed

to

$ virsh blockcommit  --wait --verbose VM vda  --base vda[1] --active --pivot
Block commit: [100 %]error: failed to pivot job for disk vda
error: block copy still active: disk 'vda' not ready for pivot yet

src/qemu/qemu_driver.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c

index 9dbe6355b7ba10ca16a8f29f62c99b237e5da50c..61a7a7cc2c686ba6b4be30a58f44f5c16f42c574 100644 (file)
@@ -16091,8 +16091,12 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
             goto cleanup;
         if (rc < 0)
             goto cleanup;
-        if (rc == 1 && info.cur == info.end &&
-            info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
+        if (rc == 1 &&
+            (info.ready == 1 ||
+             (info.ready == -1 &&
+              info.end == info.cur &&
+              (info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY ||
+               info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT))))
             disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
     }
 
@@ -16490,6 +16494,7 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom,
      * hold the vm lock, so modifying the in-memory representation is
      * safe, even if we are a query rather than a modify job. */
     if (ret == 1 && disk->mirror &&
+        rawInfo.ready != 0 &&
         info->cur == info->end && !disk->mirrorState) {
         virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
 
@@ -17120,6 +17125,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
      * thing if the user specified a relative name).  Be prepared for
      * a ready event to occur while locks are dropped.  */
     if (mirror) {
+        disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
         disk->mirror = mirror;
         disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
     }
index 1e7b6bb78777145dcd3bf87e3446782ec8f29344..85ea8222f03ae87911ac12bf7c0ceda879f522a9 100644 (file)
@@ -797,6 +797,7 @@ struct _qemuMonitorBlockJobInfo {
     unsigned long long bandwidth; /* in bytes/s */
     virDomainBlockJobCursor cur;
     virDomainBlockJobCursor end;
+    int ready; /* -1 if unknown, 0 if not ready, 1 if ready */
 };
 
 virHashTablePtr qemuMonitorGetAllBlockJobInfo(qemuMonitorPtr mon);
index ff568d92047b4000acefa854bdfe3a3c08d69225..5c2f50ffaa2c50386d7a992404e05ce10087f9e3 100644 (file)
@@ -4027,6 +4027,7 @@ qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
     qemuMonitorBlockJobInfoPtr info = NULL;
     const char *device;
     const char *type;
+    bool ready;
 
     if (!(device = virJSONValueObjectGetString(entry, "device"))) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -4042,6 +4043,9 @@ qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
         return -1;
     }
 
+    /* assume we don't know the state */
+    info->ready = -1;
+
     if (!(type = virJSONValueObjectGetString(entry, "type"))) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("entry was missing 'type'"));
@@ -4074,6 +4078,9 @@ qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
         return -1;
     }
 
+    if (virJSONValueObjectGetBoolean(entry, "ready", &ready) == 0)
+        info->ready = ready;
+
     return 0;
 }