|
|
383d26 |
From 1adf648f5842dd52698c338b0a4916606325ccb6 Mon Sep 17 00:00:00 2001
|
|
|
383d26 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
383d26 |
Date: Tue, 26 Jun 2018 09:48:08 +0200
|
|
|
383d26 |
Subject: [PATCH 39/89] job: Move defer_to_main_loop to Job
|
|
|
383d26 |
|
|
|
383d26 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
383d26 |
Message-id: <20180626094856.6924-26-kwolf@redhat.com>
|
|
|
383d26 |
Patchwork-id: 81091
|
|
|
383d26 |
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH v2 25/73] job: Move defer_to_main_loop to Job
|
|
|
383d26 |
Bugzilla: 1513543
|
|
|
383d26 |
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
|
|
|
383d26 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
383d26 |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
383d26 |
|
|
|
383d26 |
Move the defer_to_main_loop functionality from BlockJob to Job.
|
|
|
383d26 |
|
|
|
383d26 |
The code can be simplified because we can use job->aio_context in
|
|
|
383d26 |
job_defer_to_main_loop_bh() now, instead of having to access the
|
|
|
383d26 |
BlockDriverState.
|
|
|
383d26 |
|
|
|
383d26 |
Probably taking the data->aio_context lock in addition was already
|
|
|
383d26 |
unnecessary in the old code because we didn't actually make use of
|
|
|
383d26 |
anything protected by the old AioContext except getting the new
|
|
|
383d26 |
AioContext, in case it changed between scheduling the BH and running it.
|
|
|
383d26 |
But it's certainly unnecessary now that the BDS isn't accessed at all
|
|
|
383d26 |
any more.
|
|
|
383d26 |
|
|
|
383d26 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
383d26 |
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
|
383d26 |
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
|
383d26 |
(cherry picked from commit 1908a5590c7d214b1b6886bc19b81076fb65cec9)
|
|
|
383d26 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
383d26 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
383d26 |
---
|
|
|
383d26 |
block/backup.c | 7 +++---
|
|
|
383d26 |
block/commit.c | 11 +++++----
|
|
|
383d26 |
block/mirror.c | 15 ++++++------
|
|
|
383d26 |
block/stream.c | 14 +++++------
|
|
|
383d26 |
blockjob.c | 57 ++++----------------------------------------
|
|
|
383d26 |
include/block/blockjob.h | 5 ----
|
|
|
383d26 |
include/block/blockjob_int.h | 19 ---------------
|
|
|
383d26 |
include/qemu/job.h | 20 ++++++++++++++++
|
|
|
383d26 |
job.c | 32 +++++++++++++++++++++++++
|
|
|
383d26 |
tests/test-bdrv-drain.c | 7 +++---
|
|
|
383d26 |
tests/test-blockjob-txn.c | 13 +++++-----
|
|
|
383d26 |
tests/test-blockjob.c | 7 +++---
|
|
|
383d26 |
12 files changed, 97 insertions(+), 110 deletions(-)
|
|
|
383d26 |
|
|
|
383d26 |
diff --git a/block/backup.c b/block/backup.c
|
|
|
383d26 |
index ef0aa0e..22dd368 100644
|
|
|
383d26 |
--- a/block/backup.c
|
|
|
383d26 |
+++ b/block/backup.c
|
|
|
383d26 |
@@ -317,11 +317,12 @@ typedef struct {
|
|
|
383d26 |
int ret;
|
|
|
383d26 |
} BackupCompleteData;
|
|
|
383d26 |
|
|
|
383d26 |
-static void backup_complete(BlockJob *job, void *opaque)
|
|
|
383d26 |
+static void backup_complete(Job *job, void *opaque)
|
|
|
383d26 |
{
|
|
|
383d26 |
+ BlockJob *bjob = container_of(job, BlockJob, job);
|
|
|
383d26 |
BackupCompleteData *data = opaque;
|
|
|
383d26 |
|
|
|
383d26 |
- block_job_completed(job, data->ret);
|
|
|
383d26 |
+ block_job_completed(bjob, data->ret);
|
|
|
383d26 |
g_free(data);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
@@ -519,7 +520,7 @@ static void coroutine_fn backup_run(void *opaque)
|
|
|
383d26 |
|
|
|
383d26 |
data = g_malloc(sizeof(*data));
|
|
|
383d26 |
data->ret = ret;
|
|
|
383d26 |
- block_job_defer_to_main_loop(&job->common, backup_complete, data);
|
|
|
383d26 |
+ job_defer_to_main_loop(&job->common.job, backup_complete, data);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
static const BlockJobDriver backup_job_driver = {
|
|
|
383d26 |
diff --git a/block/commit.c b/block/commit.c
|
|
|
383d26 |
index 85baea8..d326766 100644
|
|
|
383d26 |
--- a/block/commit.c
|
|
|
383d26 |
+++ b/block/commit.c
|
|
|
383d26 |
@@ -72,9 +72,10 @@ typedef struct {
|
|
|
383d26 |
int ret;
|
|
|
383d26 |
} CommitCompleteData;
|
|
|
383d26 |
|
|
|
383d26 |
-static void commit_complete(BlockJob *job, void *opaque)
|
|
|
383d26 |
+static void commit_complete(Job *job, void *opaque)
|
|
|
383d26 |
{
|
|
|
383d26 |
- CommitBlockJob *s = container_of(job, CommitBlockJob, common);
|
|
|
383d26 |
+ CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
|
|
|
383d26 |
+ BlockJob *bjob = &s->common;
|
|
|
383d26 |
CommitCompleteData *data = opaque;
|
|
|
383d26 |
BlockDriverState *top = blk_bs(s->top);
|
|
|
383d26 |
BlockDriverState *base = blk_bs(s->base);
|
|
|
383d26 |
@@ -90,7 +91,7 @@ static void commit_complete(BlockJob *job, void *opaque)
|
|
|
383d26 |
* the normal backing chain can be restored. */
|
|
|
383d26 |
blk_unref(s->base);
|
|
|
383d26 |
|
|
|
383d26 |
- if (!job_is_cancelled(&s->common.job) && ret == 0) {
|
|
|
383d26 |
+ if (!job_is_cancelled(job) && ret == 0) {
|
|
|
383d26 |
/* success */
|
|
|
383d26 |
ret = bdrv_drop_intermediate(s->commit_top_bs, base,
|
|
|
383d26 |
s->backing_file_str);
|
|
|
383d26 |
@@ -114,7 +115,7 @@ static void commit_complete(BlockJob *job, void *opaque)
|
|
|
383d26 |
* block_job_finish_sync()), block_job_completed() won't free it and
|
|
|
383d26 |
* therefore the blockers on the intermediate nodes remain. This would
|
|
|
383d26 |
* cause bdrv_set_backing_hd() to fail. */
|
|
|
383d26 |
- block_job_remove_all_bdrv(job);
|
|
|
383d26 |
+ block_job_remove_all_bdrv(bjob);
|
|
|
383d26 |
|
|
|
383d26 |
block_job_completed(&s->common, ret);
|
|
|
383d26 |
g_free(data);
|
|
|
383d26 |
@@ -211,7 +212,7 @@ out:
|
|
|
383d26 |
|
|
|
383d26 |
data = g_malloc(sizeof(*data));
|
|
|
383d26 |
data->ret = ret;
|
|
|
383d26 |
- block_job_defer_to_main_loop(&s->common, commit_complete, data);
|
|
|
383d26 |
+ job_defer_to_main_loop(&s->common.job, commit_complete, data);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
static const BlockJobDriver commit_job_driver = {
|
|
|
383d26 |
diff --git a/block/mirror.c b/block/mirror.c
|
|
|
383d26 |
index 424072e..90d4ac9 100644
|
|
|
383d26 |
--- a/block/mirror.c
|
|
|
383d26 |
+++ b/block/mirror.c
|
|
|
383d26 |
@@ -484,9 +484,10 @@ typedef struct {
|
|
|
383d26 |
int ret;
|
|
|
383d26 |
} MirrorExitData;
|
|
|
383d26 |
|
|
|
383d26 |
-static void mirror_exit(BlockJob *job, void *opaque)
|
|
|
383d26 |
+static void mirror_exit(Job *job, void *opaque)
|
|
|
383d26 |
{
|
|
|
383d26 |
- MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
|
|
|
383d26 |
+ MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
|
|
|
383d26 |
+ BlockJob *bjob = &s->common;
|
|
|
383d26 |
MirrorExitData *data = opaque;
|
|
|
383d26 |
AioContext *replace_aio_context = NULL;
|
|
|
383d26 |
BlockDriverState *src = s->source;
|
|
|
383d26 |
@@ -568,7 +569,7 @@ static void mirror_exit(BlockJob *job, void *opaque)
|
|
|
383d26 |
* the blockers on the intermediate nodes so that the resulting state is
|
|
|
383d26 |
* valid. Also give up permissions on mirror_top_bs->backing, which might
|
|
|
383d26 |
* block the removal. */
|
|
|
383d26 |
- block_job_remove_all_bdrv(job);
|
|
|
383d26 |
+ block_job_remove_all_bdrv(bjob);
|
|
|
383d26 |
bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,
|
|
|
383d26 |
&error_abort);
|
|
|
383d26 |
bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);
|
|
|
383d26 |
@@ -576,9 +577,9 @@ static void mirror_exit(BlockJob *job, void *opaque)
|
|
|
383d26 |
/* We just changed the BDS the job BB refers to (with either or both of the
|
|
|
383d26 |
* bdrv_replace_node() calls), so switch the BB back so the cleanup does
|
|
|
383d26 |
* the right thing. We don't need any permissions any more now. */
|
|
|
383d26 |
- blk_remove_bs(job->blk);
|
|
|
383d26 |
- blk_set_perm(job->blk, 0, BLK_PERM_ALL, &error_abort);
|
|
|
383d26 |
- blk_insert_bs(job->blk, mirror_top_bs, &error_abort);
|
|
|
383d26 |
+ blk_remove_bs(bjob->blk);
|
|
|
383d26 |
+ blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
|
|
|
383d26 |
+ blk_insert_bs(bjob->blk, mirror_top_bs, &error_abort);
|
|
|
383d26 |
|
|
|
383d26 |
block_job_completed(&s->common, data->ret);
|
|
|
383d26 |
|
|
|
383d26 |
@@ -901,7 +902,7 @@ immediate_exit:
|
|
|
383d26 |
if (need_drain) {
|
|
|
383d26 |
bdrv_drained_begin(bs);
|
|
|
383d26 |
}
|
|
|
383d26 |
- block_job_defer_to_main_loop(&s->common, mirror_exit, data);
|
|
|
383d26 |
+ job_defer_to_main_loop(&s->common.job, mirror_exit, data);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
static void mirror_complete(BlockJob *job, Error **errp)
|
|
|
383d26 |
diff --git a/block/stream.c b/block/stream.c
|
|
|
383d26 |
index 22c71ae..0bba816 100644
|
|
|
383d26 |
--- a/block/stream.c
|
|
|
383d26 |
+++ b/block/stream.c
|
|
|
383d26 |
@@ -58,16 +58,16 @@ typedef struct {
|
|
|
383d26 |
int ret;
|
|
|
383d26 |
} StreamCompleteData;
|
|
|
383d26 |
|
|
|
383d26 |
-static void stream_complete(BlockJob *job, void *opaque)
|
|
|
383d26 |
+static void stream_complete(Job *job, void *opaque)
|
|
|
383d26 |
{
|
|
|
383d26 |
- StreamBlockJob *s = container_of(job, StreamBlockJob, common);
|
|
|
383d26 |
+ StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
|
|
|
383d26 |
+ BlockJob *bjob = &s->common;
|
|
|
383d26 |
StreamCompleteData *data = opaque;
|
|
|
383d26 |
- BlockDriverState *bs = blk_bs(job->blk);
|
|
|
383d26 |
+ BlockDriverState *bs = blk_bs(bjob->blk);
|
|
|
383d26 |
BlockDriverState *base = s->base;
|
|
|
383d26 |
Error *local_err = NULL;
|
|
|
383d26 |
|
|
|
383d26 |
- if (!job_is_cancelled(&s->common.job) && bs->backing &&
|
|
|
383d26 |
- data->ret == 0) {
|
|
|
383d26 |
+ if (!job_is_cancelled(job) && bs->backing && data->ret == 0) {
|
|
|
383d26 |
const char *base_id = NULL, *base_fmt = NULL;
|
|
|
383d26 |
if (base) {
|
|
|
383d26 |
base_id = s->backing_file_str;
|
|
|
383d26 |
@@ -88,7 +88,7 @@ out:
|
|
|
383d26 |
/* Reopen the image back in read-only mode if necessary */
|
|
|
383d26 |
if (s->bs_flags != bdrv_get_flags(bs)) {
|
|
|
383d26 |
/* Give up write permissions before making it read-only */
|
|
|
383d26 |
- blk_set_perm(job->blk, 0, BLK_PERM_ALL, &error_abort);
|
|
|
383d26 |
+ blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
|
|
|
383d26 |
bdrv_reopen(bs, s->bs_flags, NULL);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
@@ -205,7 +205,7 @@ out:
|
|
|
383d26 |
/* Modify backing chain and close BDSes in main loop */
|
|
|
383d26 |
data = g_malloc(sizeof(*data));
|
|
|
383d26 |
data->ret = ret;
|
|
|
383d26 |
- block_job_defer_to_main_loop(&s->common, stream_complete, data);
|
|
|
383d26 |
+ job_defer_to_main_loop(&s->common.job, stream_complete, data);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
static const BlockJobDriver stream_job_driver = {
|
|
|
383d26 |
diff --git a/blockjob.c b/blockjob.c
|
|
|
383d26 |
index 0a0b1c4..3ede511 100644
|
|
|
383d26 |
--- a/blockjob.c
|
|
|
383d26 |
+++ b/blockjob.c
|
|
|
383d26 |
@@ -360,7 +360,7 @@ static void block_job_decommission(BlockJob *job)
|
|
|
383d26 |
job->completed = true;
|
|
|
383d26 |
job->busy = false;
|
|
|
383d26 |
job->paused = false;
|
|
|
383d26 |
- job->deferred_to_main_loop = true;
|
|
|
383d26 |
+ job->job.deferred_to_main_loop = true;
|
|
|
383d26 |
block_job_txn_del_job(job);
|
|
|
383d26 |
job_state_transition(&job->job, JOB_STATUS_NULL);
|
|
|
383d26 |
job_unref(&job->job);
|
|
|
383d26 |
@@ -515,7 +515,7 @@ static int block_job_finish_sync(BlockJob *job,
|
|
|
383d26 |
/* block_job_drain calls block_job_enter, and it should be enough to
|
|
|
383d26 |
* induce progress until the job completes or moves to the main thread.
|
|
|
383d26 |
*/
|
|
|
383d26 |
- while (!job->deferred_to_main_loop && !job->completed) {
|
|
|
383d26 |
+ while (!job->job.deferred_to_main_loop && !job->completed) {
|
|
|
383d26 |
block_job_drain(job);
|
|
|
383d26 |
}
|
|
|
383d26 |
while (!job->completed) {
|
|
|
383d26 |
@@ -729,7 +729,7 @@ void block_job_cancel(BlockJob *job, bool force)
|
|
|
383d26 |
block_job_cancel_async(job, force);
|
|
|
383d26 |
if (!block_job_started(job)) {
|
|
|
383d26 |
block_job_completed(job, -ECANCELED);
|
|
|
383d26 |
- } else if (job->deferred_to_main_loop) {
|
|
|
383d26 |
+ } else if (job->job.deferred_to_main_loop) {
|
|
|
383d26 |
block_job_completed_txn_abort(job);
|
|
|
383d26 |
} else {
|
|
|
383d26 |
block_job_enter(job);
|
|
|
383d26 |
@@ -1045,7 +1045,7 @@ static void block_job_enter_cond(BlockJob *job, bool(*fn)(BlockJob *job))
|
|
|
383d26 |
if (!block_job_started(job)) {
|
|
|
383d26 |
return;
|
|
|
383d26 |
}
|
|
|
383d26 |
- if (job->deferred_to_main_loop) {
|
|
|
383d26 |
+ if (job->job.deferred_to_main_loop) {
|
|
|
383d26 |
return;
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
@@ -1060,7 +1060,7 @@ static void block_job_enter_cond(BlockJob *job, bool(*fn)(BlockJob *job))
|
|
|
383d26 |
return;
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
- assert(!job->deferred_to_main_loop);
|
|
|
383d26 |
+ assert(!job->job.deferred_to_main_loop);
|
|
|
383d26 |
timer_del(&job->sleep_timer);
|
|
|
383d26 |
job->busy = true;
|
|
|
383d26 |
block_job_unlock();
|
|
|
383d26 |
@@ -1166,50 +1166,3 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
|
|
|
383d26 |
}
|
|
|
383d26 |
return action;
|
|
|
383d26 |
}
|
|
|
383d26 |
-
|
|
|
383d26 |
-typedef struct {
|
|
|
383d26 |
- BlockJob *job;
|
|
|
383d26 |
- AioContext *aio_context;
|
|
|
383d26 |
- BlockJobDeferToMainLoopFn *fn;
|
|
|
383d26 |
- void *opaque;
|
|
|
383d26 |
-} BlockJobDeferToMainLoopData;
|
|
|
383d26 |
-
|
|
|
383d26 |
-static void block_job_defer_to_main_loop_bh(void *opaque)
|
|
|
383d26 |
-{
|
|
|
383d26 |
- BlockJobDeferToMainLoopData *data = opaque;
|
|
|
383d26 |
- AioContext *aio_context;
|
|
|
383d26 |
-
|
|
|
383d26 |
- /* Prevent race with block_job_defer_to_main_loop() */
|
|
|
383d26 |
- aio_context_acquire(data->aio_context);
|
|
|
383d26 |
-
|
|
|
383d26 |
- /* Fetch BDS AioContext again, in case it has changed */
|
|
|
383d26 |
- aio_context = blk_get_aio_context(data->job->blk);
|
|
|
383d26 |
- if (aio_context != data->aio_context) {
|
|
|
383d26 |
- aio_context_acquire(aio_context);
|
|
|
383d26 |
- }
|
|
|
383d26 |
-
|
|
|
383d26 |
- data->fn(data->job, data->opaque);
|
|
|
383d26 |
-
|
|
|
383d26 |
- if (aio_context != data->aio_context) {
|
|
|
383d26 |
- aio_context_release(aio_context);
|
|
|
383d26 |
- }
|
|
|
383d26 |
-
|
|
|
383d26 |
- aio_context_release(data->aio_context);
|
|
|
383d26 |
-
|
|
|
383d26 |
- g_free(data);
|
|
|
383d26 |
-}
|
|
|
383d26 |
-
|
|
|
383d26 |
-void block_job_defer_to_main_loop(BlockJob *job,
|
|
|
383d26 |
- BlockJobDeferToMainLoopFn *fn,
|
|
|
383d26 |
- void *opaque)
|
|
|
383d26 |
-{
|
|
|
383d26 |
- BlockJobDeferToMainLoopData *data = g_malloc(sizeof(*data));
|
|
|
383d26 |
- data->job = job;
|
|
|
383d26 |
- data->aio_context = blk_get_aio_context(job->blk);
|
|
|
383d26 |
- data->fn = fn;
|
|
|
383d26 |
- data->opaque = opaque;
|
|
|
383d26 |
- job->deferred_to_main_loop = true;
|
|
|
383d26 |
-
|
|
|
383d26 |
- aio_bh_schedule_oneshot(qemu_get_aio_context(),
|
|
|
383d26 |
- block_job_defer_to_main_loop_bh, data);
|
|
|
383d26 |
-}
|
|
|
383d26 |
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
|
|
|
383d26 |
index 1e708f4..2a9e865 100644
|
|
|
383d26 |
--- a/include/block/blockjob.h
|
|
|
383d26 |
+++ b/include/block/blockjob.h
|
|
|
383d26 |
@@ -92,11 +92,6 @@ typedef struct BlockJob {
|
|
|
383d26 |
*/
|
|
|
383d26 |
bool ready;
|
|
|
383d26 |
|
|
|
383d26 |
- /**
|
|
|
383d26 |
- * Set to true when the job has deferred work to the main loop.
|
|
|
383d26 |
- */
|
|
|
383d26 |
- bool deferred_to_main_loop;
|
|
|
383d26 |
-
|
|
|
383d26 |
/** Status that is published by the query-block-jobs QMP API */
|
|
|
383d26 |
BlockDeviceIoStatus iostatus;
|
|
|
383d26 |
|
|
|
383d26 |
diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
|
|
|
383d26 |
index d64f30e..0c2f8de 100644
|
|
|
383d26 |
--- a/include/block/blockjob_int.h
|
|
|
383d26 |
+++ b/include/block/blockjob_int.h
|
|
|
383d26 |
@@ -233,23 +233,4 @@ void block_job_event_ready(BlockJob *job);
|
|
|
383d26 |
BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
|
|
|
383d26 |
int is_read, int error);
|
|
|
383d26 |
|
|
|
383d26 |
-typedef void BlockJobDeferToMainLoopFn(BlockJob *job, void *opaque);
|
|
|
383d26 |
-
|
|
|
383d26 |
-/**
|
|
|
383d26 |
- * block_job_defer_to_main_loop:
|
|
|
383d26 |
- * @job: The job
|
|
|
383d26 |
- * @fn: The function to run in the main loop
|
|
|
383d26 |
- * @opaque: The opaque value that is passed to @fn
|
|
|
383d26 |
- *
|
|
|
383d26 |
- * This function must be called by the main job coroutine just before it
|
|
|
383d26 |
- * returns. @fn is executed in the main loop with the BlockDriverState
|
|
|
383d26 |
- * AioContext acquired. Block jobs must call bdrv_unref(), bdrv_close(), and
|
|
|
383d26 |
- * anything that uses bdrv_drain_all() in the main loop.
|
|
|
383d26 |
- *
|
|
|
383d26 |
- * The @job AioContext is held while @fn executes.
|
|
|
383d26 |
- */
|
|
|
383d26 |
-void block_job_defer_to_main_loop(BlockJob *job,
|
|
|
383d26 |
- BlockJobDeferToMainLoopFn *fn,
|
|
|
383d26 |
- void *opaque);
|
|
|
383d26 |
-
|
|
|
383d26 |
#endif
|
|
|
383d26 |
diff --git a/include/qemu/job.h b/include/qemu/job.h
|
|
|
383d26 |
index 01e083f..933e0ab 100644
|
|
|
383d26 |
--- a/include/qemu/job.h
|
|
|
383d26 |
+++ b/include/qemu/job.h
|
|
|
383d26 |
@@ -58,6 +58,9 @@ typedef struct Job {
|
|
|
383d26 |
*/
|
|
|
383d26 |
bool cancelled;
|
|
|
383d26 |
|
|
|
383d26 |
+ /** Set to true when the job has deferred work to the main loop. */
|
|
|
383d26 |
+ bool deferred_to_main_loop;
|
|
|
383d26 |
+
|
|
|
383d26 |
/** Element of the list of jobs */
|
|
|
383d26 |
QLIST_ENTRY(Job) job_list;
|
|
|
383d26 |
} Job;
|
|
|
383d26 |
@@ -131,6 +134,23 @@ Job *job_get(const char *id);
|
|
|
383d26 |
*/
|
|
|
383d26 |
int job_apply_verb(Job *job, JobVerb verb, Error **errp);
|
|
|
383d26 |
|
|
|
383d26 |
+typedef void JobDeferToMainLoopFn(Job *job, void *opaque);
|
|
|
383d26 |
+
|
|
|
383d26 |
+/**
|
|
|
383d26 |
+ * @job: The job
|
|
|
383d26 |
+ * @fn: The function to run in the main loop
|
|
|
383d26 |
+ * @opaque: The opaque value that is passed to @fn
|
|
|
383d26 |
+ *
|
|
|
383d26 |
+ * This function must be called by the main job coroutine just before it
|
|
|
383d26 |
+ * returns. @fn is executed in the main loop with the job AioContext acquired.
|
|
|
383d26 |
+ *
|
|
|
383d26 |
+ * Block jobs must call bdrv_unref(), bdrv_close(), and anything that uses
|
|
|
383d26 |
+ * bdrv_drain_all() in the main loop.
|
|
|
383d26 |
+ *
|
|
|
383d26 |
+ * The @job AioContext is held while @fn executes.
|
|
|
383d26 |
+ */
|
|
|
383d26 |
+void job_defer_to_main_loop(Job *job, JobDeferToMainLoopFn *fn, void *opaque);
|
|
|
383d26 |
+
|
|
|
383d26 |
/* TODO To be removed from the public interface */
|
|
|
383d26 |
void job_state_transition(Job *job, JobStatus s1);
|
|
|
383d26 |
|
|
|
383d26 |
diff --git a/job.c b/job.c
|
|
|
383d26 |
index 01074d0..c5a37fb 100644
|
|
|
383d26 |
--- a/job.c
|
|
|
383d26 |
+++ b/job.c
|
|
|
383d26 |
@@ -28,6 +28,7 @@
|
|
|
383d26 |
#include "qapi/error.h"
|
|
|
383d26 |
#include "qemu/job.h"
|
|
|
383d26 |
#include "qemu/id.h"
|
|
|
383d26 |
+#include "qemu/main-loop.h"
|
|
|
383d26 |
#include "trace-root.h"
|
|
|
383d26 |
|
|
|
383d26 |
static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);
|
|
|
383d26 |
@@ -170,3 +171,34 @@ void job_unref(Job *job)
|
|
|
383d26 |
g_free(job);
|
|
|
383d26 |
}
|
|
|
383d26 |
}
|
|
|
383d26 |
+
|
|
|
383d26 |
+typedef struct {
|
|
|
383d26 |
+ Job *job;
|
|
|
383d26 |
+ JobDeferToMainLoopFn *fn;
|
|
|
383d26 |
+ void *opaque;
|
|
|
383d26 |
+} JobDeferToMainLoopData;
|
|
|
383d26 |
+
|
|
|
383d26 |
+static void job_defer_to_main_loop_bh(void *opaque)
|
|
|
383d26 |
+{
|
|
|
383d26 |
+ JobDeferToMainLoopData *data = opaque;
|
|
|
383d26 |
+ Job *job = data->job;
|
|
|
383d26 |
+ AioContext *aio_context = job->aio_context;
|
|
|
383d26 |
+
|
|
|
383d26 |
+ aio_context_acquire(aio_context);
|
|
|
383d26 |
+ data->fn(data->job, data->opaque);
|
|
|
383d26 |
+ aio_context_release(aio_context);
|
|
|
383d26 |
+
|
|
|
383d26 |
+ g_free(data);
|
|
|
383d26 |
+}
|
|
|
383d26 |
+
|
|
|
383d26 |
+void job_defer_to_main_loop(Job *job, JobDeferToMainLoopFn *fn, void *opaque)
|
|
|
383d26 |
+{
|
|
|
383d26 |
+ JobDeferToMainLoopData *data = g_malloc(sizeof(*data));
|
|
|
383d26 |
+ data->job = job;
|
|
|
383d26 |
+ data->fn = fn;
|
|
|
383d26 |
+ data->opaque = opaque;
|
|
|
383d26 |
+ job->deferred_to_main_loop = true;
|
|
|
383d26 |
+
|
|
|
383d26 |
+ aio_bh_schedule_oneshot(qemu_get_aio_context(),
|
|
|
383d26 |
+ job_defer_to_main_loop_bh, data);
|
|
|
383d26 |
+}
|
|
|
383d26 |
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
|
|
|
383d26 |
index f9e37d4..4f8cba8 100644
|
|
|
383d26 |
--- a/tests/test-bdrv-drain.c
|
|
|
383d26 |
+++ b/tests/test-bdrv-drain.c
|
|
|
383d26 |
@@ -496,9 +496,10 @@ typedef struct TestBlockJob {
|
|
|
383d26 |
bool should_complete;
|
|
|
383d26 |
} TestBlockJob;
|
|
|
383d26 |
|
|
|
383d26 |
-static void test_job_completed(BlockJob *job, void *opaque)
|
|
|
383d26 |
+static void test_job_completed(Job *job, void *opaque)
|
|
|
383d26 |
{
|
|
|
383d26 |
- block_job_completed(job, 0);
|
|
|
383d26 |
+ BlockJob *bjob = container_of(job, BlockJob, job);
|
|
|
383d26 |
+ block_job_completed(bjob, 0);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
static void coroutine_fn test_job_start(void *opaque)
|
|
|
383d26 |
@@ -510,7 +511,7 @@ static void coroutine_fn test_job_start(void *opaque)
|
|
|
383d26 |
block_job_sleep_ns(&s->common, 100000);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
- block_job_defer_to_main_loop(&s->common, test_job_completed, NULL);
|
|
|
383d26 |
+ job_defer_to_main_loop(&s->common.job, test_job_completed, NULL);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
static void test_job_complete(BlockJob *job, Error **errp)
|
|
|
383d26 |
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
|
|
|
383d26 |
index 26b4bbb..c03f966 100644
|
|
|
383d26 |
--- a/tests/test-blockjob-txn.c
|
|
|
383d26 |
+++ b/tests/test-blockjob-txn.c
|
|
|
383d26 |
@@ -24,16 +24,17 @@ typedef struct {
|
|
|
383d26 |
int *result;
|
|
|
383d26 |
} TestBlockJob;
|
|
|
383d26 |
|
|
|
383d26 |
-static void test_block_job_complete(BlockJob *job, void *opaque)
|
|
|
383d26 |
+static void test_block_job_complete(Job *job, void *opaque)
|
|
|
383d26 |
{
|
|
|
383d26 |
- BlockDriverState *bs = blk_bs(job->blk);
|
|
|
383d26 |
+ BlockJob *bjob = container_of(job, BlockJob, job);
|
|
|
383d26 |
+ BlockDriverState *bs = blk_bs(bjob->blk);
|
|
|
383d26 |
int rc = (intptr_t)opaque;
|
|
|
383d26 |
|
|
|
383d26 |
- if (job_is_cancelled(&job->job)) {
|
|
|
383d26 |
+ if (job_is_cancelled(job)) {
|
|
|
383d26 |
rc = -ECANCELED;
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
- block_job_completed(job, rc);
|
|
|
383d26 |
+ block_job_completed(bjob, rc);
|
|
|
383d26 |
bdrv_unref(bs);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
@@ -54,8 +55,8 @@ static void coroutine_fn test_block_job_run(void *opaque)
|
|
|
383d26 |
}
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
- block_job_defer_to_main_loop(job, test_block_job_complete,
|
|
|
383d26 |
- (void *)(intptr_t)s->rc);
|
|
|
383d26 |
+ job_defer_to_main_loop(&job->job, test_block_job_complete,
|
|
|
383d26 |
+ (void *)(intptr_t)s->rc);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
typedef struct {
|
|
|
383d26 |
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
|
|
|
383d26 |
index fa31481..5f43bd7 100644
|
|
|
383d26 |
--- a/tests/test-blockjob.c
|
|
|
383d26 |
+++ b/tests/test-blockjob.c
|
|
|
383d26 |
@@ -161,11 +161,12 @@ typedef struct CancelJob {
|
|
|
383d26 |
bool completed;
|
|
|
383d26 |
} CancelJob;
|
|
|
383d26 |
|
|
|
383d26 |
-static void cancel_job_completed(BlockJob *job, void *opaque)
|
|
|
383d26 |
+static void cancel_job_completed(Job *job, void *opaque)
|
|
|
383d26 |
{
|
|
|
383d26 |
+ BlockJob *bjob = container_of(job, BlockJob, job);
|
|
|
383d26 |
CancelJob *s = opaque;
|
|
|
383d26 |
s->completed = true;
|
|
|
383d26 |
- block_job_completed(job, 0);
|
|
|
383d26 |
+ block_job_completed(bjob, 0);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
static void cancel_job_complete(BlockJob *job, Error **errp)
|
|
|
383d26 |
@@ -191,7 +192,7 @@ static void coroutine_fn cancel_job_start(void *opaque)
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
defer:
|
|
|
383d26 |
- block_job_defer_to_main_loop(&s->common, cancel_job_completed, s);
|
|
|
383d26 |
+ job_defer_to_main_loop(&s->common.job, cancel_job_completed, s);
|
|
|
383d26 |
}
|
|
|
383d26 |
|
|
|
383d26 |
static const BlockJobDriver test_cancel_driver = {
|
|
|
383d26 |
--
|
|
|
383d26 |
1.8.3.1
|
|
|
383d26 |
|