Currently in qemuProcessHandleBlockJob we either offload blockjob event
processing to the worker thread or notify another thread that waits for
blockjob event and that thread processes the event. But sometimes after event
is offloaded to the worker thread we need to process the event in a different
thread.
To be able to to do it let's always set newstate/errmsg and then let whatever
thread is first process it.
Libvirt always creates blockjob object before starting blockjob but at least in
Virtuozzo we have been using virDomainQemuMonitorCommand for several years to
start push backups and relay on behaviour that libvirt sends block job events
even in this case. Thus let's continue to send notifications if block job
object is not found.
Note that we can have issue on reconnect when block jobs are not yet created
but this will addressed in following patches.
Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
---
src/qemu/qemu_blockjob.c | 2 +-
src/qemu/qemu_blockjob.h | 7 +++++++
src/qemu/qemu_driver.c | 17 ++++-------------
src/qemu/qemu_process.c | 19 +++++++++++--------
4 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 2a5a5e6..cf3939d 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -596,7 +596,7 @@ qemuBlockJobRefreshJobs(virQEMUDriverPtr driver,
* Emits the VIR_DOMAIN_EVENT_ID_BLOCK_JOB and VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2
* for a block job. The former event is emitted only for local disks.
*/
-static void
+void
qemuBlockJobEmitEvents(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainDiskDefPtr disk,
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index 9f73a35..5edb459 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -245,3 +245,10 @@ qemuBlockJobGetByDisk(virDomainDiskDefPtr disk)
qemuBlockjobState
qemuBlockjobConvertMonitorStatus(int monitorstatus);
+
+void
+qemuBlockJobEmitEvents(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainDiskDefPtr disk,
+ virDomainBlockJobType type,
+ virConnectDomainEventBlockJobStatus status);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 05f8eb2..25466f6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4116,9 +4116,7 @@ processSerialChangedEvent(virQEMUDriverPtr driver,
static void
processBlockJobEvent(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- const char *diskAlias,
- int type,
- int status)
+ const char *diskAlias)
{
virDomainDiskDefPtr disk;
g_autoptr(qemuBlockJobData) job = NULL;
@@ -4137,14 +4135,10 @@ processBlockJobEvent(virQEMUDriverPtr driver,
}
if (!(job = qemuBlockJobDiskGetJob(disk))) {
- VIR_DEBUG("creating new block job object for '%s'",
diskAlias);
- if (!(job = qemuBlockJobDiskNew(vm, disk, type, diskAlias)))
- goto endjob;
- job->state = QEMU_BLOCKJOB_STATE_RUNNING;
+ VIR_DEBUG("disk %s job not found", diskAlias);
+ goto endjob;
}
- job->newstate = status;
-
qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
endjob:
@@ -4319,10 +4313,7 @@ static void qemuProcessEventHandler(void *data, void *opaque)
processEvent->action);
break;
case QEMU_PROCESS_EVENT_BLOCK_JOB:
- processBlockJobEvent(driver, vm,
- processEvent->data,
- processEvent->action,
- processEvent->status);
+ processBlockJobEvent(driver, vm, processEvent->data);
break;
case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE:
processJobStatusChangeEvent(driver, vm, processEvent->data);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1963de9..a810f38 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -953,13 +953,18 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon G_GNUC_UNUSED,
if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL)))
goto cleanup;
- job = qemuBlockJobDiskGetJob(disk);
+ if (!(job = qemuBlockJobDiskGetJob(disk))) {
+ VIR_DEBUG("block job for '%s' not found", diskAlias);
+ qemuBlockJobEmitEvents(driver, vm, disk, type, status);
+ goto cleanup;
+ }
- if (job && job->synchronous) {
- /* We have a SYNC API waiting for this event, dispatch it back */
- job->newstate = status;
- VIR_FREE(job->errmsg);
- job->errmsg = g_strdup(error);
+ job->newstate = status;
+ VIR_FREE(job->errmsg);
+ job->errmsg = g_strdup(error);
+
+ /* We have a SYNC API waiting for this event, dispatch it back */
+ if (job->synchronous) {
virDomainObjBroadcast(vm);
} else {
/* there is no waiting SYNC API, dispatch the update to a thread */
@@ -969,8 +974,6 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon G_GNUC_UNUSED,
data = g_strdup(diskAlias);
processEvent->data = data;
processEvent->vm = virObjectRef(vm);
- processEvent->action = type;
- processEvent->status = status;
if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
virObjectUnref(vm);
--
1.8.3.1