[libvirt] [PATCH RFC 49/51] qemu: Add handler for job state change event

Peter Krempa pkrempa at redhat.com
Wed Dec 12 17:09:05 UTC 2018


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 | 66 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 93 insertions(+)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 7845889dec..9467d0fd32 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -13711,6 +13711,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 a243bdc80e..0a2973aba9 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -485,6 +485,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,

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f62d153c03..0c38a61adc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4747,6 +4747,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)
@@ -4842,6 +4862,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 255a5acc13..fb687a1fd9 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -981,6 +981,71 @@ 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;
+    qemuBlockjobState 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;
+    }
+
+    jobnewstate = qemuBlockjobConvertMonitorStatus(status);
+
+    if (jobnewstate == 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);
+        VIR_STEAL_PTR(processEvent->data, job);
+
+        if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
+            ignore_value(virObjectUnref(vm));
+            goto cleanup;
+        }
+
+        processEvent = NULL;
+    }
+
+ cleanup:
+    qemuProcessEventFree(processEvent);
+    virObjectUnref(job);
+    virObjectUnlock(vm);
+    return 0;
+}
+
+
 static int
 qemuProcessHandleGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                           virDomainObjPtr vm,
@@ -1735,6 +1800,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
     .domainIOError = qemuProcessHandleIOError,
     .domainGraphics = qemuProcessHandleGraphics,
     .domainBlockJob = qemuProcessHandleBlockJob,
+    .jobStatusChange = qemuProcessHandleJobStatusChange,
     .domainTrayChange = qemuProcessHandleTrayChange,
     .domainPMWakeup = qemuProcessHandlePMWakeup,
     .domainPMSuspend = qemuProcessHandlePMSuspend,
-- 
2.19.2




More information about the libvir-list mailing list