From nobody Tue Feb 10 05:10:37 2026 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1517019434714967.938920704753; Fri, 26 Jan 2018 18:17:14 -0800 (PST) Received: from localhost ([::1]:43850 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1efG3L-0004Uw-PW for importer@patchew.org; Fri, 26 Jan 2018 21:17:11 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37415) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1efFsA-00019t-DU for qemu-devel@nongnu.org; Fri, 26 Jan 2018 21:05:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1efFs9-0008U8-0z for qemu-devel@nongnu.org; Fri, 26 Jan 2018 21:05:38 -0500 Received: from mx1.redhat.com ([209.132.183.28]:35282) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1efFs4-0008Op-3A; Fri, 26 Jan 2018 21:05:32 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5F1798EB0F; Sat, 27 Jan 2018 02:05:31 +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 8268A5457C; Sat, 27 Jan 2018 02:05:30 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org Date: Fri, 26 Jan 2018 21:05:11 -0500 Message-Id: <20180127020515.27137-11-jsnow@redhat.com> In-Reply-To: <20180127020515.27137-1-jsnow@redhat.com> References: <20180127020515.27137-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Sat, 27 Jan 2018 02:05:31 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC v3 10/14] blockjobs: Add waiting event 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" For jobs that are stuck waiting on others in a transaction, it would be nice to know that they are no longer "running" in that sense, but instead are waiting on other jobs in the transaction. Jobs that are "waiting" in this sense cannot be meaningfully altered any longer as they have left their running loop. The only meaningful user verb for jobs in this state is "cancel," which will cancel the whole transaction, too. Valid transitions: Running -> Waiting (transactional, non-mirror jobs upon completion) Ready -> Waiting (hypothetically: transactional mirror jobs upon block-job-complete) Waiting -> Concluded (transactional jobs of any kind upon convergence) Valid verbs: Cancel: A waiting job may still be canceled. Signed-off-by: John Snow --- blockjob.c | 45 +++++++++++++++++++++++++++++++-------------- qapi/block-core.json | 25 ++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/blockjob.c b/blockjob.c index e52b4c4ce0..6a3a630517 100644 --- a/blockjob.c +++ b/blockjob.c @@ -44,13 +44,14 @@ 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, E */ - /* 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, 1}, - /* P: */ [BLOCK_JOB_STATUS_PAUSED] =3D {0, 0, 1, 0, 1, 1}, - /* Y: */ [BLOCK_JOB_STATUS_READY] =3D {0, 0, 0, 1, 0, 1}, - /* E: */ [BLOCK_JOB_STATUS_CONCLUDED] =3D {1, 0, 0, 0, 0, 0}, + /* U, C, R, P, Y, W, E */ + /* U: */ [BLOCK_JOB_STATUS_UNDEFINED] =3D {0, 1, 0, 0, 0, 0, 0}, + /* C: */ [BLOCK_JOB_STATUS_CREATED] =3D {0, 0, 1, 0, 0, 0, 0}, + /* R: */ [BLOCK_JOB_STATUS_RUNNING] =3D {0, 0, 0, 1, 1, 1, 1}, + /* P: */ [BLOCK_JOB_STATUS_PAUSED] =3D {0, 0, 1, 0, 1, 0, 1}, + /* Y: */ [BLOCK_JOB_STATUS_READY] =3D {0, 0, 0, 1, 0, 1, 1}, + /* W: */ [BLOCK_JOB_STATUS_WAITING] =3D {0, 0, 0, 0, 0, 0, 1}, + /* E: */ [BLOCK_JOB_STATUS_CONCLUDED] =3D {1, 0, 0, 0, 0, 0, 0}, }; =20 enum BlockJobVerb { @@ -64,13 +65,13 @@ enum BlockJobVerb { }; =20 bool BlockJobVerb[BLOCK_JOB_VERB__MAX][BLOCK_JOB_STATUS__MAX] =3D { - /* U, C, R, P, Y, E */ - [BLOCK_JOB_VERB_CANCEL] =3D {0, 1, 1, 1, 1, 0}, - [BLOCK_JOB_VERB_PAUSE] =3D {0, 1, 1, 1, 1, 0}, - [BLOCK_JOB_VERB_RESUME] =3D {0, 0, 0, 1, 0, 0}, - [BLOCK_JOB_VERB_SET_SPEED] =3D {0, 1, 1, 1, 1, 0}, - [BLOCK_JOB_VERB_COMPLETE] =3D {0, 0, 0, 0, 1, 0}, - [BLOCK_JOB_VERB_DISMISS] =3D {0, 0, 0, 0, 0, 1}, + /* U, C, R, P, Y, W, E */ + [BLOCK_JOB_VERB_CANCEL] =3D {0, 1, 1, 1, 1, 1, 0}, + [BLOCK_JOB_VERB_PAUSE] =3D {0, 1, 1, 1, 1, 0, 0}, + [BLOCK_JOB_VERB_RESUME] =3D {0, 0, 0, 1, 0, 0, 0}, + [BLOCK_JOB_VERB_SET_SPEED] =3D {0, 1, 1, 1, 1, 0, 0}, + [BLOCK_JOB_VERB_COMPLETE] =3D {0, 0, 0, 0, 1, 0, 0}, + [BLOCK_JOB_VERB_DISMISS] =3D {0, 0, 0, 0, 0, 0, 1}, }; =20 static void block_job_state_transition(BlockJob *job, BlockJobStatus s1) @@ -789,6 +790,21 @@ static void block_job_event_completed(BlockJob *job, c= onst char *msg) &error_abort); } =20 +static void block_job_event_waiting(BlockJob *job) +{ + if (!job->manual) { + return; + } + block_job_state_transition(job, BLOCK_JOB_STATUS_WAITING); + if (block_job_is_internal(job)) { + return; + } + + qapi_event_send_block_job_waiting(job->driver->job_type, + job->id, + &error_abort); +} + static void block_job_event_concluded(BlockJob *job) { if (block_job_is_internal(job) || !job->manual) { @@ -925,6 +941,7 @@ void block_job_completed(BlockJob *job, int ret) } else if (ret < 0 || block_job_is_cancelled(job)) { block_job_completed_txn_abort(job); } else { + block_job_event_waiting(job); block_job_completed_txn_success(job); } } diff --git a/qapi/block-core.json b/qapi/block-core.json index f27c7054d2..f26fd1d8fd 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -966,7 +966,7 @@ ## { 'enum': 'BlockJobStatus', 'data': ['undefined', 'created', 'running', 'paused', 'ready', - 'concluded' ] } + 'waiting', 'concluded' ] } =20 ## # @BlockJobInfo: @@ -3867,6 +3867,29 @@ 'offset': 'int', 'speed' : 'int' } } =20 +## +# @BLOCK_JOB_WAITING: +# +# Emitted when a block job that is part of a transction has stopped work a= nd is +# waiting for other jobs in the transaction to reach the same state. +# +# @type: job type +# +# @id: The job identifier. +# +# Since: 2.12 +# +# Example: +# +# <- { "event": "BLOCK_JOB_WAITING", +# "data": { "id": "drive0", "type": "mirror" }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'BLOCK_JOB_WAITING', + 'data': { 'type' : 'BlockJobType', + 'id' : 'str' } } + ## # @PreallocMode: # --=20 2.14.3