summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/backup.c2
-rw-r--r--block/trace-events1
-rw-r--r--blockjob.c21
3 files changed, 18 insertions, 6 deletions
diff --git a/block/backup.c b/block/backup.c
index 7e254dabff..453cd62c24 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -206,7 +206,7 @@ static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
BdrvDirtyBitmap *bm;
BlockDriverState *bs = blk_bs(job->common.blk);
- if (ret < 0 || block_job_is_cancelled(&job->common)) {
+ if (ret < 0) {
/* Merge the successor back into the parent, delete nothing. */
bm = bdrv_reclaim_dirty_bitmap(bs, job->sync_bitmap, NULL);
assert(bm);
diff --git a/block/trace-events b/block/trace-events
index 7212f2ae2d..1c6edb0b5a 100644
--- a/block/trace-events
+++ b/block/trace-events
@@ -5,6 +5,7 @@ bdrv_open_common(void *bs, const char *filename, int flags, const char *format_n
bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d"
# blockjob.c
+block_job_completed(void *job, int ret, int jret) "job %p ret %d corrected ret %d"
block_job_state_transition(void *job, int ret, const char *legal, const char *s0, const char *s1) "job %p (ret: %d) attempting %s transition (%s-->%s)"
block_job_apply_verb(void *job, const char *state, const char *verb, const char *legal) "job %p in state %s; applying verb %s (%s)"
diff --git a/blockjob.c b/blockjob.c
index 59ac4a13c7..61af628376 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -51,7 +51,7 @@ bool BlockJobSTT[BLOCK_JOB_STATUS__MAX][BLOCK_JOB_STATUS__MAX] = {
/* P: */ [BLOCK_JOB_STATUS_PAUSED] = {0, 0, 1, 0, 0, 0, 0, 0, 0},
/* Y: */ [BLOCK_JOB_STATUS_READY] = {0, 0, 0, 0, 0, 1, 1, 1, 0},
/* S: */ [BLOCK_JOB_STATUS_STANDBY] = {0, 0, 0, 0, 1, 0, 0, 0, 0},
- /* X: */ [BLOCK_JOB_STATUS_ABORTING] = {0, 0, 0, 0, 0, 0, 0, 1, 0},
+ /* X: */ [BLOCK_JOB_STATUS_ABORTING] = {0, 0, 0, 0, 0, 0, 1, 1, 0},
/* E: */ [BLOCK_JOB_STATUS_CONCLUDED] = {0, 0, 0, 0, 0, 0, 0, 0, 1},
/* N: */ [BLOCK_JOB_STATUS_NULL] = {0, 0, 0, 0, 0, 0, 0, 0, 0},
};
@@ -405,13 +405,22 @@ static void block_job_conclude(BlockJob *job)
}
}
+static void block_job_update_rc(BlockJob *job)
+{
+ if (!job->ret && block_job_is_cancelled(job)) {
+ job->ret = -ECANCELED;
+ }
+ if (job->ret) {
+ block_job_state_transition(job, BLOCK_JOB_STATUS_ABORTING);
+ }
+}
+
static void block_job_completed_single(BlockJob *job)
{
assert(job->completed);
- if (job->ret || block_job_is_cancelled(job)) {
- block_job_state_transition(job, BLOCK_JOB_STATUS_ABORTING);
- }
+ /* Ensure abort is called for late-transactional failures */
+ block_job_update_rc(job);
if (!job->ret) {
if (job->driver->commit) {
@@ -896,7 +905,9 @@ void block_job_completed(BlockJob *job, int ret)
assert(blk_bs(job->blk)->job == job);
job->completed = true;
job->ret = ret;
- if (ret < 0 || block_job_is_cancelled(job)) {
+ block_job_update_rc(job);
+ trace_block_job_completed(job, ret, job->ret);
+ if (job->ret) {
block_job_completed_txn_abort(job);
} else {
block_job_completed_txn_success(job);