qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 15/41] blockjobs: add prepare callback
Date: Tue, 13 Mar 2018 17:17:37 +0100	[thread overview]
Message-ID: <20180313161803.1814-16-kwolf@redhat.com> (raw)
In-Reply-To: <20180313161803.1814-1-kwolf@redhat.com>

From: John Snow <jsnow@redhat.com>

Some jobs upon finalization may need to perform some work that can
still fail. If these jobs are part of a transaction, it's important
that these callbacks fail the entire transaction.

We allow for a new callback in addition to commit/abort/clean that
allows us the opportunity to have fairly late-breaking failures
in the transactional process.

The expected flow is:

- All jobs in a transaction converge to the PENDING state,
  added in a forthcoming commit.
- Upon being finalized, either automatically or explicitly
  by the user, jobs prepare to complete.
- If any job fails preparation, all jobs call .abort.
- Otherwise, they succeed and call .commit.

Signed-off-by: John Snow <jsnow@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/blockjob_int.h | 10 ++++++++++
 blockjob.c                   | 30 +++++++++++++++++++++++++++---
 2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
index 259d49b32a..642adce68b 100644
--- a/include/block/blockjob_int.h
+++ b/include/block/blockjob_int.h
@@ -54,6 +54,16 @@ struct BlockJobDriver {
     void (*complete)(BlockJob *job, Error **errp);
 
     /**
+     * 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.
+     *
+     * This callback will not be invoked if the job has already failed.
+     * If it fails, abort and then clean will be called.
+     */
+    int (*prepare)(BlockJob *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
      * completion if it is not in a transaction. Skipped if NULL.
diff --git a/blockjob.c b/blockjob.c
index 7e03824751..1395d8eed1 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -415,6 +415,14 @@ static void block_job_update_rc(BlockJob *job)
     }
 }
 
+static int block_job_prepare(BlockJob *job)
+{
+    if (job->ret == 0 && job->driver->prepare) {
+        job->ret = job->driver->prepare(job);
+    }
+    return job->ret;
+}
+
 static void block_job_commit(BlockJob *job)
 {
     assert(!job->ret);
@@ -438,7 +446,7 @@ static void block_job_clean(BlockJob *job)
     }
 }
 
-static void block_job_completed_single(BlockJob *job)
+static int block_job_completed_single(BlockJob *job)
 {
     assert(job->completed);
 
@@ -472,6 +480,7 @@ static void block_job_completed_single(BlockJob *job)
     QLIST_REMOVE(job, txn_list);
     block_job_txn_unref(job->txn);
     block_job_conclude(job);
+    return 0;
 }
 
 static void block_job_cancel_async(BlockJob *job)
@@ -487,17 +496,22 @@ static void block_job_cancel_async(BlockJob *job)
     job->cancelled = true;
 }
 
-static void block_job_txn_apply(BlockJobTxn *txn, void fn(BlockJob *))
+static int block_job_txn_apply(BlockJobTxn *txn, int fn(BlockJob *))
 {
     AioContext *ctx;
     BlockJob *job, *next;
+    int rc;
 
     QLIST_FOREACH_SAFE(job, &txn->jobs, txn_list, next) {
         ctx = blk_get_aio_context(job->blk);
         aio_context_acquire(ctx);
-        fn(job);
+        rc = fn(job);
         aio_context_release(ctx);
+        if (rc) {
+            break;
+        }
     }
+    return rc;
 }
 
 static int block_job_finish_sync(BlockJob *job,
@@ -580,6 +594,8 @@ static void block_job_completed_txn_success(BlockJob *job)
 {
     BlockJobTxn *txn = job->txn;
     BlockJob *other_job;
+    int rc = 0;
+
     /*
      * Successful completion, see if there are other running jobs in this
      * txn.
@@ -590,6 +606,14 @@ static void block_job_completed_txn_success(BlockJob *job)
         }
         assert(other_job->ret == 0);
     }
+
+    /* Jobs may require some prep-work to complete without failure */
+    rc = block_job_txn_apply(txn, block_job_prepare);
+    if (rc) {
+        block_job_completed_txn_abort(job);
+        return;
+    }
+
     /* We are the last completed job, commit the transaction. */
     block_job_txn_apply(txn, block_job_completed_single);
 }
-- 
2.13.6

  parent reply	other threads:[~2018-03-13 16:18 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-13 16:17 [Qemu-devel] [PULL 00/41] Block layer patches Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 01/41] blockjobs: fix set-speed kick Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 02/41] blockjobs: model single jobs as transactions Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 03/41] Blockjobs: documentation touchup Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 04/41] blockjobs: add status enum Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 05/41] blockjobs: add state transition table Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 06/41] iotests: add pause_wait Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 07/41] blockjobs: add block_job_verb permission table Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 08/41] blockjobs: add ABORTING state Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 09/41] blockjobs: add CONCLUDED state Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 10/41] blockjobs: add NULL state Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 11/41] blockjobs: add block_job_dismiss Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 12/41] blockjobs: ensure abort is called for cancelled jobs Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 13/41] blockjobs: add commit, abort, clean helpers Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 14/41] blockjobs: add block_job_txn_apply function Kevin Wolf
2018-03-13 16:17 ` Kevin Wolf [this message]
2018-03-13 16:17 ` [Qemu-devel] [PULL 16/41] blockjobs: add waiting status Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 17/41] blockjobs: add PENDING status and event Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 18/41] blockjobs: add block-job-finalize Kevin Wolf
2018-03-13 18:47   ` Eric Blake
2018-03-14 20:24     ` John Snow
2018-03-13 16:17 ` [Qemu-devel] [PULL 19/41] blockjobs: Expose manual property Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 20/41] iotests: test manual job dismissal Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 21/41] tests/test-blockjob: test cancellations Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 22/41] luks: Separate image file creation from formatting Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 23/41] luks: Create block_crypto_co_create_generic() Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 24/41] luks: Support .bdrv_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 25/41] luks: Turn invalid assertion into check Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 26/41] luks: Catch integer overflow for huge sizes Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 27/41] qemu-iotests: Test luks QMP image creation Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 28/41] vdi: Pull option parsing from vdi_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 29/41] vdi: Move file creation to vdi_co_create_opts Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 30/41] vdi: Implement .bdrv_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 31/41] block: Fix flags in reopen queue Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 32/41] iotests: Add regression test for commit base locking Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 33/41] parallels: Support .bdrv_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 34/41] qemu-iotests: Enable write tests for parallels Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 35/41] qcow: Support .bdrv_co_create Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 36/41] qed: " Kevin Wolf
2018-03-13 16:17 ` [Qemu-devel] [PULL 37/41] vdi: Make comments consistent with other drivers Kevin Wolf
2018-03-13 16:18 ` [Qemu-devel] [PULL 38/41] vhdx: Support .bdrv_co_create Kevin Wolf
2018-03-13 16:18 ` [Qemu-devel] [PULL 39/41] vpc: " Kevin Wolf
2018-03-13 16:18 ` [Qemu-devel] [PULL 40/41] vpc: Require aligned size in .bdrv_co_create Kevin Wolf
2018-03-13 16:18 ` [Qemu-devel] [PULL 41/41] block/mirror: change the semantic of 'force' of block-job-cancel Kevin Wolf
2018-03-13 17:13 ` [Qemu-devel] [PULL 00/41] Block layer patches no-reply
2018-03-15 16:42 ` Peter Maydell
2018-03-15 16:56   ` Kevin Wolf
2018-03-15 17:55     ` John Snow
2018-03-16 12:44       ` Kevin Wolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180313161803.1814-16-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).