From nobody Fri Oct 24 09:53:11 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519430524166631.805224976412; Fri, 23 Feb 2018 16:02:04 -0800 (PST) Received: from localhost ([::1]:47926 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1epNHv-0005uw-AQ for importer@patchew.org; Fri, 23 Feb 2018 19:02:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55300) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1epN8M-0005rs-5i for qemu-devel@nongnu.org; Fri, 23 Feb 2018 18:52:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1epN8I-0005s2-BO for qemu-devel@nongnu.org; Fri, 23 Feb 2018 18:52:10 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33863 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1epN8A-0005Vf-K9; Fri, 23 Feb 2018 18:51:58 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A3518404085A; Fri, 23 Feb 2018 23:51:52 +0000 (UTC) Received: from probe.bos.redhat.com (dhcp-17-231.bos.redhat.com [10.18.17.231]) by smtp.corp.redhat.com (Postfix) with ESMTP id 726C610AF9ED; Fri, 23 Feb 2018 23:51:52 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org Date: Fri, 23 Feb 2018 18:51:26 -0500 Message-Id: <20180223235142.21501-6-jsnow@redhat.com> In-Reply-To: <20180223235142.21501-1-jsnow@redhat.com> References: <20180223235142.21501-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 23 Feb 2018 23:51:52 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 23 Feb 2018 23:51:52 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'jsnow@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [RFC v4 05/21] blockjobs: add state transition table X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, John Snow , pkrempa@redhat.com, jtc@redhat.com, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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. 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. Signed-off-by: John Snow --- block/trace-events | 3 +++ blockjob.c | 42 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/block/trace-events b/block/trace-events index 02dd80ff0c..b75a0c8409 100644 --- a/block/trace-events +++ b/block/trace-events @@ -4,6 +4,9 @@ bdrv_open_common(void *bs, const char *filename, int flags, const char *fo= rmat_name) "bs %p filename \"%s\" flags 0x%x format_name \"%s\"" bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d" =20 +# blockjob.c +block_job_state_transition(void *job, int ret, const char *legal, const c= har *s0, const char *s1) "job %p (ret: %d) attempting %s transition (%s-->%= s)" + # block/block-backend.c blk_co_preadv(void *blk, void *bs, int64_t offset, unsigned int bytes, int= flags) "blk %p bs %p offset %"PRId64" bytes %u flags 0x%x" blk_co_pwritev(void *blk, void *bs, int64_t offset, unsigned int bytes, in= t flags) "blk %p bs %p offset %"PRId64" bytes %u flags 0x%x" diff --git a/blockjob.c b/blockjob.c index 1be9c20cff..d745b3bb69 100644 --- a/blockjob.c +++ b/blockjob.c @@ -28,6 +28,7 @@ #include "block/block.h" #include "block/blockjob_int.h" #include "block/block_int.h" +#include "block/trace.h" #include "sysemu/block-backend.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" @@ -41,6 +42,34 @@ * block_job_enter. */ static QemuMutex block_job_mutex; =20 +/* BlockJob State Transition Table */ +bool BlockJobSTT[BLOCK_JOB_STATUS__MAX][BLOCK_JOB_STATUS__MAX] =3D { + /* U, C, R, P, Y, S */ + /* U: */ [BLOCK_JOB_STATUS_UNDEFINED] =3D {0, 1, 0, 0, 0, 0}, + /* C: */ [BLOCK_JOB_STATUS_CREATED] =3D {0, 0, 1, 0, 0, 0}, + /* R: */ [BLOCK_JOB_STATUS_RUNNING] =3D {0, 0, 0, 1, 1, 0}, + /* P: */ [BLOCK_JOB_STATUS_PAUSED] =3D {0, 0, 1, 0, 0, 0}, + /* Y: */ [BLOCK_JOB_STATUS_READY] =3D {0, 0, 0, 0, 0, 1}, + /* S: */ [BLOCK_JOB_STATUS_STANDBY] =3D {0, 0, 0, 0, 1, 0}, +}; + +static void block_job_state_transition(BlockJob *job, BlockJobStatus s1) +{ + BlockJobStatus s0 =3D job->status; + if (s0 =3D=3D s1) { + return; + } + assert(s1 >=3D 0 && s1 <=3D BLOCK_JOB_STATUS__MAX); + trace_block_job_state_transition(job, job->ret, BlockJobSTT[s0][s1] ? + "allowed" : "disallowed", + qapi_enum_lookup(&BlockJobStatus_look= up, + s0), + qapi_enum_lookup(&BlockJobStatus_look= up, + s1)); + assert(BlockJobSTT[s0][s1]); + job->status =3D s1; +} + static void block_job_lock(void) { qemu_mutex_lock(&block_job_mutex); @@ -320,7 +349,7 @@ void block_job_start(BlockJob *job) job->pause_count--; job->busy =3D true; job->paused =3D false; - job->status =3D BLOCK_JOB_STATUS_RUNNING; + block_job_state_transition(job, BLOCK_JOB_STATUS_RUNNING); bdrv_coroutine_enter(blk_bs(job->blk), job->co); } =20 @@ -704,6 +733,7 @@ void *block_job_create(const char *job_id, const BlockJ= obDriver *driver, job->refcnt =3D 1; job->manual =3D (flags & BLOCK_JOB_MANUAL); job->status =3D BLOCK_JOB_STATUS_CREATED; + block_job_state_transition(job, BLOCK_JOB_STATUS_CREATED); aio_timer_init(qemu_get_aio_context(), &job->sleep_timer, QEMU_CLOCK_REALTIME, SCALE_NS, block_job_sleep_timer_cb, job); @@ -818,13 +848,13 @@ void coroutine_fn block_job_pause_point(BlockJob *job) =20 if (block_job_should_pause(job) && !block_job_is_cancelled(job)) { BlockJobStatus status =3D job->status; - job->status =3D status =3D=3D BLOCK_JOB_STATUS_READY ? \ - BLOCK_JOB_STATUS_STANDBY : \ - BLOCK_JOB_STATUS_PAUSED; + block_job_state_transition(job, status =3D=3D BLOCK_JOB_STATUS_REA= DY ? \ + BLOCK_JOB_STATUS_STANDBY : \ + BLOCK_JOB_STATUS_PAUSED); job->paused =3D true; block_job_do_yield(job, -1); job->paused =3D false; - job->status =3D status; + block_job_state_transition(job, status); } =20 if (job->driver->resume) { @@ -930,7 +960,7 @@ void block_job_iostatus_reset(BlockJob *job) =20 void block_job_event_ready(BlockJob *job) { - job->status =3D BLOCK_JOB_STATUS_READY; + block_job_state_transition(job, BLOCK_JOB_STATUS_READY); job->ready =3D true; =20 if (block_job_is_internal(job)) { --=20 2.14.3