Message ID | 20180223235142.21501-10-jsnow@redhat.com |
---|---|
State | New |
Headers | show |
Series | blockjobs: add explicit job management | expand |
On 02/23/2018 05:51 PM, John Snow wrote: > add a new state "CONCLUDED" that identifies a job that has ceased all > operations. The wording was chosen to avoid any phrasing that might > imply success, error, or cancellation. The task has simply ceased all > operation and can never again perform any work. > > ("finished", "done", and "completed" might all imply success.) > > Transitions: > Running -> Concluded: normal completion > Ready -> Concluded: normal completion > Aborting -> Concluded: error and cancellations > > Verbs: > None as of this commit. (a future commit adds 'dismiss') > > @@ -620,7 +623,9 @@ void block_job_user_resume(BlockJob *job, Error **errp) > > void block_job_cancel(BlockJob *job) > { > - if (block_job_started(job)) { > + if (job->status == BLOCK_JOB_STATUS_CONCLUDED) { > + return; > + } else if (block_job_started(job)) { It's also possible to do: if () { return ; } if (...) instead of chaining with an 'else if'. Matter of personal taste, so I won't make you change it. Reviewed-by: Eric Blake <eblake@redhat.com>
On 02/27/2018 02:38 PM, Eric Blake wrote: > On 02/23/2018 05:51 PM, John Snow wrote: >> add a new state "CONCLUDED" that identifies a job that has ceased all >> operations. The wording was chosen to avoid any phrasing that might >> imply success, error, or cancellation. The task has simply ceased all >> operation and can never again perform any work. >> >> ("finished", "done", and "completed" might all imply success.) >> >> Transitions: >> Running -> Concluded: normal completion >> Ready -> Concluded: normal completion >> Aborting -> Concluded: error and cancellations >> >> Verbs: >> None as of this commit. (a future commit adds 'dismiss') >> > > >> @@ -620,7 +623,9 @@ void block_job_user_resume(BlockJob *job, Error >> **errp) >> void block_job_cancel(BlockJob *job) >> { >> - if (block_job_started(job)) { >> + if (job->status == BLOCK_JOB_STATUS_CONCLUDED) { >> + return; >> + } else if (block_job_started(job)) { > > It's also possible to do: > > if () { > return ; > } > if (...) > > instead of chaining with an 'else if'. Matter of personal taste, so I > won't make you change it. > > Reviewed-by: Eric Blake <eblake@redhat.com> > I guess because in this case, what I did adds two SLOC instead of three. If the other code did not need to be guarded by an if(), I'd otherwise agree.
Am 24.02.2018 um 00:51 hat John Snow geschrieben: > add a new state "CONCLUDED" that identifies a job that has ceased all > operations. The wording was chosen to avoid any phrasing that might > imply success, error, or cancellation. The task has simply ceased all > operation and can never again perform any work. > > ("finished", "done", and "completed" might all imply success.) > > Transitions: > Running -> Concluded: normal completion > Ready -> Concluded: normal completion > Aborting -> Concluded: error and cancellations > > Verbs: > None as of this commit. (a future commit adds 'dismiss') > > +---------+ > |UNDEFINED| > +--+------+ > | > +--v----+ > |CREATED| > +--+----+ > | > +--v----+ +------+ > +---------+RUNNING<----->PAUSED| > | +--+-+--+ +------+ > | | | > | | +------------------+ > | | | > | +--v--+ +-------+ | > +---------+READY<------->STANDBY| | > | +--+--+ +-------+ | > | | | > +--v-----+ +--v------+ | > |ABORTING+--->CONCLUDED<-------------+ > +--------+ +---------+ > > Signed-off-by: John Snow <jsnow@redhat.com> > +static void block_job_event_concluded(BlockJob *job) > +{ > + if (block_job_is_internal(job) || !job->manual) { > + return; > + } > + block_job_state_transition(job, BLOCK_JOB_STATUS_CONCLUDED); > +} I don't understand why internal or automatic jobs should follow a different state machine. Sure, they won't be in this state for long because the job is immediately unref'ed. Though if someone holds an additional reference, it might be visible - I would consider this a bug fix because otherwise the job stays in READY and continues to accept the verbs for that state. Kevin
On 02/28/2018 10:37 AM, Kevin Wolf wrote: > Am 24.02.2018 um 00:51 hat John Snow geschrieben: >> add a new state "CONCLUDED" that identifies a job that has ceased all >> operations. The wording was chosen to avoid any phrasing that might >> imply success, error, or cancellation. The task has simply ceased all >> operation and can never again perform any work. >> >> ("finished", "done", and "completed" might all imply success.) >> >> Transitions: >> Running -> Concluded: normal completion >> Ready -> Concluded: normal completion >> Aborting -> Concluded: error and cancellations >> >> Verbs: >> None as of this commit. (a future commit adds 'dismiss') >> >> +---------+ >> |UNDEFINED| >> +--+------+ >> | >> +--v----+ >> |CREATED| >> +--+----+ >> | >> +--v----+ +------+ >> +---------+RUNNING<----->PAUSED| >> | +--+-+--+ +------+ >> | | | >> | | +------------------+ >> | | | >> | +--v--+ +-------+ | >> +---------+READY<------->STANDBY| | >> | +--+--+ +-------+ | >> | | | >> +--v-----+ +--v------+ | >> |ABORTING+--->CONCLUDED<-------------+ >> +--------+ +---------+ >> >> Signed-off-by: John Snow <jsnow@redhat.com> > >> +static void block_job_event_concluded(BlockJob *job) >> +{ >> + if (block_job_is_internal(job) || !job->manual) { >> + return; >> + } >> + block_job_state_transition(job, BLOCK_JOB_STATUS_CONCLUDED); >> +} > > I don't understand why internal or automatic jobs should follow a > different state machine. Sure, they won't be in this state for long The very simple answer is because I overlooked this change from when I did implement separate graphs for the old and new models. > because the job is immediately unref'ed. Though if someone holds an > additional reference, it might be visible - I would consider this a bug > fix because otherwise the job stays in READY and continues to accept the > verbs for that state. > > Kevin >
diff --git a/blockjob.c b/blockjob.c index 4c3fcda46c..93b0a36306 100644 --- a/blockjob.c +++ b/blockjob.c @@ -44,23 +44,24 @@ static QemuMutex block_job_mutex; /* BlockJob State Transition Table */ bool BlockJobSTT[BLOCK_JOB_STATUS__MAX][BLOCK_JOB_STATUS__MAX] = { - /* U, C, R, P, Y, S, X */ - /* U: */ [BLOCK_JOB_STATUS_UNDEFINED] = {0, 1, 0, 0, 0, 0, 0}, - /* C: */ [BLOCK_JOB_STATUS_CREATED] = {0, 0, 1, 0, 0, 0, 0}, - /* R: */ [BLOCK_JOB_STATUS_RUNNING] = {0, 0, 0, 1, 1, 0, 1}, - /* P: */ [BLOCK_JOB_STATUS_PAUSED] = {0, 0, 1, 0, 0, 0, 0}, - /* Y: */ [BLOCK_JOB_STATUS_READY] = {0, 0, 0, 0, 0, 1, 1}, - /* S: */ [BLOCK_JOB_STATUS_STANDBY] = {0, 0, 0, 0, 1, 0, 0}, - /* X: */ [BLOCK_JOB_STATUS_ABORTING] = {0, 0, 0, 0, 0, 0, 0}, + /* U, C, R, P, Y, S, X, E */ + /* U: */ [BLOCK_JOB_STATUS_UNDEFINED] = {0, 1, 0, 0, 0, 0, 0, 0}, + /* C: */ [BLOCK_JOB_STATUS_CREATED] = {0, 0, 1, 0, 0, 0, 0, 0}, + /* R: */ [BLOCK_JOB_STATUS_RUNNING] = {0, 0, 0, 1, 1, 0, 1, 1}, + /* P: */ [BLOCK_JOB_STATUS_PAUSED] = {0, 0, 1, 0, 0, 0, 0, 0}, + /* Y: */ [BLOCK_JOB_STATUS_READY] = {0, 0, 0, 0, 0, 1, 1, 1}, + /* S: */ [BLOCK_JOB_STATUS_STANDBY] = {0, 0, 0, 0, 1, 0, 0, 0}, + /* X: */ [BLOCK_JOB_STATUS_ABORTING] = {0, 0, 0, 0, 0, 0, 0, 1}, + /* E: */ [BLOCK_JOB_STATUS_CONCLUDED] = {0, 0, 0, 0, 0, 0, 0, 0}, }; bool BlockJobVerbTable[BLOCK_JOB_VERB__MAX][BLOCK_JOB_STATUS__MAX] = { - /* U, C, R, P, Y, S, X */ - [BLOCK_JOB_VERB_CANCEL] = {0, 1, 1, 1, 1, 1, 0}, - [BLOCK_JOB_VERB_PAUSE] = {0, 1, 1, 1, 1, 1, 0}, - [BLOCK_JOB_VERB_RESUME] = {0, 1, 1, 1, 1, 1, 0}, - [BLOCK_JOB_VERB_SET_SPEED] = {0, 1, 1, 1, 1, 1, 0}, - [BLOCK_JOB_VERB_COMPLETE] = {0, 0, 0, 0, 1, 0, 0}, + /* U, C, R, P, Y, S, X, E */ + [BLOCK_JOB_VERB_CANCEL] = {0, 1, 1, 1, 1, 1, 0, 0}, + [BLOCK_JOB_VERB_PAUSE] = {0, 1, 1, 1, 1, 1, 0, 0}, + [BLOCK_JOB_VERB_RESUME] = {0, 1, 1, 1, 1, 1, 0, 0}, + [BLOCK_JOB_VERB_SET_SPEED] = {0, 1, 1, 1, 1, 1, 0, 0}, + [BLOCK_JOB_VERB_COMPLETE] = {0, 0, 0, 0, 1, 0, 0, 0}, }; static void block_job_state_transition(BlockJob *job, BlockJobStatus s1) @@ -114,6 +115,7 @@ static void __attribute__((__constructor__)) block_job_init(void) static void block_job_event_cancelled(BlockJob *job); static void block_job_event_completed(BlockJob *job, const char *msg); +static void block_job_event_concluded(BlockJob *job); static void block_job_enter_cond(BlockJob *job, bool(*fn)(BlockJob *job)); /* Transactional group of block jobs */ @@ -420,6 +422,7 @@ static void block_job_completed_single(BlockJob *job) QLIST_REMOVE(job, txn_list); block_job_txn_unref(job->txn); + block_job_event_concluded(job); block_job_unref(job); } @@ -620,7 +623,9 @@ void block_job_user_resume(BlockJob *job, Error **errp) void block_job_cancel(BlockJob *job) { - if (block_job_started(job)) { + if (job->status == BLOCK_JOB_STATUS_CONCLUDED) { + return; + } else if (block_job_started(job)) { block_job_cancel_async(job); block_job_enter(job); } else { @@ -727,6 +732,14 @@ static void block_job_event_completed(BlockJob *job, const char *msg) &error_abort); } +static void block_job_event_concluded(BlockJob *job) +{ + if (block_job_is_internal(job) || !job->manual) { + return; + } + block_job_state_transition(job, BLOCK_JOB_STATUS_CONCLUDED); +} + /* * API for block job drivers and the block layer. These functions are * declared in blockjob_int.h. diff --git a/qapi/block-core.json b/qapi/block-core.json index 3f7d559fc0..aeb9b1937b 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1000,11 +1000,14 @@ # an error. The job will afterwards report that it is @concluded. # This status may not be visible to the management process. # +# @concluded: The job has finished all work. If manual was set to true, the job +# will remain in the query list until it is dismissed. +# # Since: 2.12 ## { 'enum': 'BlockJobStatus', 'data': ['undefined', 'created', 'running', 'paused', 'ready', 'standby', - 'aborting' ] } + 'aborting', 'concluded' ] } ## # @BlockJobInfo:
add a new state "CONCLUDED" that identifies a job that has ceased all operations. The wording was chosen to avoid any phrasing that might imply success, error, or cancellation. The task has simply ceased all operation and can never again perform any work. ("finished", "done", and "completed" might all imply success.) Transitions: Running -> Concluded: normal completion Ready -> Concluded: normal completion Aborting -> Concluded: error and cancellations Verbs: None as of this commit. (a future commit adds 'dismiss') +---------+ |UNDEFINED| +--+------+ | +--v----+ |CREATED| +--+----+ | +--v----+ +------+ +---------+RUNNING<----->PAUSED| | +--+-+--+ +------+ | | | | | +------------------+ | | | | +--v--+ +-------+ | +---------+READY<------->STANDBY| | | +--+--+ +-------+ | | | | +--v-----+ +--v------+ | |ABORTING+--->CONCLUDED<-------------+ +--------+ +---------+ Signed-off-by: John Snow <jsnow@redhat.com> --- blockjob.c | 43 ++++++++++++++++++++++++++++--------------- qapi/block-core.json | 5 ++++- 2 files changed, 32 insertions(+), 16 deletions(-)