Skip to content

Commit 1266c9b

Browse files
committed
job: Add error message for failing jobs
So far we relied on job->ret and strerror() to produce an error message for failed jobs. Not surprisingly, this tends to result in completely useless messages. This adds a Job.error field that can contain an error string for a failing job, and a parameter to job_completed() that sets the field. As a default, if NULL is passed, we continue to use strerror(job->ret). All existing callers are changed to pass NULL. They can be improved in separate patches. Signed-off-by: Kevin Wolf <[email protected]> Reviewed-by: Max Reitz <[email protected]> Reviewed-by: Jeff Cody <[email protected]>
1 parent 4a5f277 commit 1266c9b

10 files changed

+29
-17
lines changed

block/backup.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ static void backup_complete(Job *job, void *opaque)
321321
{
322322
BackupCompleteData *data = opaque;
323323

324-
job_completed(job, data->ret);
324+
job_completed(job, data->ret, NULL);
325325
g_free(data);
326326
}
327327

block/commit.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ static void commit_complete(Job *job, void *opaque)
117117
* bdrv_set_backing_hd() to fail. */
118118
block_job_remove_all_bdrv(bjob);
119119

120-
job_completed(job, ret);
120+
job_completed(job, ret, NULL);
121121
g_free(data);
122122

123123
/* If bdrv_drop_intermediate() didn't already do that, remove the commit

block/mirror.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ static void mirror_exit(Job *job, void *opaque)
581581
blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
582582
blk_insert_bs(bjob->blk, mirror_top_bs, &error_abort);
583583

584-
job_completed(job, data->ret);
584+
job_completed(job, data->ret, NULL);
585585

586586
g_free(data);
587587
bdrv_drained_end(src);

block/stream.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ static void stream_complete(Job *job, void *opaque)
9393
}
9494

9595
g_free(s->backing_file_str);
96-
job_completed(job, data->ret);
96+
job_completed(job, data->ret, NULL);
9797
g_free(data);
9898
}
9999

include/qemu/job.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ typedef struct Job {
124124
/** Estimated progress_current value at the completion of the job */
125125
int64_t progress_total;
126126

127+
/** Error string for a failed job (NULL if, and only if, job->ret == 0) */
128+
char *error;
129+
127130
/** ret code passed to job_completed. */
128131
int ret;
129132

@@ -466,13 +469,15 @@ void job_transition_to_ready(Job *job);
466469
/**
467470
* @job: The job being completed.
468471
* @ret: The status code.
472+
* @error: The error message for a failing job (only with @ret < 0). If @ret is
473+
* negative, but NULL is given for @error, strerror() is used.
469474
*
470475
* Marks @job as completed. If @ret is non-zero, the job transaction it is part
471476
* of is aborted. If @ret is zero, the job moves into the WAITING state. If it
472477
* is the last job to complete in its transaction, all jobs in the transaction
473478
* move from WAITING to PENDING.
474479
*/
475-
void job_completed(Job *job, int ret);
480+
void job_completed(Job *job, int ret, Error *error);
476481

477482
/** Asynchronously complete the specified @job. */
478483
void job_complete(Job *job, Error **errp);

job-qmp.c

+2-7
Original file line numberDiff line numberDiff line change
@@ -136,23 +136,18 @@ void qmp_job_dismiss(const char *id, Error **errp)
136136
static JobInfo *job_query_single(Job *job, Error **errp)
137137
{
138138
JobInfo *info;
139-
const char *errmsg = NULL;
140139

141140
assert(!job_is_internal(job));
142141

143-
if (job->ret < 0) {
144-
errmsg = strerror(-job->ret);
145-
}
146-
147142
info = g_new(JobInfo, 1);
148143
*info = (JobInfo) {
149144
.id = g_strdup(job->id),
150145
.type = job_type(job),
151146
.status = job->status,
152147
.current_progress = job->progress_current,
153148
.total_progress = job->progress_total,
154-
.has_error = !!errmsg,
155-
.error = g_strdup(errmsg),
149+
.has_error = !!job->error,
150+
.error = g_strdup(job->error),
156151
};
157152

158153
return info;

job.c

+14-2
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ void job_unref(Job *job)
369369

370370
QLIST_REMOVE(job, job_list);
371371

372+
g_free(job->error);
372373
g_free(job->id);
373374
g_free(job);
374375
}
@@ -660,6 +661,9 @@ static void job_update_rc(Job *job)
660661
job->ret = -ECANCELED;
661662
}
662663
if (job->ret) {
664+
if (!job->error) {
665+
job->error = g_strdup(strerror(-job->ret));
666+
}
663667
job_state_transition(job, JOB_STATUS_ABORTING);
664668
}
665669
}
@@ -782,6 +786,7 @@ static int job_prepare(Job *job)
782786
{
783787
if (job->ret == 0 && job->driver->prepare) {
784788
job->ret = job->driver->prepare(job);
789+
job_update_rc(job);
785790
}
786791
return job->ret;
787792
}
@@ -855,10 +860,17 @@ static void job_completed_txn_success(Job *job)
855860
}
856861
}
857862

858-
void job_completed(Job *job, int ret)
863+
void job_completed(Job *job, int ret, Error *error)
859864
{
860865
assert(job && job->txn && !job_is_completed(job));
866+
861867
job->ret = ret;
868+
if (error) {
869+
assert(job->ret < 0);
870+
job->error = g_strdup(error_get_pretty(error));
871+
error_free(error);
872+
}
873+
862874
job_update_rc(job);
863875
trace_job_completed(job, ret, job->ret);
864876
if (job->ret) {
@@ -876,7 +888,7 @@ void job_cancel(Job *job, bool force)
876888
}
877889
job_cancel_async(job, force);
878890
if (!job_started(job)) {
879-
job_completed(job, -ECANCELED);
891+
job_completed(job, -ECANCELED, NULL);
880892
} else if (job->deferred_to_main_loop) {
881893
job_completed_txn_abort(job);
882894
} else {

tests/test-bdrv-drain.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ typedef struct TestBlockJob {
498498

499499
static void test_job_completed(Job *job, void *opaque)
500500
{
501-
job_completed(job, 0);
501+
job_completed(job, 0, NULL);
502502
}
503503

504504
static void coroutine_fn test_job_start(void *opaque)

tests/test-blockjob-txn.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static void test_block_job_complete(Job *job, void *opaque)
3434
rc = -ECANCELED;
3535
}
3636

37-
job_completed(job, rc);
37+
job_completed(job, rc, NULL);
3838
bdrv_unref(bs);
3939
}
4040

tests/test-blockjob.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ static void cancel_job_completed(Job *job, void *opaque)
167167
{
168168
CancelJob *s = opaque;
169169
s->completed = true;
170-
job_completed(job, 0);
170+
job_completed(job, 0, NULL);
171171
}
172172

173173
static void cancel_job_complete(Job *job, Error **errp)

0 commit comments

Comments
 (0)