[libvirt] [PATCH 17/25] qemu: Add handler for job state change event

Peter Krempa pkrempa at redhat.com
Fri Jul 12 16:05:58 UTC 2019


Add support for handling the event either synchronously or
asynchronously using the event thread.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_domain.c  |  3 ++
 src/qemu/qemu_domain.h  |  1 +
 src/qemu/qemu_driver.c  | 23 +++++++++++++++
 src/qemu/qemu_process.c | 63 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 90 insertions(+)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 7162fca71b..13a90ab60b 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -14480,6 +14480,9 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
     case QEMU_PROCESS_EVENT_MONITOR_EOF:
         VIR_FREE(event->data);
         break;
+    case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE:
+        virObjectUnref(event->data);
+        break;
     case QEMU_PROCESS_EVENT_PR_DISCONNECT:
     case QEMU_PROCESS_EVENT_LAST:
         break;
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index b42b205398..3ccea3177e 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -514,6 +514,7 @@ typedef enum {
     QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED,
     QEMU_PROCESS_EVENT_SERIAL_CHANGED,
     QEMU_PROCESS_EVENT_BLOCK_JOB,
+    QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE,
     QEMU_PROCESS_EVENT_MONITOR_EOF,
     QEMU_PROCESS_EVENT_PR_DISCONNECT,
     QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a1dc2634ca..604beca155 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4717,6 +4717,26 @@ processBlockJobEvent(virQEMUDriverPtr driver,
 }


+static void
+processJobStatusChangeEvent(virQEMUDriverPtr driver,
+                            virDomainObjPtr vm,
+                            qemuBlockJobDataPtr job)
+{
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+        return;
+
+    if (!virDomainObjIsActive(vm)) {
+        VIR_DEBUG("Domain is not running");
+        goto endjob;
+    }
+
+    qemuBlockJobUpdate(vm, job, QEMU_ASYNC_JOB_NONE);
+
+ endjob:
+    qemuDomainObjEndJob(driver, vm);
+}
+
+
 static void
 processMonitorEOFEvent(virQEMUDriverPtr driver,
                        virDomainObjPtr vm)
@@ -4855,6 +4875,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
                              processEvent->action,
                              processEvent->status);
         break;
+    case QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE:
+        processJobStatusChangeEvent(driver, vm, processEvent->data);
+        break;
     case QEMU_PROCESS_EVENT_MONITOR_EOF:
         processMonitorEOFEvent(driver, vm);
         break;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4e24201674..416f4f5c9a 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -990,6 +990,68 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
 }


+static int
+qemuProcessHandleJobStatusChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+                                 virDomainObjPtr vm,
+                                 const char *jobname,
+                                 int status,
+                                 void *opaque)
+{
+    virQEMUDriverPtr driver = opaque;
+    qemuDomainObjPrivatePtr priv;
+    struct qemuProcessEvent *processEvent = NULL;
+    qemuBlockJobDataPtr job = NULL;
+    int jobnewstate;
+
+    virObjectLock(vm);
+    priv = vm->privateData;
+
+    VIR_DEBUG("job '%s'(domain: %p,%s) state changed to '%s'(%d)",
+              jobname, vm, vm->def->name,
+              qemuMonitorJobStatusTypeToString(status), status);
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
+        VIR_DEBUG("job '%s' handled by old blockjob handler", jobname);
+        goto cleanup;
+    }
+
+    if ((jobnewstate = qemuBlockjobConvertMonitorStatus(status)) == QEMU_BLOCKJOB_STATE_LAST)
+        goto cleanup;
+
+    if (!(job = virHashLookup(priv->blockjobs, jobname))) {
+        VIR_DEBUG("job '%s' not registered", jobname);
+        goto cleanup;
+    }
+
+    job->newstate = jobnewstate;
+
+    if (job->synchronous) {
+        VIR_DEBUG("job '%s' handled synchronously", jobname);
+        virDomainObjBroadcast(vm);
+    } else {
+        VIR_DEBUG("job '%s' handled by event thread", jobname);
+        if (VIR_ALLOC(processEvent) < 0)
+            goto cleanup;
+
+        processEvent->eventType = QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE;
+        processEvent->vm = virObjectRef(vm);
+        processEvent->data = virObjectRef(job);
+
+        if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
+            ignore_value(virObjectUnref(vm));
+            goto cleanup;
+        }
+
+        processEvent = NULL;
+    }
+
+ cleanup:
+    qemuProcessEventFree(processEvent);
+    virObjectUnlock(vm);
+    return 0;
+}
+
+
 static int
 qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                           virDomainObjPtr vm,
@@ -1820,6 +1882,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
     .domainIOError = qemuProcessHandleIOError,
     .domainGraphics = qemuProcessHandleGraphics,
     .domainBlockJob = qemuProcessHandleBlockJob,
+    .jobStatusChange = qemuProcessHandleJobStatusChange,
     .domainTrayChange = qemuProcessHandleTrayChange,
     .domainPMWakeup = qemuProcessHandlePMWakeup,
     .domainPMSuspend = qemuProcessHandlePMSuspend,
-- 
2.21.0




More information about the libvir-list mailing list