On 02/23/2018 05:51 PM, John Snow wrote:
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 WAITING state
(added in a forthcoming commit)
- All jobs prepare to call either commit/abort
- If any job fails, is canceled, or fails preparation, all jobs
call their .abort callback.
- All jobs enter the PENDING state, awaiting manual intervention
(also added in a forthcoming commit)
- block-job-finalize is issued by the user/management layer
- All jobs call their commit callbacks.
Signed-off-by: John Snow <js...@redhat.com>
---
blockjob.c | 34 +++++++++++++++++++++++++++++++---
include/block/blockjob_int.h | 10 ++++++++++
2 files changed, 41 insertions(+), 3 deletions(-)
@@ -467,17 +480,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;
+ }
This short-circuits the application of the function to the rest of the
group. Is that ever going to be a problem?
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org