diff mbox series

[27/42] job: Add job_drain()

Message ID 20180509162637.15575-28-kwolf@redhat.com
State New
Headers show
Series Generic background jobs | expand

Commit Message

Kevin Wolf May 9, 2018, 4:26 p.m. UTC
block_job_drain() contains a blk_drain() call which cannot be moved to
Job, so add a new JobDriver callback JobDriver.drain which has a common
implementation for all BlockJobs. In addition to this we keep the
existing BlockJobDriver.drain callback that is called by the common
drain implementation for all block jobs.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/blockjob_int.h | 12 ++++++++++++
 include/qemu/job.h           | 13 +++++++++++++
 block/backup.c               |  1 +
 block/commit.c               |  1 +
 block/mirror.c               |  2 ++
 block/stream.c               |  1 +
 blockjob.c                   | 20 ++++++++++----------
 job.c                        | 11 +++++++++++
 tests/test-bdrv-drain.c      |  1 +
 tests/test-blockjob-txn.c    |  1 +
 tests/test-blockjob.c        |  2 ++
 11 files changed, 55 insertions(+), 10 deletions(-)

Comments

Max Reitz May 14, 2018, 7:26 p.m. UTC | #1
On 2018-05-09 18:26, Kevin Wolf wrote:
> block_job_drain() contains a blk_drain() call which cannot be moved to
> Job, so add a new JobDriver callback JobDriver.drain which has a common
> implementation for all BlockJobs. In addition to this we keep the
> existing BlockJobDriver.drain callback that is called by the common
> drain implementation for all block jobs.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  include/block/blockjob_int.h | 12 ++++++++++++
>  include/qemu/job.h           | 13 +++++++++++++
>  block/backup.c               |  1 +
>  block/commit.c               |  1 +
>  block/mirror.c               |  2 ++
>  block/stream.c               |  1 +
>  blockjob.c                   | 20 ++++++++++----------
>  job.c                        | 11 +++++++++++
>  tests/test-bdrv-drain.c      |  1 +
>  tests/test-blockjob-txn.c    |  1 +
>  tests/test-blockjob.c        |  2 ++
>  11 files changed, 55 insertions(+), 10 deletions(-)
> 
> diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
> index bf2b762808..38fe22d7e0 100644
> --- a/include/block/blockjob_int.h
> +++ b/include/block/blockjob_int.h
> @@ -65,6 +65,10 @@ struct BlockJobDriver {
>       * If the callback is not NULL, it will be invoked when the job has to be
>       * synchronously cancelled or completed; it should drain BlockDriverStates
>       * as required to ensure progress.
> +     *
> +     * Block jobs must use the default implementation for job_driver.drain,
> +     * which will in turn call this callback after doing generic block job
> +     * stuff.
>       */
>      void (*drain)(BlockJob *job);

I don't really see the point of having two drain callbacks for block
jobs.  Well, it allows an assert() that block_job_drain() is called at
some point, but still.  I'd like block jobs to be not very special, but
this makes them a bit more special than they need to be.

Maybe I'd like it a bit more if there was a macro to automatically set
these mandatory values for block jobs...

But mostly a question of style, so I'll grudgingly give a:

Reviewed-by: Max Reitz <mreitz@redhat.com>

>  };
diff mbox series

Patch

diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
index bf2b762808..38fe22d7e0 100644
--- a/include/block/blockjob_int.h
+++ b/include/block/blockjob_int.h
@@ -65,6 +65,10 @@  struct BlockJobDriver {
      * If the callback is not NULL, it will be invoked when the job has to be
      * synchronously cancelled or completed; it should drain BlockDriverStates
      * as required to ensure progress.
+     *
+     * Block jobs must use the default implementation for job_driver.drain,
+     * which will in turn call this callback after doing generic block job
+     * stuff.
      */
     void (*drain)(BlockJob *job);
 };
@@ -112,6 +116,14 @@  void block_job_free(Job *job);
 void block_job_user_resume(Job *job);
 
 /**
+ * block_job_drain:
+ * Callback to be used for JobDriver.drain in all block jobs. Drains the main
+ * block node associated with the block jobs and calls BlockJobDriver.drain for
+ * job-specific actions.
+ */
+void block_job_drain(Job *job);
+
+/**
  * block_job_yield:
  * @job: The job that calls the function.
  *
diff --git a/include/qemu/job.h b/include/qemu/job.h
index b96ec10413..49e254f01a 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -167,6 +167,13 @@  struct JobDriver {
      */
     void (*user_resume)(Job *job);
 
+    /*
+     * If the callback is not NULL, it will be invoked when the job has to be
+     * synchronously cancelled or completed; it should drain any activities
+     * as required to ensure progress.
+     */
+    void (*drain)(Job *job);
+
     /**
      * If the callback is not NULL, it will be invoked when all the jobs
      * belonging to the same transaction complete; or upon this job's
@@ -325,6 +332,12 @@  bool job_user_paused(Job *job);
  */
 void job_user_resume(Job *job, Error **errp);
 
+/*
+ * Drain any activities as required to ensure progress. This can be called in a
+ * loop to synchronously complete a job.
+ */
+void job_drain(Job *job);
+
 /**
  * Get the next element from the list of block jobs after @job, or the
  * first one if @job is %NULL.
diff --git a/block/backup.c b/block/backup.c
index bd31282924..ca7d990b21 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -529,6 +529,7 @@  static const BlockJobDriver backup_job_driver = {
         .job_type               = JOB_TYPE_BACKUP,
         .free                   = block_job_free,
         .user_resume            = block_job_user_resume,
+        .drain                  = block_job_drain,
         .start                  = backup_run,
         .commit                 = backup_commit,
         .abort                  = backup_abort,
diff --git a/block/commit.c b/block/commit.c
index e53b2d7d55..02a8af9127 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -221,6 +221,7 @@  static const BlockJobDriver commit_job_driver = {
         .job_type      = JOB_TYPE_COMMIT,
         .free          = block_job_free,
         .user_resume   = block_job_user_resume,
+        .drain         = block_job_drain,
         .start         = commit_run,
     },
 };
diff --git a/block/mirror.c b/block/mirror.c
index f18240e34c..4ab7e088ee 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -992,6 +992,7 @@  static const BlockJobDriver mirror_job_driver = {
         .job_type               = JOB_TYPE_MIRROR,
         .free                   = block_job_free,
         .user_resume            = block_job_user_resume,
+        .drain                  = block_job_drain,
         .start                  = mirror_run,
         .pause                  = mirror_pause,
     },
@@ -1006,6 +1007,7 @@  static const BlockJobDriver commit_active_job_driver = {
         .job_type               = JOB_TYPE_COMMIT,
         .free                   = block_job_free,
         .user_resume            = block_job_user_resume,
+        .drain                  = block_job_drain,
         .start                  = mirror_run,
         .pause                  = mirror_pause,
     },
diff --git a/block/stream.c b/block/stream.c
index eee02538ed..b996278ab3 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -215,6 +215,7 @@  static const BlockJobDriver stream_job_driver = {
         .free          = block_job_free,
         .start         = stream_run,
         .user_resume   = block_job_user_resume,
+        .drain         = block_job_drain,
     },
 };
 
diff --git a/blockjob.c b/blockjob.c
index ca88e166e1..76d9cb32b3 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -170,14 +170,13 @@  static void block_job_attached_aio_context(AioContext *new_context,
     job_resume(&job->job);
 }
 
-static void block_job_drain(BlockJob *job)
+void block_job_drain(Job *job)
 {
-    /* If job is !job->job.busy this kicks it into the next pause point. */
-    block_job_enter(job);
+    BlockJob *bjob = container_of(job, BlockJob, job);
 
-    blk_drain(job->blk);
-    if (job->driver->drain) {
-        job->driver->drain(job);
+    blk_drain(bjob->blk);
+    if (bjob->driver->drain) {
+        bjob->driver->drain(bjob);
     }
 }
 
@@ -191,7 +190,7 @@  static void block_job_detach_aio_context(void *opaque)
     job_pause(&job->job);
 
     while (!job->job.paused && !job_is_completed(&job->job)) {
-        block_job_drain(job);
+        job_drain(&job->job);
     }
 
     job->job.aio_context = NULL;
@@ -328,11 +327,11 @@  static int block_job_finish_sync(BlockJob *job,
         job_unref(&job->job);
         return -EBUSY;
     }
-    /* block_job_drain calls block_job_enter, and it should be enough to
-     * induce progress until the job completes or moves to the main thread.
+    /* job_drain calls job_enter, and it should be enough to induce progress
+     * until the job completes or moves to the main thread.
     */
     while (!job->job.deferred_to_main_loop && !job_is_completed(&job->job)) {
-        block_job_drain(job);
+        job_drain(&job->job);
     }
     while (!job_is_completed(&job->job)) {
         aio_poll(qemu_get_aio_context(), true);
@@ -714,6 +713,7 @@  void *block_job_create(const char *job_id, const BlockJobDriver *driver,
     assert(is_block_job(&job->job));
     assert(job->job.driver->free == &block_job_free);
     assert(job->job.driver->user_resume == &block_job_user_resume);
+    assert(job->job.driver->drain == &block_job_drain);
 
     job->driver        = driver;
     job->blk           = blk;
diff --git a/job.c b/job.c
index 4591e09e92..6cc05f4476 100644
--- a/job.c
+++ b/job.c
@@ -367,6 +367,17 @@  void coroutine_fn job_sleep_ns(Job *job, int64_t ns)
     job_pause_point(job);
 }
 
+void job_drain(Job *job)
+{
+    /* If job is !busy this kicks it into the next pause point. */
+    job_enter(job);
+
+    if (job->driver->drain) {
+        job->driver->drain(job);
+    }
+}
+
+
 /**
  * All jobs must allow a pause point before entering their job proper. This
  * ensures that jobs can be paused prior to being started, then resumed later.
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
index c993512f66..58ea5663f0 100644
--- a/tests/test-bdrv-drain.c
+++ b/tests/test-bdrv-drain.c
@@ -525,6 +525,7 @@  BlockJobDriver test_job_driver = {
         .instance_size  = sizeof(TestBlockJob),
         .free           = block_job_free,
         .user_resume    = block_job_user_resume,
+        .drain          = block_job_drain,
         .start          = test_job_start,
     },
     .complete       = test_job_complete,
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
index 60e9fa2298..1572f8d96f 100644
--- a/tests/test-blockjob-txn.c
+++ b/tests/test-blockjob-txn.c
@@ -79,6 +79,7 @@  static const BlockJobDriver test_block_job_driver = {
         .instance_size = sizeof(TestBlockJob),
         .free          = block_job_free,
         .user_resume   = block_job_user_resume,
+        .drain         = block_job_drain,
         .start         = test_block_job_run,
     },
 };
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
index 1fe6803fe0..592a13613d 100644
--- a/tests/test-blockjob.c
+++ b/tests/test-blockjob.c
@@ -21,6 +21,7 @@  static const BlockJobDriver test_block_job_driver = {
         .instance_size = sizeof(BlockJob),
         .free          = block_job_free,
         .user_resume   = block_job_user_resume,
+        .drain         = block_job_drain,
     },
 };
 
@@ -201,6 +202,7 @@  static const BlockJobDriver test_cancel_driver = {
         .instance_size = sizeof(CancelJob),
         .free          = block_job_free,
         .user_resume   = block_job_user_resume,
+        .drain         = block_job_drain,
         .start         = cancel_job_start,
     },
     .complete      = cancel_job_complete,