From nobody Fri Oct 24 09:53:12 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 1519430093575449.8930519513317; Fri, 23 Feb 2018 15:54:53 -0800 (PST) Received: from localhost ([::1]:47859 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1epNAp-0007pD-EA for importer@patchew.org; Fri, 23 Feb 2018 18:54:43 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55275) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1epN8L-0005qO-A6 for qemu-devel@nongnu.org; Fri, 23 Feb 2018 18:52:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1epN8I-0005rj-8w for qemu-devel@nongnu.org; Fri, 23 Feb 2018 18:52:09 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33868 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 1epN8B-0005ZL-2K; Fri, 23 Feb 2018 18:51:59 -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 430E340744D1; Fri, 23 Feb 2018 23:51:54 +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 119CE104947B; Fri, 23 Feb 2018 23:51:54 +0000 (UTC) From: John Snow To: qemu-block@nongnu.org Date: Fri, 23 Feb 2018 18:51:33 -0500 Message-Id: <20180223235142.21501-13-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:54 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 23 Feb 2018 23:51:54 +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 12/21] blockjobs: ensure abort is called for cancelled jobs 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" Presently, even if a job is canceled post-completion as a result of a failing peer in a transaction, it will still call .commit because nothing has updated or changed its return code. The reason why this does not cause problems currently is because backup's implementation of .commit checks for cancellation itself. I'd like to simplify this contract: (1) Abort is called if the job/transaction fails (2) Commit is called if the job/transaction succeeds To this end: A job's return code, if 0, will be forcibly set as -ECANCELED if that job has already concluded. Remove the now redundant check in the backup job implementation. We need to check for cancellation in both block_job_completed AND block_job_completed_single, because jobs may be cancelled between those two calls; for instance in transactions. The check in block_job_completed could be removed, but there's no point in starting to attempt to succeed a transaction that we know in advance will fail. This does NOT affect mirror jobs that are "canceled" during their synchronous phase. The mirror job itself forcibly sets the canceled property to false prior to ceding control, so such cases will invoke the "commit" callback. Signed-off-by: John Snow Reviewed-by: Eric Blake Reviewed-by: Kevin Wolf --- block/backup.c | 2 +- block/trace-events | 1 + blockjob.c | 19 +++++++++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/block/backup.c b/block/backup.c index 7e254dabff..453cd62c24 100644 --- a/block/backup.c +++ b/block/backup.c @@ -206,7 +206,7 @@ static void backup_cleanup_sync_bitmap(BackupBlockJob *= job, int ret) BdrvDirtyBitmap *bm; BlockDriverState *bs =3D blk_bs(job->common.blk); =20 - if (ret < 0 || block_job_is_cancelled(&job->common)) { + if (ret < 0) { /* Merge the successor back into the parent, delete nothing. */ bm =3D bdrv_reclaim_dirty_bitmap(bs, job->sync_bitmap, NULL); assert(bm); diff --git a/block/trace-events b/block/trace-events index 266afd9e99..5e531e0310 100644 --- a/block/trace-events +++ b/block/trace-events @@ -5,6 +5,7 @@ bdrv_open_common(void *bs, const char *filename, int flags,= const char *format_n bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d" =20 # blockjob.c +block_job_completed(void *job, int ret, int jret) "job %p ret %d corrected= ret %d" 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_job_apply_verb(void *job, const char *state, const char *verb, const= char *legal) "job %p in state %s; applying verb %s (%s)" =20 diff --git a/blockjob.c b/blockjob.c index 4d29391673..ef17dea004 100644 --- a/blockjob.c +++ b/blockjob.c @@ -384,13 +384,22 @@ void block_job_start(BlockJob *job) bdrv_coroutine_enter(blk_bs(job->blk), job->co); } =20 +static void block_job_update_rc(BlockJob *job) +{ + if (!job->ret && block_job_is_cancelled(job)) { + job->ret =3D -ECANCELED; + } + if (job->ret) { + block_job_state_transition(job, BLOCK_JOB_STATUS_ABORTING); + } +} + static void block_job_completed_single(BlockJob *job) { assert(job->completed); =20 - if (job->ret || block_job_is_cancelled(job)) { - block_job_state_transition(job, BLOCK_JOB_STATUS_ABORTING); - } + /* Ensure abort is called for late-transactional failures */ + block_job_update_rc(job); =20 if (!job->ret) { if (job->driver->commit) { @@ -898,7 +907,9 @@ void block_job_completed(BlockJob *job, int ret) assert(blk_bs(job->blk)->job =3D=3D job); job->completed =3D true; job->ret =3D ret; - if (ret < 0 || block_job_is_cancelled(job)) { + block_job_update_rc(job); + trace_block_job_completed(job, ret, job->ret); + if (job->ret) { block_job_completed_txn_abort(job); } else { block_job_completed_txn_success(job); --=20 2.14.3