[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH v5 15/21] blockjobs: add prepare callback
From: |
John Snow |
Subject: |
[Qemu-block] [PATCH v5 15/21] blockjobs: add prepare callback |
Date: |
Sat, 10 Mar 2018 03:27:40 -0500 |
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 <address@hidden>
---
blockjob.c | 30 +++++++++++++++++++++++++++---
include/block/blockjob_int.h | 10 ++++++++++
2 files changed, 37 insertions(+), 3 deletions(-)
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);
}
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
@@ -53,6 +53,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
--
2.14.3
- [Qemu-block] [PATCH v5 00/21] blockjobs: add explicit job management, John Snow, 2018/03/10
- [Qemu-block] [PATCH v5 14/21] blockjobs: add block_job_txn_apply function, John Snow, 2018/03/10
- [Qemu-block] [PATCH v5 09/21] blockjobs: add CONCLUDED state, John Snow, 2018/03/10
- [Qemu-block] [PATCH v5 01/21] blockjobs: fix set-speed kick, John Snow, 2018/03/10
- [Qemu-block] [PATCH v5 03/21] Blockjobs: documentation touchup, John Snow, 2018/03/10
- [Qemu-block] [PATCH v5 06/21] iotests: add pause_wait, John Snow, 2018/03/10
- [Qemu-block] [PATCH v5 12/21] blockjobs: ensure abort is called for cancelled jobs, John Snow, 2018/03/10
- [Qemu-block] [PATCH v5 08/21] blockjobs: add ABORTING state, John Snow, 2018/03/10
- [Qemu-block] [PATCH v5 15/21] blockjobs: add prepare callback,
John Snow <=
- [Qemu-block] [PATCH v5 10/21] blockjobs: add NULL state, John Snow, 2018/03/10
[Qemu-block] [PATCH v5 11/21] blockjobs: add block_job_dismiss, John Snow, 2018/03/10
[Qemu-block] [PATCH v5 13/21] blockjobs: add commit, abort, clean helpers, John Snow, 2018/03/10
[Qemu-block] [PATCH v5 05/21] blockjobs: add state transition table, John Snow, 2018/03/10
[Qemu-block] [PATCH v5 02/21] blockjobs: model single jobs as transactions, John Snow, 2018/03/10
[Qemu-block] [PATCH v5 16/21] blockjobs: add waiting status, John Snow, 2018/03/10