|
|
ae23c9 |
From ba0f4624b12b27820e7e59b5e2a6a84f9736533d Mon Sep 17 00:00:00 2001
|
|
|
ae23c9 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
ae23c9 |
Date: Tue, 26 Jun 2018 09:48:18 +0200
|
|
|
ae23c9 |
Subject: [PATCH 110/268] job: Add job_drain()
|
|
|
ae23c9 |
|
|
|
ae23c9 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
ae23c9 |
Message-id: <20180626094856.6924-36-kwolf@redhat.com>
|
|
|
ae23c9 |
Patchwork-id: 81119
|
|
|
ae23c9 |
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH v2 35/73] job: Add job_drain()
|
|
|
ae23c9 |
Bugzilla: 1513543
|
|
|
ae23c9 |
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
|
|
|
ae23c9 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
ae23c9 |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
ae23c9 |
|
|
|
ae23c9 |
block_job_drain() contains a blk_drain() call which cannot be moved to
|
|
|
ae23c9 |
Job, so add a new JobDriver callback JobDriver.drain which has a common
|
|
|
ae23c9 |
implementation for all BlockJobs. In addition to this we keep the
|
|
|
ae23c9 |
existing BlockJobDriver.drain callback that is called by the common
|
|
|
ae23c9 |
drain implementation for all block jobs.
|
|
|
ae23c9 |
|
|
|
ae23c9 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
ae23c9 |
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
|
ae23c9 |
(cherry picked from commit b69f777dd9ba992fdd35828a90eefcd88c0ec332)
|
|
|
ae23c9 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
ae23c9 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
ae23c9 |
---
|
|
|
ae23c9 |
block/backup.c | 1 +
|
|
|
ae23c9 |
block/commit.c | 1 +
|
|
|
ae23c9 |
block/mirror.c | 2 ++
|
|
|
ae23c9 |
block/stream.c | 1 +
|
|
|
ae23c9 |
blockjob.c | 20 ++++++++++----------
|
|
|
ae23c9 |
include/block/blockjob_int.h | 12 ++++++++++++
|
|
|
ae23c9 |
include/qemu/job.h | 13 +++++++++++++
|
|
|
ae23c9 |
job.c | 11 +++++++++++
|
|
|
ae23c9 |
tests/test-bdrv-drain.c | 1 +
|
|
|
ae23c9 |
tests/test-blockjob-txn.c | 1 +
|
|
|
ae23c9 |
tests/test-blockjob.c | 2 ++
|
|
|
ae23c9 |
11 files changed, 55 insertions(+), 10 deletions(-)
|
|
|
ae23c9 |
|
|
|
ae23c9 |
diff --git a/block/backup.c b/block/backup.c
|
|
|
ae23c9 |
index bd31282..ca7d990 100644
|
|
|
ae23c9 |
--- a/block/backup.c
|
|
|
ae23c9 |
+++ b/block/backup.c
|
|
|
ae23c9 |
@@ -529,6 +529,7 @@ static const BlockJobDriver backup_job_driver = {
|
|
|
ae23c9 |
.job_type = JOB_TYPE_BACKUP,
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
.start = backup_run,
|
|
|
ae23c9 |
.commit = backup_commit,
|
|
|
ae23c9 |
.abort = backup_abort,
|
|
|
ae23c9 |
diff --git a/block/commit.c b/block/commit.c
|
|
|
ae23c9 |
index e53b2d7..02a8af9 100644
|
|
|
ae23c9 |
--- a/block/commit.c
|
|
|
ae23c9 |
+++ b/block/commit.c
|
|
|
ae23c9 |
@@ -221,6 +221,7 @@ static const BlockJobDriver commit_job_driver = {
|
|
|
ae23c9 |
.job_type = JOB_TYPE_COMMIT,
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
.start = commit_run,
|
|
|
ae23c9 |
},
|
|
|
ae23c9 |
};
|
|
|
ae23c9 |
diff --git a/block/mirror.c b/block/mirror.c
|
|
|
ae23c9 |
index c3951d1..a579bd8 100644
|
|
|
ae23c9 |
--- a/block/mirror.c
|
|
|
ae23c9 |
+++ b/block/mirror.c
|
|
|
ae23c9 |
@@ -992,6 +992,7 @@ static const BlockJobDriver mirror_job_driver = {
|
|
|
ae23c9 |
.job_type = JOB_TYPE_MIRROR,
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
.start = mirror_run,
|
|
|
ae23c9 |
.pause = mirror_pause,
|
|
|
ae23c9 |
},
|
|
|
ae23c9 |
@@ -1006,6 +1007,7 @@ static const BlockJobDriver commit_active_job_driver = {
|
|
|
ae23c9 |
.job_type = JOB_TYPE_COMMIT,
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
.start = mirror_run,
|
|
|
ae23c9 |
.pause = mirror_pause,
|
|
|
ae23c9 |
},
|
|
|
ae23c9 |
diff --git a/block/stream.c b/block/stream.c
|
|
|
ae23c9 |
index eee0253..b996278 100644
|
|
|
ae23c9 |
--- a/block/stream.c
|
|
|
ae23c9 |
+++ b/block/stream.c
|
|
|
ae23c9 |
@@ -215,6 +215,7 @@ static const BlockJobDriver stream_job_driver = {
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.start = stream_run,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
},
|
|
|
ae23c9 |
};
|
|
|
ae23c9 |
|
|
|
ae23c9 |
diff --git a/blockjob.c b/blockjob.c
|
|
|
ae23c9 |
index 4cac367..63e1669 100644
|
|
|
ae23c9 |
--- a/blockjob.c
|
|
|
ae23c9 |
+++ b/blockjob.c
|
|
|
ae23c9 |
@@ -169,14 +169,13 @@ static void block_job_attached_aio_context(AioContext *new_context,
|
|
|
ae23c9 |
job_resume(&job->job);
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
|
|
|
ae23c9 |
-static void block_job_drain(BlockJob *job)
|
|
|
ae23c9 |
+void block_job_drain(Job *job)
|
|
|
ae23c9 |
{
|
|
|
ae23c9 |
- /* If job is !job->job.busy this kicks it into the next pause point. */
|
|
|
ae23c9 |
- block_job_enter(job);
|
|
|
ae23c9 |
+ BlockJob *bjob = container_of(job, BlockJob, job);
|
|
|
ae23c9 |
|
|
|
ae23c9 |
- blk_drain(job->blk);
|
|
|
ae23c9 |
- if (job->driver->drain) {
|
|
|
ae23c9 |
- job->driver->drain(job);
|
|
|
ae23c9 |
+ blk_drain(bjob->blk);
|
|
|
ae23c9 |
+ if (bjob->driver->drain) {
|
|
|
ae23c9 |
+ bjob->driver->drain(bjob);
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
|
|
|
ae23c9 |
@@ -190,7 +189,7 @@ static void block_job_detach_aio_context(void *opaque)
|
|
|
ae23c9 |
job_pause(&job->job);
|
|
|
ae23c9 |
|
|
|
ae23c9 |
while (!job->job.paused && !job_is_completed(&job->job)) {
|
|
|
ae23c9 |
- block_job_drain(job);
|
|
|
ae23c9 |
+ job_drain(&job->job);
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
|
|
|
ae23c9 |
job->job.aio_context = NULL;
|
|
|
ae23c9 |
@@ -327,11 +326,11 @@ static int block_job_finish_sync(BlockJob *job,
|
|
|
ae23c9 |
job_unref(&job->job);
|
|
|
ae23c9 |
return -EBUSY;
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
- /* block_job_drain calls block_job_enter, and it should be enough to
|
|
|
ae23c9 |
- * induce progress until the job completes or moves to the main thread.
|
|
|
ae23c9 |
+ /* job_drain calls job_enter, and it should be enough to induce progress
|
|
|
ae23c9 |
+ * until the job completes or moves to the main thread.
|
|
|
ae23c9 |
*/
|
|
|
ae23c9 |
while (!job->job.deferred_to_main_loop && !job_is_completed(&job->job)) {
|
|
|
ae23c9 |
- block_job_drain(job);
|
|
|
ae23c9 |
+ job_drain(&job->job);
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
while (!job_is_completed(&job->job)) {
|
|
|
ae23c9 |
aio_poll(qemu_get_aio_context(), true);
|
|
|
ae23c9 |
@@ -713,6 +712,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
|
|
ae23c9 |
assert(is_block_job(&job->job));
|
|
|
ae23c9 |
assert(job->job.driver->free == &block_job_free);
|
|
|
ae23c9 |
assert(job->job.driver->user_resume == &block_job_user_resume);
|
|
|
ae23c9 |
+ assert(job->job.driver->drain == &block_job_drain);
|
|
|
ae23c9 |
|
|
|
ae23c9 |
job->driver = driver;
|
|
|
ae23c9 |
job->blk = blk;
|
|
|
ae23c9 |
diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
|
|
|
ae23c9 |
index bf2b762..38fe22d 100644
|
|
|
ae23c9 |
--- a/include/block/blockjob_int.h
|
|
|
ae23c9 |
+++ b/include/block/blockjob_int.h
|
|
|
ae23c9 |
@@ -65,6 +65,10 @@ struct BlockJobDriver {
|
|
|
ae23c9 |
* If the callback is not NULL, it will be invoked when the job has to be
|
|
|
ae23c9 |
* synchronously cancelled or completed; it should drain BlockDriverStates
|
|
|
ae23c9 |
* as required to ensure progress.
|
|
|
ae23c9 |
+ *
|
|
|
ae23c9 |
+ * Block jobs must use the default implementation for job_driver.drain,
|
|
|
ae23c9 |
+ * which will in turn call this callback after doing generic block job
|
|
|
ae23c9 |
+ * stuff.
|
|
|
ae23c9 |
*/
|
|
|
ae23c9 |
void (*drain)(BlockJob *job);
|
|
|
ae23c9 |
};
|
|
|
ae23c9 |
@@ -112,6 +116,14 @@ void block_job_free(Job *job);
|
|
|
ae23c9 |
void block_job_user_resume(Job *job);
|
|
|
ae23c9 |
|
|
|
ae23c9 |
/**
|
|
|
ae23c9 |
+ * block_job_drain:
|
|
|
ae23c9 |
+ * Callback to be used for JobDriver.drain in all block jobs. Drains the main
|
|
|
ae23c9 |
+ * block node associated with the block jobs and calls BlockJobDriver.drain for
|
|
|
ae23c9 |
+ * job-specific actions.
|
|
|
ae23c9 |
+ */
|
|
|
ae23c9 |
+void block_job_drain(Job *job);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
+/**
|
|
|
ae23c9 |
* block_job_yield:
|
|
|
ae23c9 |
* @job: The job that calls the function.
|
|
|
ae23c9 |
*
|
|
|
ae23c9 |
diff --git a/include/qemu/job.h b/include/qemu/job.h
|
|
|
ae23c9 |
index 2648c74..aebc195 100644
|
|
|
ae23c9 |
--- a/include/qemu/job.h
|
|
|
ae23c9 |
+++ b/include/qemu/job.h
|
|
|
ae23c9 |
@@ -167,6 +167,13 @@ struct JobDriver {
|
|
|
ae23c9 |
*/
|
|
|
ae23c9 |
void (*user_resume)(Job *job);
|
|
|
ae23c9 |
|
|
|
ae23c9 |
+ /*
|
|
|
ae23c9 |
+ * If the callback is not NULL, it will be invoked when the job has to be
|
|
|
ae23c9 |
+ * synchronously cancelled or completed; it should drain any activities
|
|
|
ae23c9 |
+ * as required to ensure progress.
|
|
|
ae23c9 |
+ */
|
|
|
ae23c9 |
+ void (*drain)(Job *job);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
/**
|
|
|
ae23c9 |
* If the callback is not NULL, it will be invoked when all the jobs
|
|
|
ae23c9 |
* belonging to the same transaction complete; or upon this job's
|
|
|
ae23c9 |
@@ -325,6 +332,12 @@ bool job_user_paused(Job *job);
|
|
|
ae23c9 |
*/
|
|
|
ae23c9 |
void job_user_resume(Job *job, Error **errp);
|
|
|
ae23c9 |
|
|
|
ae23c9 |
+/*
|
|
|
ae23c9 |
+ * Drain any activities as required to ensure progress. This can be called in a
|
|
|
ae23c9 |
+ * loop to synchronously complete a job.
|
|
|
ae23c9 |
+ */
|
|
|
ae23c9 |
+void job_drain(Job *job);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
/**
|
|
|
ae23c9 |
* Get the next element from the list of block jobs after @job, or the
|
|
|
ae23c9 |
* first one if @job is %NULL.
|
|
|
ae23c9 |
diff --git a/job.c b/job.c
|
|
|
ae23c9 |
index 64b64da..3772a35 100644
|
|
|
ae23c9 |
--- a/job.c
|
|
|
ae23c9 |
+++ b/job.c
|
|
|
ae23c9 |
@@ -367,6 +367,17 @@ void coroutine_fn job_sleep_ns(Job *job, int64_t ns)
|
|
|
ae23c9 |
job_pause_point(job);
|
|
|
ae23c9 |
}
|
|
|
ae23c9 |
|
|
|
ae23c9 |
+void job_drain(Job *job)
|
|
|
ae23c9 |
+{
|
|
|
ae23c9 |
+ /* If job is !busy this kicks it into the next pause point. */
|
|
|
ae23c9 |
+ job_enter(job);
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
+ if (job->driver->drain) {
|
|
|
ae23c9 |
+ job->driver->drain(job);
|
|
|
ae23c9 |
+ }
|
|
|
ae23c9 |
+}
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
+
|
|
|
ae23c9 |
/**
|
|
|
ae23c9 |
* All jobs must allow a pause point before entering their job proper. This
|
|
|
ae23c9 |
* ensures that jobs can be paused prior to being started, then resumed later.
|
|
|
ae23c9 |
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
|
|
|
ae23c9 |
index c993512..58ea566 100644
|
|
|
ae23c9 |
--- a/tests/test-bdrv-drain.c
|
|
|
ae23c9 |
+++ b/tests/test-bdrv-drain.c
|
|
|
ae23c9 |
@@ -525,6 +525,7 @@ BlockJobDriver test_job_driver = {
|
|
|
ae23c9 |
.instance_size = sizeof(TestBlockJob),
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
.start = test_job_start,
|
|
|
ae23c9 |
},
|
|
|
ae23c9 |
.complete = test_job_complete,
|
|
|
ae23c9 |
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
|
|
|
ae23c9 |
index 60e9fa2..1572f8d 100644
|
|
|
ae23c9 |
--- a/tests/test-blockjob-txn.c
|
|
|
ae23c9 |
+++ b/tests/test-blockjob-txn.c
|
|
|
ae23c9 |
@@ -79,6 +79,7 @@ static const BlockJobDriver test_block_job_driver = {
|
|
|
ae23c9 |
.instance_size = sizeof(TestBlockJob),
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
.start = test_block_job_run,
|
|
|
ae23c9 |
},
|
|
|
ae23c9 |
};
|
|
|
ae23c9 |
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
|
|
|
ae23c9 |
index 1fe6803..592a136 100644
|
|
|
ae23c9 |
--- a/tests/test-blockjob.c
|
|
|
ae23c9 |
+++ b/tests/test-blockjob.c
|
|
|
ae23c9 |
@@ -21,6 +21,7 @@ static const BlockJobDriver test_block_job_driver = {
|
|
|
ae23c9 |
.instance_size = sizeof(BlockJob),
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
},
|
|
|
ae23c9 |
};
|
|
|
ae23c9 |
|
|
|
ae23c9 |
@@ -201,6 +202,7 @@ static const BlockJobDriver test_cancel_driver = {
|
|
|
ae23c9 |
.instance_size = sizeof(CancelJob),
|
|
|
ae23c9 |
.free = block_job_free,
|
|
|
ae23c9 |
.user_resume = block_job_user_resume,
|
|
|
ae23c9 |
+ .drain = block_job_drain,
|
|
|
ae23c9 |
.start = cancel_job_start,
|
|
|
ae23c9 |
},
|
|
|
ae23c9 |
.complete = cancel_job_complete,
|
|
|
ae23c9 |
--
|
|
|
ae23c9 |
1.8.3.1
|
|
|
ae23c9 |
|