{
uint64_t delay_ns;
- if (block_job_is_cancelled(&job->common)) {
+ if (job_is_cancelled(&job->common.job)) {
return true;
}
job->bytes_read = 0;
block_job_sleep_ns(&job->common, delay_ns);
- if (block_job_is_cancelled(&job->common)) {
+ if (job_is_cancelled(&job->common.job)) {
return true;
}
if (job->sync_mode == MIRROR_SYNC_MODE_NONE) {
/* All bits are set in copy_bitmap to allow any cluster to be copied.
* This does not actually require them to be copied. */
- while (!block_job_is_cancelled(&job->common)) {
+ while (!job_is_cancelled(&job->common.job)) {
/* Yield until the job is cancelled. We just let our before_write
* notify callback service CoW requests. */
block_job_yield(&job->common);
* the normal backing chain can be restored. */
blk_unref(s->base);
- if (!block_job_is_cancelled(&s->common) && ret == 0) {
+ if (!job_is_cancelled(&s->common.job) && ret == 0) {
/* success */
ret = bdrv_drop_intermediate(s->commit_top_bs, base,
s->backing_file_str);
* with no pending I/O here so that bdrv_drain_all() returns.
*/
block_job_sleep_ns(&s->common, delay_ns);
- if (block_job_is_cancelled(&s->common)) {
+ if (job_is_cancelled(&s->common.job)) {
break;
}
/* Copy if allocated above the base */
mirror_throttle(s);
- if (block_job_is_cancelled(&s->common)) {
+ if (job_is_cancelled(&s->common.job)) {
s->initial_zeroing_ongoing = false;
return 0;
}
mirror_throttle(s);
- if (block_job_is_cancelled(&s->common)) {
+ if (job_is_cancelled(&s->common.job)) {
return 0;
}
checking for a NULL string */
int ret = 0;
- if (block_job_is_cancelled(&s->common)) {
+ if (job_is_cancelled(&s->common.job)) {
goto immediate_exit;
}
/* Report BLOCK_JOB_READY and wait for complete. */
block_job_event_ready(&s->common);
s->synced = true;
- while (!block_job_is_cancelled(&s->common) && !s->should_complete) {
+ while (!job_is_cancelled(&s->common.job) && !s->should_complete) {
block_job_yield(&s->common);
}
- s->common.cancelled = false;
+ s->common.job.cancelled = false;
goto immediate_exit;
}
s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
if (!s->is_none_mode) {
ret = mirror_dirty_init(s);
- if (ret < 0 || block_job_is_cancelled(&s->common)) {
+ if (ret < 0 || job_is_cancelled(&s->common.job)) {
goto immediate_exit;
}
}
}
should_complete = s->should_complete ||
- block_job_is_cancelled(&s->common);
+ job_is_cancelled(&s->common.job);
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
}
* completion.
*/
assert(QLIST_EMPTY(&bs->tracked_requests));
- s->common.cancelled = false;
+ s->common.job.cancelled = false;
need_drain = false;
break;
}
}
trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
block_job_sleep_ns(&s->common, delay_ns);
- if (block_job_is_cancelled(&s->common) &&
+ if (job_is_cancelled(&s->common.job) &&
(!s->synced || s->common.force))
{
break;
* the target is a copy of the source.
*/
assert(ret < 0 || ((s->common.force || !s->synced) &&
- block_job_is_cancelled(&s->common)));
+ job_is_cancelled(&s->common.job)));
assert(need_drain);
mirror_wait_for_all_io(s);
}
BlockDriverState *base = s->base;
Error *local_err = NULL;
- if (!block_job_is_cancelled(&s->common) && bs->backing &&
+ if (!job_is_cancelled(&s->common.job) && bs->backing &&
data->ret == 0) {
const char *base_id = NULL, *base_fmt = NULL;
if (base) {
* with no pending I/O here so that bdrv_drain_all() returns.
*/
block_job_sleep_ns(&s->common, delay_ns);
- if (block_job_is_cancelled(&s->common)) {
+ if (job_is_cancelled(&s->common.job)) {
break;
}
static void block_job_update_rc(BlockJob *job)
{
- if (!job->ret && block_job_is_cancelled(job)) {
+ if (!job->ret && job_is_cancelled(&job->job)) {
job->ret = -ECANCELED;
}
if (job->ret) {
/* Emit events only if we actually started */
if (block_job_started(job)) {
- if (block_job_is_cancelled(job)) {
+ if (job_is_cancelled(&job->job)) {
block_job_event_cancelled(job);
} else {
const char *msg = NULL;
job->user_paused = false;
job->pause_count--;
}
- job->cancelled = true;
+ job->job.cancelled = true;
/* To prevent 'force == false' overriding a previous 'force == true' */
job->force |= force;
}
while (!job->completed) {
aio_poll(qemu_get_aio_context(), true);
}
- ret = (job->cancelled && job->ret == 0) ? -ECANCELED : job->ret;
+ ret = (job_is_cancelled(&job->job) && job->ret == 0)
+ ? -ECANCELED : job->ret;
job_unref(&job->job);
return ret;
}
other_job = QLIST_FIRST(&txn->jobs);
ctx = blk_get_aio_context(other_job->blk);
if (!other_job->completed) {
- assert(other_job->cancelled);
+ assert(job_is_cancelled(&other_job->job));
block_job_finish_sync(other_job, NULL, NULL);
}
block_job_finalize_single(other_job);
if (job_apply_verb(&job->job, JOB_VERB_COMPLETE, errp)) {
return;
}
- if (job->pause_count || job->cancelled || !job->driver->complete) {
+ if (job->pause_count || job_is_cancelled(&job->job) ||
+ !job->driver->complete)
+ {
error_setg(errp, "The active block job '%s' cannot be completed",
job->job.id);
return;
if (!block_job_should_pause(job)) {
return;
}
- if (block_job_is_cancelled(job)) {
+ if (job_is_cancelled(&job->job)) {
return;
}
job->driver->pause(job);
}
- if (block_job_should_pause(job) && !block_job_is_cancelled(job)) {
+ if (block_job_should_pause(job) && !job_is_cancelled(&job->job)) {
JobStatus status = job->job.status;
job_state_transition(&job->job, status == JOB_STATUS_READY
? JOB_STATUS_STANDBY
block_job_enter_cond(job, NULL);
}
-bool block_job_is_cancelled(BlockJob *job)
-{
- return job->cancelled;
-}
-
void block_job_sleep_ns(BlockJob *job, int64_t ns)
{
assert(job->busy);
/* Check cancellation *before* setting busy = false, too! */
- if (block_job_is_cancelled(job)) {
+ if (job_is_cancelled(&job->job)) {
return;
}
assert(job->busy);
/* Check cancellation *before* setting busy = false, too! */
- if (block_job_is_cancelled(job)) {
+ if (job_is_cancelled(&job->job)) {
return;
}
*/
Coroutine *co;
- /**
- * Set to true if the job should cancel itself. The flag must
- * always be tested just before toggling the busy flag from false
- * to true. After a job has been cancelled, it should only yield
- * if #aio_poll will ("sooner or later") reenter the coroutine.
- */
- bool cancelled;
-
/**
* Set to true if the job should abort immediately without waiting
* for data to be in sync.
*/
void block_job_completed(BlockJob *job, int ret);
-/**
- * block_job_is_cancelled:
- * @job: The job being queried.
- *
- * Returns whether the job is scheduled for cancellation.
- */
-bool block_job_is_cancelled(BlockJob *job);
-
/**
* block_job_pause_point:
* @job: The job that is ready to pause.
/** Current state; See @JobStatus for details. */
JobStatus status;
+ /**
+ * Set to true if the job should cancel itself. The flag must
+ * always be tested just before toggling the busy flag from false
+ * to true. After a job has been cancelled, it should only yield
+ * if #aio_poll will ("sooner or later") reenter the coroutine.
+ */
+ bool cancelled;
+
/** Element of the list of jobs */
QLIST_ENTRY(Job) job_list;
} Job;
/** Returns the enum string for the JobType of a given Job. */
const char *job_type_str(const Job *job);
+/** Returns whether the job is scheduled for cancellation. */
+bool job_is_cancelled(Job *job);
+
/**
* Get the next element from the list of block jobs after @job, or the
* first one if @job is %NULL.
return JobType_str(job_type(job));
}
+bool job_is_cancelled(Job *job)
+{
+ return job->cancelled;
+}
+
Job *job_next(Job *job)
{
if (!job) {
BlockDriverState *bs = blk_bs(job->blk);
int rc = (intptr_t)opaque;
- if (block_job_is_cancelled(job)) {
+ if (job_is_cancelled(&job->job)) {
rc = -ECANCELED;
}
block_job_yield(job);
}
- if (block_job_is_cancelled(job)) {
+ if (job_is_cancelled(&job->job)) {
break;
}
}
static void test_block_job_cb(void *opaque, int ret)
{
TestBlockJobCBData *data = opaque;
- if (!ret && block_job_is_cancelled(&data->job->common)) {
+ if (!ret && job_is_cancelled(&data->job->common.job)) {
ret = -ECANCELED;
}
*data->result = ret;
CancelJob *s = opaque;
while (!s->should_complete) {
- if (block_job_is_cancelled(&s->common)) {
+ if (job_is_cancelled(&s->common.job)) {
goto defer;
}