BlockJob *bjob = container_of(job, BlockJob, job);
block_job_remove_all_bdrv(bjob);
- blk_unref(bjob->blk);
ratelimit_destroy(&bjob->limit);
error_free(bjob->blocker);
}
BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
{
BlockJobInfo *info;
+ uint64_t progress_current, progress_total;
if (block_job_is_internal(job)) {
error_setg(errp, "Cannot query QEMU internal jobs");
return NULL;
}
+
+ progress_get_snapshot(&job->job.progress, &progress_current,
+ &progress_total);
+
info = g_new0(BlockJobInfo, 1);
info->type = g_strdup(job_type_str(&job->job));
info->device = g_strdup(job->job.id);
info->busy = qatomic_read(&job->job.busy);
info->paused = job->job.pause_count > 0;
- info->offset = job->job.progress.current;
- info->len = job->job.progress.total;
+ info->offset = progress_current;
+ info->len = progress_total;
info->speed = job->speed;
info->io_status = job->iostatus;
info->ready = job_is_ready(&job->job),
static void block_job_event_cancelled(Notifier *n, void *opaque)
{
BlockJob *job = opaque;
+ uint64_t progress_current, progress_total;
if (block_job_is_internal(job)) {
return;
}
+ progress_get_snapshot(&job->job.progress, &progress_current,
+ &progress_total);
+
qapi_event_send_block_job_cancelled(job_type(&job->job),
job->job.id,
- job->job.progress.total,
- job->job.progress.current,
+ progress_total,
+ progress_current,
job->speed);
}
{
BlockJob *job = opaque;
const char *msg = NULL;
+ uint64_t progress_current, progress_total;
if (block_job_is_internal(job)) {
return;
msg = error_get_pretty(job->job.err);
}
+ progress_get_snapshot(&job->job.progress, &progress_current,
+ &progress_total);
+
qapi_event_send_block_job_completed(job_type(&job->job),
job->job.id,
- job->job.progress.total,
- job->job.progress.current,
+ progress_total,
+ progress_current,
job->speed,
!!msg,
msg);
static void block_job_event_ready(Notifier *n, void *opaque)
{
BlockJob *job = opaque;
+ uint64_t progress_current, progress_total;
if (block_job_is_internal(job)) {
return;
}
+ progress_get_snapshot(&job->job.progress, &progress_current,
+ &progress_total);
+
qapi_event_send_block_job_ready(job_type(&job->job),
job->job.id,
- job->job.progress.total,
- job->job.progress.current,
+ progress_total,
+ progress_current,
job->speed);
}
uint64_t shared_perm, int64_t speed, int flags,
BlockCompletionFunc *cb, void *opaque, Error **errp)
{
- BlockBackend *blk;
BlockJob *job;
+ int ret;
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
job_id = bdrv_get_device_name(bs);
}
- blk = blk_new_with_bs(bs, perm, shared_perm, errp);
- if (!blk) {
- return NULL;
- }
-
- job = job_create(job_id, &driver->job_driver, txn, blk_get_aio_context(blk),
+ job = job_create(job_id, &driver->job_driver, txn, bdrv_get_aio_context(bs),
flags, cb, opaque, errp);
if (job == NULL) {
- blk_unref(blk);
return NULL;
}
ratelimit_init(&job->limit);
- job->blk = blk;
-
job->finalize_cancelled_notifier.notify = block_job_event_cancelled;
job->finalize_completed_notifier.notify = block_job_event_completed;
job->pending_notifier.notify = block_job_event_pending;
error_setg(&job->blocker, "block device is in use by block job: %s",
job_type_str(&job->job));
- block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
- bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker);
+ ret = block_job_add_bdrv(job, "main node", bs, perm, shared_perm, errp);
+ if (ret < 0) {
+ goto fail;
+ }
- /* Disable request queuing in the BlockBackend to avoid deadlocks on drain:
- * The job reports that it's busy until it reaches a pause point. */
- blk_set_disable_request_queuing(blk, true);
- blk_set_allow_aio_context_change(blk, true);
+ bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker);
if (!block_job_set_speed(job, speed, errp)) {
- job_early_fail(&job->job);
- return NULL;
+ goto fail;
}
return job;
+
+fail:
+ job_early_fail(&job->job);
+ return NULL;
}
void block_job_iostatus_reset(BlockJob *job)
}
return action;
}
+
+AioContext *block_job_get_aio_context(BlockJob *job)
+{
+ return job->job.aio_context;
+}