On 02/23/2018 05:51 PM, John Snow wrote:
The state transition table has mostly been implied. We're about to make
it a bit more complex, so let's make the STM explicit instead.

Perform state transitions with a function that for now just asserts the
transition is appropriate.

Transitions:
Undefined -> Created: During job initialization.

Unless we use Created as the default state 0 for g_new0().

Created   -> Running: Once the job is started.
                       Jobs cannot transition from "Created" to "Paused"
                       directly, but will instead synchronously transition
                       to running to paused immediately.
Running   -> Paused:  Normal workflow for pauses.
Running   -> Ready:   Normal workflow for jobs reaching their sync point.
                       (e.g. mirror)
Ready     -> Standby: Normal workflow for pausing ready jobs.
Paused    -> Running: Normal resume.
Standby   -> Ready:   Resume of a Standby job.


+---------+
|UNDEFINED|
+--+------+
    |
+--v----+
|CREATED|
+--+----+
    |
+--v----+     +------+
|RUNNING<----->PAUSED|
+--+----+     +------+
    |
+--v--+       +-------+
|READY<------->STANDBY|
+-----+       +-------+


Notably, there is no state presently defined as of this commit that
deals with a job after the "running" or "ready" states, so this table
will be adjusted alongside the commits that introduce those states.

The ascii-art tables help in this and other patches. Thanks for producing them.


Signed-off-by: John Snow <js...@redhat.com>
---
  block/trace-events |  3 +++
  blockjob.c         | 42 ++++++++++++++++++++++++++++++++++++------
  2 files changed, 39 insertions(+), 6 deletions(-)


+static void block_job_state_transition(BlockJob *job, BlockJobStatus s1)
+{
+    BlockJobStatus s0 = job->status;
+    if (s0 == s1) {
+        return;
+    }
+    assert(s1 >= 0 && s1 <= BLOCK_JOB_STATUS__MAX);

Or, if you keep the zero state distinct from valid states, this could be 'assert(s1 > 0 && ...)'

@@ -320,7 +349,7 @@ void block_job_start(BlockJob *job)
      job->pause_count--;
      job->busy = true;
      job->paused = false;
-    job->status = BLOCK_JOB_STATUS_RUNNING;
+    block_job_state_transition(job, BLOCK_JOB_STATUS_RUNNING);
      bdrv_coroutine_enter(blk_bs(job->blk), job->co);
  }
@@ -704,6 +733,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
      job->refcnt        = 1;
      job->manual        = (flags & BLOCK_JOB_MANUAL);
      job->status        = BLOCK_JOB_STATUS_CREATED;
+    block_job_state_transition(job, BLOCK_JOB_STATUS_CREATED);

Oops, missing a deletion of the job->status assignment line.

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org

Reply via email to