Skip to content

Commit

Permalink
job: Add job_transition_to_ready()
Browse files Browse the repository at this point in the history
The transition to the READY state was still performed in the BlockJob
layer, in the same function that sent the BLOCK_JOB_READY QMP event.

This patch brings the state transition to the Job layer and implements
the QMP event using a notifier called from the Job layer, like we
already do for other events related to state transitions.

Signed-off-by: Kevin Wolf <[email protected]>
Reviewed-by: Max Reitz <[email protected]>
  • Loading branch information
kevmw committed May 23, 2018
1 parent df956ae commit 2e1795b
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 34 deletions.
6 changes: 3 additions & 3 deletions block/mirror.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,8 +727,8 @@ static void coroutine_fn mirror_run(void *opaque)
}

if (s->bdev_length == 0) {
/* Report BLOCK_JOB_READY and wait for complete. */
block_job_event_ready(&s->common);
/* Transition to the READY state and wait for complete. */
job_transition_to_ready(&s->common.job);
s->synced = true;
while (!job_is_cancelled(&s->common.job) && !s->should_complete) {
job_yield(&s->common.job);
Expand Down Expand Up @@ -824,7 +824,7 @@ static void coroutine_fn mirror_run(void *opaque)
* report completion. This way, block-job-cancel will leave
* the target in a consistent state.
*/
block_job_event_ready(&s->common);
job_transition_to_ready(&s->common.job);
s->synced = true;
}

Expand Down
33 changes: 18 additions & 15 deletions blockjob.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,22 @@ static void block_job_event_pending(Notifier *n, void *opaque)
&error_abort);
}

static void block_job_event_ready(Notifier *n, void *opaque)
{
BlockJob *job = opaque;

if (block_job_is_internal(job)) {
return;
}

qapi_event_send_block_job_ready(job_type(&job->job),
job->job.id,
job->len,
job->offset,
job->speed, &error_abort);
}


/*
* API for block job drivers and the block layer. These functions are
* declared in blockjob_int.h.
Expand Down Expand Up @@ -386,12 +402,14 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
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;
job->ready_notifier.notify = block_job_event_ready;

notifier_list_add(&job->job.on_finalize_cancelled,
&job->finalize_cancelled_notifier);
notifier_list_add(&job->job.on_finalize_completed,
&job->finalize_completed_notifier);
notifier_list_add(&job->job.on_pending, &job->pending_notifier);
notifier_list_add(&job->job.on_ready, &job->ready_notifier);

error_setg(&job->blocker, "block device is in use by block job: %s",
job_type_str(&job->job));
Expand Down Expand Up @@ -433,21 +451,6 @@ void block_job_user_resume(Job *job)
block_job_iostatus_reset(bjob);
}

void block_job_event_ready(BlockJob *job)
{
job_state_transition(&job->job, JOB_STATUS_READY);

if (block_job_is_internal(job)) {
return;
}

qapi_event_send_block_job_ready(job_type(&job->job),
job->job.id,
job->len,
job->offset,
job->speed, &error_abort);
}

BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
int is_read, int error)
{
Expand Down
3 changes: 3 additions & 0 deletions include/block/blockjob.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ typedef struct BlockJob {
/** Called when the job transitions to PENDING */
Notifier pending_notifier;

/** Called when the job transitions to READY */
Notifier ready_notifier;

/** BlockDriverStates that are involved in this block job */
GSList *nodes;
} BlockJob;
Expand Down
8 changes: 0 additions & 8 deletions include/block/blockjob_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,6 @@ void block_job_drain(Job *job);
*/
int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n);

/**
* block_job_event_ready:
* @job: The job which is now ready to be completed.
*
* Send a BLOCK_JOB_READY event for the specified job.
*/
void block_job_event_ready(BlockJob *job);

/**
* block_job_error_action:
* @job: The job to signal an error for.
Expand Down
9 changes: 6 additions & 3 deletions include/qemu/job.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ typedef struct Job {
/** Notifiers called when the job transitions to PENDING */
NotifierList on_pending;

/** Notifiers called when the job transitions to READY */
NotifierList on_ready;

/** Element of the list of jobs */
QLIST_ENTRY(Job) job_list;

Expand Down Expand Up @@ -426,6 +429,9 @@ int job_apply_verb(Job *job, JobVerb verb, Error **errp);
/** The @job could not be started, free it. */
void job_early_fail(Job *job);

/** Moves the @job from RUNNING to READY */
void job_transition_to_ready(Job *job);

/**
* @job: The job being completed.
* @ret: The status code.
Expand Down Expand Up @@ -522,7 +528,4 @@ void job_defer_to_main_loop(Job *job, JobDeferToMainLoopFn *fn, void *opaque);
*/
int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp);

/* TODO To be removed from the public interface */
void job_state_transition(Job *job, JobStatus s1);

#endif
16 changes: 13 additions & 3 deletions job.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,7 @@ static int job_txn_apply(JobTxn *txn, int fn(Job *), bool lock)
return rc;
}


/* TODO Make static once the whole state machine is in job.c */
void job_state_transition(Job *job, JobStatus s1)
static void job_state_transition(Job *job, JobStatus s1)
{
JobStatus s0 = job->status;
assert(s1 >= 0 && s1 <= JOB_STATUS__MAX);
Expand Down Expand Up @@ -321,6 +319,7 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
notifier_list_init(&job->on_finalize_cancelled);
notifier_list_init(&job->on_finalize_completed);
notifier_list_init(&job->on_pending);
notifier_list_init(&job->on_ready);

job_state_transition(job, JOB_STATUS_CREATED);
aio_timer_init(qemu_get_aio_context(), &job->sleep_timer,
Expand Down Expand Up @@ -380,6 +379,11 @@ static void job_event_pending(Job *job)
notifier_list_notify(&job->on_pending, job);
}

static void job_event_ready(Job *job)
{
notifier_list_notify(&job->on_ready, job);
}

void job_enter_cond(Job *job, bool(*fn)(Job *job))
{
if (!job_started(job)) {
Expand Down Expand Up @@ -799,6 +803,12 @@ static int job_transition_to_pending(Job *job)
return 0;
}

void job_transition_to_ready(Job *job)
{
job_state_transition(job, JOB_STATUS_READY);
job_event_ready(job);
}

static void job_completed_txn_success(Job *job)
{
JobTxn *txn = job->txn;
Expand Down
2 changes: 1 addition & 1 deletion tests/test-bdrv-drain.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ static void coroutine_fn test_job_start(void *opaque)
{
TestBlockJob *s = opaque;

block_job_event_ready(&s->common);
job_transition_to_ready(&s->common.job);
while (!s->should_complete) {
job_sleep_ns(&s->common.job, 100000);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/test-blockjob.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ static void coroutine_fn cancel_job_start(void *opaque)
}

if (!job_is_ready(&s->common.job) && s->should_converge) {
block_job_event_ready(&s->common);
job_transition_to_ready(&s->common.job);
}

job_sleep_ns(&s->common.job, 100000);
Expand Down

0 comments on commit 2e1795b

Please sign in to comment.