From nobody Tue Nov 4 18:30:35 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=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1531154377060608.2241192721638; Mon, 9 Jul 2018 09:39:37 -0700 (PDT) Received: from localhost ([::1]:43315 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fcZCI-0003mF-HM for importer@patchew.org; Mon, 09 Jul 2018 12:39:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57831) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fcZAG-0002bi-7P for qemu-devel@nongnu.org; Mon, 09 Jul 2018 12:37:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fcZAB-0002cy-Aq for qemu-devel@nongnu.org; Mon, 09 Jul 2018 12:37:28 -0400 Received: from relay.sw.ru ([185.231.240.75]:32926) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fcZAB-0002az-1z; Mon, 09 Jul 2018 12:37:23 -0400 Received: from vz-out.virtuozzo.com ([185.231.240.5] helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.90_1) (envelope-from ) id 1fcZA8-00062Y-6C; Mon, 09 Jul 2018 19:37:20 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 9 Jul 2018 19:37:18 +0300 Message-Id: <20180709163719.87107-4-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20180709163719.87107-1-vsementsov@virtuozzo.com> References: <20180709163719.87107-1-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH v5 3/4] block: add BDRV_REQ_SERIALISING flag 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, vsementsov@virtuozzo.com, famz@redhat.com, ronniesahlberg@gmail.com, jcody@redhat.com, pl@kamp.de, mreitz@redhat.com, stefanha@redhat.com, den@openvz.org, pbonzini@redhat.com, jsnow@redhat.com 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" Serialized writes should be used in copy-on-write of backup(sync=3Dnone) for image fleecing scheme. We need to change an assert in bdrv_aligned_pwritev, added in 28de2dcd88de. The assert may fail now, because call to wait_serialising_requests here may become first call to it for this request with serializing flag set. It occurs if the request is aligned (otherwise, we should already set serializing flag before calling bdrv_aligned_pwritev and correspondingly waited for all intersecting requests). However, for aligned requests, we should not care about outdating of previously read data, as there no such data. Therefore, let's just update an assert to not care about aligned requests. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Fam Zheng --- include/block/block.h | 13 ++++++++++++- block/io.c | 26 +++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/include/block/block.h b/include/block/block.h index 57a96d4988..6623d15432 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -69,8 +69,19 @@ typedef enum { * content. */ BDRV_REQ_WRITE_UNCHANGED =3D 0x40, =20 + /* BDRV_REQ_SERIALISING forces request serialisation for writes. + * It is used to ensure that writes to the backing file of a backup pr= ocess + * target cannot race with a read of the backup target that defers to = the + * backing file. + * + * Note, that BDRV_REQ_SERIALISING is _not_ opposite in meaning to + * BDRV_REQ_NO_SERIALISING. A more descriptive name for the latter mig= ht be + * _DO_NOT_WAIT_FOR_SERIALISING, except that is too long. + */ + BDRV_REQ_SERIALISING =3D 0x80, + /* Mask of valid flags */ - BDRV_REQ_MASK =3D 0x7f, + BDRV_REQ_MASK =3D 0xff, } BdrvRequestFlags; =20 typedef struct BlockSizes { diff --git a/block/io.c b/block/io.c index 5d5651ad84..102cb0e1ba 100644 --- a/block/io.c +++ b/block/io.c @@ -623,6 +623,16 @@ static void mark_request_serialising(BdrvTrackedReques= t *req, uint64_t align) req->overlap_bytes =3D MAX(req->overlap_bytes, overlap_bytes); } =20 +static bool is_request_serialising_and_aligned(BdrvTrackedRequest *req) +{ + /* if request is serialising, overlap_offset and overlap_bytes are set= , so + * we can check is request aligned. Otherwise don't care and return fa= lse + */ + + return req->serialising && (req->offset =3D=3D req->overlap_offset) && + (req->bytes =3D=3D req->overlap_bytes); +} + /** * Round a region to cluster boundaries */ @@ -1291,6 +1301,9 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild= *child, mark_request_serialising(req, bdrv_get_cluster_size(bs)); } =20 + /* BDRV_REQ_SERIALISING is only for write operation */ + assert(!(flags & BDRV_REQ_SERIALISING)); + if (!(flags & BDRV_REQ_NO_SERIALISING)) { wait_serialising_requests(req); } @@ -1574,8 +1587,14 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChi= ld *child, =20 /* BDRV_REQ_NO_SERIALISING is only for read operation */ assert(!(flags & BDRV_REQ_NO_SERIALISING)); + + if (flags & BDRV_REQ_SERIALISING) { + mark_request_serialising(req, bdrv_get_cluster_size(bs)); + } + waited =3D wait_serialising_requests(req); - assert(!waited || !req->serialising); + assert(!waited || !req->serialising || + is_request_serialising_and_aligned(req)); assert(req->overlap_offset <=3D offset); assert(offset + bytes <=3D req->overlap_offset + req->overlap_bytes); if (flags & BDRV_REQ_WRITE_UNCHANGED) { @@ -2929,6 +2948,8 @@ static int coroutine_fn bdrv_co_copy_range_internal( tracked_request_begin(&req, src->bs, src_offset, bytes, BDRV_TRACKED_READ); =20 + /* BDRV_REQ_SERIALISING is only for write operation */ + assert(!(read_flags & BDRV_REQ_SERIALISING)); if (!(read_flags & BDRV_REQ_NO_SERIALISING)) { wait_serialising_requests(&req); } @@ -2948,6 +2969,9 @@ static int coroutine_fn bdrv_co_copy_range_internal( =20 /* BDRV_REQ_NO_SERIALISING is only for read operation */ assert(!(write_flags & BDRV_REQ_NO_SERIALISING)); + if (write_flags & BDRV_REQ_SERIALISING) { + mark_request_serialising(&req, bdrv_get_cluster_size(dst->bs)); + } wait_serialising_requests(&req); =20 ret =3D dst->bs->drv->bdrv_co_copy_range_to(dst->bs, --=20 2.11.1