render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
7a3408
From 14b6b01cce6316d9df09f473592de303dce94084 Mon Sep 17 00:00:00 2001
7a3408
Message-Id: <14b6b01cce6316d9df09f473592de303dce94084@dist-git>
7a3408
From: Peter Krempa <pkrempa@redhat.com>
7a3408
Date: Tue, 21 Jul 2015 16:18:32 +0200
7a3408
Subject: [PATCH] qemu: Update state of block job to READY only if it actually
7a3408
 is ready
7a3408
7a3408
https://bugzilla.redhat.com/show_bug.cgi?id=1227551
7a3408
https://bugzilla.redhat.com/show_bug.cgi?id=1197592
7a3408
7a3408
Few parts of the code looked at the current progress of and assumed that
7a3408
a two phase blockjob is in the _READY state as soon as the progress
7a3408
reached 100% (info.cur == info.end). In current versions of qemu this
7a3408
assumption is invalid and qemu exposes a new flag 'ready' in the
7a3408
query-block-jobs output that is set to true if the job is actually
7a3408
finished.
7a3408
7a3408
This patch adds internal data handling for reading the 'ready' flag and
7a3408
acting appropriately as long as the flag is present.
7a3408
7a3408
While this still doesn't fix the virsh client problem with two phase
7a3408
block jobs and the --pivot option, it at least improves the error
7a3408
message:
7a3408
7a3408
$ virsh blockcommit  --wait --verbose vm vda  --base vda[1] --active --pivot
7a3408
Block commit: [100 %]error: failed to pivot job for disk vda
7a3408
error: internal error: unable to execute QEMU command 'block-job-complete': The active block job for device 'drive-virtio-disk0' cannot be completed
7a3408
7a3408
to
7a3408
7a3408
$ virsh blockcommit  --wait --verbose VM vda  --base vda[1] --active --pivot
7a3408
Block commit: [100 %]error: failed to pivot job for disk vda
7a3408
error: block copy still active: disk 'vda' not ready for pivot yet
7a3408
7a3408
(cherry picked from commit eae59247c59aa02147b2b4a50177e8e877fdb218)
7a3408
7a3408
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
7a3408
---
7a3408
 src/qemu/qemu_driver.c       | 10 ++++++++--
7a3408
 src/qemu/qemu_monitor.h      |  1 +
7a3408
 src/qemu/qemu_monitor_json.c |  7 +++++++
7a3408
 3 files changed, 16 insertions(+), 2 deletions(-)
7a3408
7a3408
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
7a3408
index 47889d9..204ed72 100644
7a3408
--- a/src/qemu/qemu_driver.c
7a3408
+++ b/src/qemu/qemu_driver.c
7a3408
@@ -16170,8 +16170,12 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
7a3408
             goto cleanup;
7a3408
         if (rc < 0)
7a3408
             goto cleanup;
7a3408
-        if (rc == 1 && info.cur == info.end &&
7a3408
-            info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
7a3408
+        if (rc == 1 &&
7a3408
+            (info.ready == 1 ||
7a3408
+             (info.ready == -1 &&
7a3408
+              info.end == info.cur &&
7a3408
+              (info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY ||
7a3408
+               info.type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT))))
7a3408
             disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
7a3408
     }
7a3408
 
7a3408
@@ -16569,6 +16573,7 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom,
7a3408
      * hold the vm lock, so modifying the in-memory representation is
7a3408
      * safe, even if we are a query rather than a modify job. */
7a3408
     if (ret == 1 && disk->mirror &&
7a3408
+        rawInfo.ready != 0 &&
7a3408
         info->cur == info->end && !disk->mirrorState) {
7a3408
         virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
7a3408
 
7a3408
@@ -17199,6 +17204,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
7a3408
      * thing if the user specified a relative name).  Be prepared for
7a3408
      * a ready event to occur while locks are dropped.  */
7a3408
     if (mirror) {
7a3408
+        disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
7a3408
         disk->mirror = mirror;
7a3408
         disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
7a3408
     }
7a3408
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
7a3408
index 8ad3b2b..fc58638 100644
7a3408
--- a/src/qemu/qemu_monitor.h
7a3408
+++ b/src/qemu/qemu_monitor.h
7a3408
@@ -798,6 +798,7 @@ struct _qemuMonitorBlockJobInfo {
7a3408
     unsigned long long bandwidth; /* in bytes/s */
7a3408
     virDomainBlockJobCursor cur;
7a3408
     virDomainBlockJobCursor end;
7a3408
+    int ready; /* -1 if unknown, 0 if not ready, 1 if ready */
7a3408
 };
7a3408
 
7a3408
 virHashTablePtr qemuMonitorGetAllBlockJobInfo(qemuMonitorPtr mon);
7a3408
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
7a3408
index 4040ff0..d2a5374 100644
7a3408
--- a/src/qemu/qemu_monitor_json.c
7a3408
+++ b/src/qemu/qemu_monitor_json.c
7a3408
@@ -4136,6 +4136,7 @@ qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
7a3408
     qemuMonitorBlockJobInfoPtr info = NULL;
7a3408
     const char *device;
7a3408
     const char *type;
7a3408
+    bool ready;
7a3408
 
7a3408
     if (!(device = virJSONValueObjectGetString(entry, "device"))) {
7a3408
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7a3408
@@ -4151,6 +4152,9 @@ qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
7a3408
         return -1;
7a3408
     }
7a3408
 
7a3408
+    /* assume we don't know the state */
7a3408
+    info->ready = -1;
7a3408
+
7a3408
     if (!(type = virJSONValueObjectGetString(entry, "type"))) {
7a3408
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7a3408
                        _("entry was missing 'type'"));
7a3408
@@ -4183,6 +4187,9 @@ qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
7a3408
         return -1;
7a3408
     }
7a3408
 
7a3408
+    if (virJSONValueObjectGetBoolean(entry, "ready", &ready) == 0)
7a3408
+        info->ready = ready;
7a3408
+
7a3408
     return 0;
7a3408
 }
7a3408
 
7a3408
-- 
7a3408
2.5.0
7a3408