Handle the new type of block copy event and info. Of course,
this patch does nothing until a later patch actually allows the
creation/abort of a block copy job. The new event is available
in qemu 1.3, but not in RHEL 6.3; rather than doing polling
ourselves to synthesize the event in RHEL 6.3, we just document
that the event might not occur.
* include/libvirt/libvirt.h.in (VIR_DOMAIN_BLOCK_JOB_READY): New
block job status.
* src/libvirt.c (virDomainBlockRebase): Document the event.
* src/qemu/qemu_monitor_json.c (eventHandlers): New event.
(qemuMonitorJSONHandleBlockJobReady): New function.
(qemuMonitorJSONGetBlockJobInfoOne): Translate new job type.
(qemuMonitorJSONHandleBlockJobImpl): Handle new event and job type.
* src/qemu/qemu_process.c (qemuProcessHandleBlockJob): Recognize
the event to minimize snooping.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Snoop a successful
info query to save effort on a pivot request.
---
include/libvirt/libvirt.h.in | 1 +
src/libvirt.c | 7 ++++---
src/qemu/qemu_driver.c | 6 ++++++
src/qemu/qemu_monitor_json.c | 19 +++++++++++++++++--
src/qemu/qemu_process.c | 2 ++
5 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index ca04f6c..ab7f3fe 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -3884,6 +3884,7 @@ typedef enum {
VIR_DOMAIN_BLOCK_JOB_COMPLETED = 0,
VIR_DOMAIN_BLOCK_JOB_FAILED = 1,
VIR_DOMAIN_BLOCK_JOB_CANCELED = 2,
+ VIR_DOMAIN_BLOCK_JOB_READY = 3,
#ifdef VIR_ENUM_SENTINELS
VIR_DOMAIN_BLOCK_JOB_LAST
diff --git a/src/libvirt.c b/src/libvirt.c
index 6e25baf..05724c3 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -18828,9 +18828,10 @@ error:
* mirror all further changes to both source and destination. The user
* must call virDomainBlockJobAbort() to end the mirroring while choosing
* whether to revert to source or pivot to the destination. An event is
- * issued when the job ends, and in the future, an event may be added when
- * the job transitions from pulling to mirroring. If the job is aborted,
- * a new job will have to start over from the beginning of the first phase.
+ * issued when the job ends, and depending on the hypervisor, an event may
+ * also be issued when the job transitions from pulling to mirroring. If
+ * the job is aborted, a new job will have to start over from the beginning
+ * of the first phase.
*
* Some hypervisors will restrict certain actions, such as virDomainSave()
* or virDomainDetachDevice(), while a copy job is active; they may
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index df77df1..e8f42f2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12687,6 +12687,12 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const
char *base,
if (ret < 0)
goto endjob;
+ /* Snoop block copy operations, so future cancel operations can
+ * avoid checking if pivot is safe. */
+ if (mode == BLOCK_JOB_INFO && ret == 1 && disk->mirror &&
+ info->cur == info->end && info->type ==
VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
+ disk->mirroring = true;
+
/* With synchronous block cancel, we must synthesize an event, and
* we silently ignore the ABORT_ASYNC flag. With asynchronous
* block cancel, the event will come from qemu, but without the
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index a223c08..b23be1e 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -69,6 +69,7 @@ static void qemuMonitorJSONHandlePMWakeup(qemuMonitorPtr mon,
virJSONValuePtr da
static void qemuMonitorJSONHandlePMSuspend(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon, virJSONValuePtr
data);
static void qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon, virJSONValuePtr
data);
+static void qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon, virJSONValuePtr
data);
static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValuePtr
data);
typedef struct {
@@ -81,6 +82,7 @@ static qemuEventHandler eventHandlers[] = {
{ "BLOCK_IO_ERROR", qemuMonitorJSONHandleIOError, },
{ "BLOCK_JOB_CANCELLED", qemuMonitorJSONHandleBlockJobCanceled, },
{ "BLOCK_JOB_COMPLETED", qemuMonitorJSONHandleBlockJobCompleted, },
+ { "BLOCK_JOB_READY", qemuMonitorJSONHandleBlockJobReady, },
{ "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
{ "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
{ "RESET", qemuMonitorJSONHandleReset, },
@@ -803,6 +805,8 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
if (STREQ(type_str, "stream"))
type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
+ else if (STREQ(type_str, "mirror"))
+ type = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
switch ((virConnectDomainEventBlockJobStatus) event) {
case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
@@ -811,11 +815,12 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
event = VIR_DOMAIN_BLOCK_JOB_FAILED;
break;
case VIR_DOMAIN_BLOCK_JOB_CANCELED:
+ case VIR_DOMAIN_BLOCK_JOB_READY:
break;
case VIR_DOMAIN_BLOCK_JOB_FAILED:
case VIR_DOMAIN_BLOCK_JOB_LAST:
- VIR_DEBUG("should not get here");
- break;
+ VIR_DEBUG("should not get here");
+ break;
}
out:
@@ -879,6 +884,14 @@ qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon,
}
static void
+qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon,
+ virJSONValuePtr data)
+{
+ qemuMonitorJSONHandleBlockJobImpl(mon, data,
+ VIR_DOMAIN_BLOCK_JOB_READY);
+}
+
+static void
qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon,
virJSONValuePtr data)
{
@@ -3530,6 +3543,8 @@ static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
}
if (STREQ(type, "stream"))
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
+ else if (STREQ(type, "mirror"))
+ info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
else
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 5ac1d2b..7eac7db 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -913,6 +913,8 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
if (disk) {
path = disk->src;
event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
+ if (disk->mirror && status == VIR_DOMAIN_BLOCK_JOB_READY)
+ disk->mirroring = true;
}
virDomainObjUnlock(vm);
--
1.7.11.4