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