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,
}
+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)
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;
}
+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,
.domainIOError = qemuProcessHandleIOError,
.domainGraphics = qemuProcessHandleGraphics,
.domainBlockJob = qemuProcessHandleBlockJob,
+ .jobStatusChange = qemuProcessHandleJobStatusChange,
.domainTrayChange = qemuProcessHandleTrayChange,
.domainPMWakeup = qemuProcessHandlePMWakeup,
.domainPMSuspend = qemuProcessHandlePMSuspend,