summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/qemu/job.h11
-rw-r--r--job.c18
2 files changed, 29 insertions, 0 deletions
diff --git a/include/qemu/job.h b/include/qemu/job.h
index e0e99870a1..1144d671a1 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -209,6 +209,17 @@ struct JobDriver {
void (*drain)(Job *job);
/**
+ * If the callback is not NULL, exit will be invoked from the main thread
+ * when the job's coroutine has finished, but before transactional
+ * convergence; before @prepare or @abort.
+ *
+ * FIXME TODO: This callback is only temporary to transition remaining jobs
+ * to prepare/commit/abort/clean callbacks and will be removed before 3.1.
+ * is released.
+ */
+ void (*exit)(Job *job);
+
+ /**
* If the callback is not NULL, prepare will be invoked when all the jobs
* belonging to the same transaction complete; or upon this job's completion
* if it is not in a transaction.
diff --git a/job.c b/job.c
index 7b3721d2c7..5df7791ad8 100644
--- a/job.c
+++ b/job.c
@@ -535,6 +535,18 @@ void job_drain(Job *job)
}
}
+static void job_exit(void *opaque)
+{
+ Job *job = (Job *)opaque;
+ AioContext *aio_context = job->aio_context;
+
+ if (job->driver->exit) {
+ aio_context_acquire(aio_context);
+ job->driver->exit(job);
+ aio_context_release(aio_context);
+ }
+ job_completed(job, job->ret);
+}
/**
* All jobs must allow a pause point before entering their job proper. This
@@ -547,6 +559,12 @@ static void coroutine_fn job_co_entry(void *opaque)
assert(job && job->driver && job->driver->run);
job_pause_point(job);
job->ret = job->driver->run(job, &job->err);
+ if (!job->deferred_to_main_loop) {
+ job->deferred_to_main_loop = true;
+ aio_bh_schedule_oneshot(qemu_get_aio_context(),
+ job_exit,
+ job);
+ }
}