From nobody Sun May 5 14:19:35 2024 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.zoho.com; dkim=fail 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 1497620383239608.6376522383127; Fri, 16 Jun 2017 06:39:43 -0700 (PDT) Received: from localhost ([::1]:58943 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrTR-0006Ga-Ib for importer@patchew.org; Fri, 16 Jun 2017 09:39:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54083) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrRd-00051f-CM for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dLrRY-0000gH-F8 for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:49 -0400 Received: from fanzine.igalia.com ([91.117.99.155]:35105) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dLrRX-0000eH-VB; Fri, 16 Jun 2017 09:37:44 -0400 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1dLrRU-0003tG-T4; Fri, 16 Jun 2017 15:37:41 +0200 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1dLrRD-00018v-3F; Fri, 16 Jun 2017 16:37:23 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=T1Qp8CjRCR/K9SRw8VNuVCHPXjuSZ6FWvb71Bif3lWI=; b=L5CAbD33Mf939sT3w1LgoLDpSWcoxfRSGahbgO1HDFJKIWe/yIuIv5lkRUXPAnHpanP6v6clyp3BbvBwShAveNckL/udL4PpuwDoiL+HI5cHRsEWbRZctorC8LAy0nOrkwM8zLXd1l31xFOwARrXoPCoiFQSg20PBN0MkQ0XzWsl8eFOalXfYhTHympgkZoVPD0zpiMW9kgbGeB3qpP0fpuEcJaARSCbPq2AJI3c0/S5OwKHKklAPoRaic5U2PFM+3xxd0lrbhlPM3oPZhk9Je0QyNH7I4Qi0oreycXLTZbcsoNEfOGVCLcSh5fO/GAiNlHb1NGuRRnmectDXpfYeg==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Fri, 16 Jun 2017 16:37:01 +0300 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH v3 1/7] qcow2: Remove unused Error variable in do_perform_cow() 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: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz , Stefan Hajnoczi , "Denis V . Lunev" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" We are using the return value of qcow2_encrypt_sectors() to detect problems but we are throwing away the returned Error since we have no way to report it to the user. Therefore we can simply get rid of the local Error variable and pass NULL instead. Alternatively we could try to figure out a way to pass the original error instead of simply returning -EIO, but that would be more invasive, so let's keep the current approach. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-cluster.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index d779ea19cf..d1c419f52b 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -440,16 +440,14 @@ static int coroutine_fn do_perform_cow(BlockDriverSta= te *bs, } =20 if (bs->encrypted) { - Error *err =3D NULL; int64_t sector =3D (src_cluster_offset + offset_in_cluster) >> BDRV_SECTOR_BITS; assert(s->cipher); assert((offset_in_cluster & ~BDRV_SECTOR_MASK) =3D=3D 0); assert((bytes & ~BDRV_SECTOR_MASK) =3D=3D 0); if (qcow2_encrypt_sectors(s, sector, iov.iov_base, iov.iov_base, - bytes >> BDRV_SECTOR_BITS, true, &err) <= 0) { + bytes >> BDRV_SECTOR_BITS, true, NULL) <= 0) { ret =3D -EIO; - error_free(err); goto out; } } --=20 2.11.0 From nobody Sun May 5 14:19:35 2024 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.zoho.com; dkim=fail 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 1497620603224646.8551870728112; Fri, 16 Jun 2017 06:43:23 -0700 (PDT) Received: from localhost ([::1]:58967 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrX0-000113-0u for importer@patchew.org; Fri, 16 Jun 2017 09:43:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54082) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrRd-00051e-Cc for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dLrRY-0000gK-Fv for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:49 -0400 Received: from fanzine.igalia.com ([91.117.99.155]:35114) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dLrRX-0000eL-VF; Fri, 16 Jun 2017 09:37:44 -0400 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1dLrRU-0003tF-R1; Fri, 16 Jun 2017 15:37:40 +0200 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1dLrRD-00018x-4G; Fri, 16 Jun 2017 16:37:23 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=I218g2GLUVG8jpp0iSl2J6pb4Y1p61WrhmBD08wbRno=; b=Uoz9Mx1++9ghcuEaPS02HxRPWLfuhLcuju6Uyop5vKI0YJkP2Iy2d6XifvNYHHUiBc63ysxe5TPVQbsw4eoAB1Gjv4b2JKH239v2loWP1cxqsmjKcKAtsgCdicEgB9F5Tykmb9SUwXo6/JtzCZsKOjdZZT1zB/0ijr+OnS6fNBt8NdFEse/UIC1JKc+/i6m5LrctFLyVPLtHvUlBpSJjPt05aOKUluzJIUv58BhfPr7i+vtTr/LoFMQD6K1ErqB5av41SJcXpeA8NkUe3LgdORVe9wu8OyYXlekJKYEFbKxf7dyokzJ/9hoFC7I5Z/jeAoHFY96fbiSgUYsEYf4vAQ==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Fri, 16 Jun 2017 16:37:02 +0300 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH v3 2/7] qcow2: Use unsigned int for both members of Qcow2COWRegion 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: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz , Stefan Hajnoczi , "Denis V . Lunev" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Qcow2COWRegion has two attributes: - The offset of the COW region from the start of the first cluster touched by the I/O request. Since it's always going to be positive and the maximum request size is at most INT_MAX, we can use a regular unsigned int to store this offset. - The size of the COW region in bytes. This is guaranteed to be >=3D 0, so we should use an unsigned type instead. In x86_64 this reduces the size of Qcow2COWRegion from 16 to 8 bytes. It will also help keep some assertions simpler now that we know that there are no negative numbers. The prototype of do_perform_cow() is also updated to reflect these changes. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-cluster.c | 4 ++-- block/qcow2.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index d1c419f52b..a86c5a75a9 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -406,8 +406,8 @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t se= ctor_num, static int coroutine_fn do_perform_cow(BlockDriverState *bs, uint64_t src_cluster_offset, uint64_t cluster_offset, - int offset_in_cluster, - int bytes) + unsigned offset_in_cluster, + unsigned bytes) { BDRVQcow2State *s =3D bs->opaque; QEMUIOVector qiov; diff --git a/block/qcow2.h b/block/qcow2.h index 1801dc30dc..c26ee0a33d 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -301,10 +301,10 @@ typedef struct Qcow2COWRegion { * Offset of the COW region in bytes from the start of the first clust= er * touched by the request. */ - uint64_t offset; + unsigned offset; =20 /** Number of bytes to copy */ - int nb_bytes; + unsigned nb_bytes; } Qcow2COWRegion; =20 /** --=20 2.11.0 From nobody Sun May 5 14:19:35 2024 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.zoho.com; dkim=fail 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 1497620408583128.05388654814885; Fri, 16 Jun 2017 06:40:08 -0700 (PDT) Received: from localhost ([::1]:58945 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrTq-0006bg-4A for importer@patchew.org; Fri, 16 Jun 2017 09:40:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54087) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrRd-00051i-DT for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dLrRY-0000gZ-G2 for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:49 -0400 Received: from fanzine.igalia.com ([91.117.99.155]:35118) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dLrRX-0000eM-VP; Fri, 16 Jun 2017 09:37:44 -0400 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1dLrRU-0003tJ-SG; Fri, 16 Jun 2017 15:37:40 +0200 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1dLrRD-000190-5K; Fri, 16 Jun 2017 16:37:23 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=Cg8lS3FJOqNrqpfimH38MQ2gFm9XIDNSuLhu8yKgBlc=; b=PmolR1+2s5g+4eG0PcxMk3ii98A38WjE9TxHEqgrHAJmHZvyfsdvG31n6b6QBG2AqoXj2zgFfH512HW3R43uc+bNZbxtbHz/KxxhH85MViIOrAfO7Fkh3EWfbG5S28xiy7U73QiWKXgi60KNvRy+yusAtbv2VknMaACSKlnsDfZh7gSkEgcNTioqCv+VBrQcs/kJASZbiXqfHkDWJVq4Q6g3KYhT/o/Ky1bMGw2k+m2K8M5MNE3Z8aLTmgWgbtmqSQWfxTDGbnIWCZQzhqlyHe/lSk70x424BBVBzERUFMREeFviZV5VqcbNijNAsVbLPgt3zHDoBQbQSN+fLgxyvA==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Fri, 16 Jun 2017 16:37:03 +0300 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH v3 3/7] qcow2: Make perform_cow() call do_perform_cow() twice 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: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz , Stefan Hajnoczi , "Denis V . Lunev" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Instead of calling perform_cow() twice with a different COW region each time, call it just once and make perform_cow() handle both regions. This patch simply moves code around. The next one will do the actual reordering of the COW operations. Signed-off-by: Alberto Garcia Reviewed-by: Eric Blake --- block/qcow2-cluster.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index a86c5a75a9..4c03639a72 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -414,6 +414,10 @@ static int coroutine_fn do_perform_cow(BlockDriverStat= e *bs, struct iovec iov; int ret; =20 + if (bytes =3D=3D 0) { + return 0; + } + iov.iov_len =3D bytes; iov.iov_base =3D qemu_try_blockalign(bs, iov.iov_len); if (iov.iov_base =3D=3D NULL) { @@ -751,31 +755,40 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockD= riverState *bs, return cluster_offset; } =20 -static int perform_cow(BlockDriverState *bs, QCowL2Meta *m, Qcow2COWRegion= *r) +static int perform_cow(BlockDriverState *bs, QCowL2Meta *m) { BDRVQcow2State *s =3D bs->opaque; + Qcow2COWRegion *start =3D &m->cow_start; + Qcow2COWRegion *end =3D &m->cow_end; int ret; =20 - if (r->nb_bytes =3D=3D 0) { + if (start->nb_bytes =3D=3D 0 && end->nb_bytes =3D=3D 0) { return 0; } =20 qemu_co_mutex_unlock(&s->lock); - ret =3D do_perform_cow(bs, m->offset, m->alloc_offset, r->offset, r->n= b_bytes); + ret =3D do_perform_cow(bs, m->offset, m->alloc_offset, + start->offset, start->nb_bytes); + if (ret < 0) { + goto fail; + } + + ret =3D do_perform_cow(bs, m->offset, m->alloc_offset, + end->offset, end->nb_bytes); + +fail: qemu_co_mutex_lock(&s->lock); =20 - if (ret < 0) { - return ret; - } - /* * Before we update the L2 table to actually point to the new cluster,= we * need to be sure that the refcounts have been increased and COW was * handled. */ - qcow2_cache_depends_on_flush(s->l2_table_cache); + if (ret =3D=3D 0) { + qcow2_cache_depends_on_flush(s->l2_table_cache); + } =20 - return 0; + return ret; } =20 int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) @@ -795,12 +808,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, = QCowL2Meta *m) } =20 /* copy content of unmodified sectors */ - ret =3D perform_cow(bs, m, &m->cow_start); - if (ret < 0) { - goto err; - } - - ret =3D perform_cow(bs, m, &m->cow_end); + ret =3D perform_cow(bs, m); if (ret < 0) { goto err; } --=20 2.11.0 From nobody Sun May 5 14:19:35 2024 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.zoho.com; dkim=fail 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 1497620508495598.7097161524475; Fri, 16 Jun 2017 06:41:48 -0700 (PDT) Received: from localhost ([::1]:58954 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrVT-00083W-7X for importer@patchew.org; Fri, 16 Jun 2017 09:41:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54084) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrRd-00051g-Ch for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dLrRY-0000gj-HM for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:49 -0400 Received: from fanzine.igalia.com ([91.117.99.155]:35106) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dLrRX-0000eI-VI; Fri, 16 Jun 2017 09:37:44 -0400 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1dLrRV-0003tL-0B; Fri, 16 Jun 2017 15:37:41 +0200 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1dLrRD-000194-6R; Fri, 16 Jun 2017 16:37:23 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=WMyeJX84p0opUO5GJP5lChVS9HK6GYStdKcILVEskj0=; b=bG23Cdmjtlizoh9GU9OAmGNfI/6sQItEAHcwNoC6AzVYgAppLmc6Gv14PsgkQhAM3usgvWnd9U8IpR8uHxcaD/8+C8fe0RBGQbZB0IVERgfzRhj4qWu6nAElxAUR4N+FN8k0boBmsmTtqubDflU8pHPXiqU85Syb+2id+dNx9l1kZaFVIyX7ai/SY9nTJxeUq/KyLDZmokuYyfC6IXPuGdfMJUCS5gKrgVwi1s+jhb6vZ+IXaDtECnGf3fhBFVhroPOhbgXEHsBOo0zYEh937oYSWuXjIfA/B/J1gR0YXgOaVorqYJkHPzPQz0/qhCRQtDaQT8ydnuurJBbRTjGkWw==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Fri, 16 Jun 2017 16:37:04 +0300 Message-Id: <19e8d8d7defd42a8859482c57affa307d7341786.1497619885.git.berto@igalia.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH v3 4/7] qcow2: Split do_perform_cow() into _read(), _encrypt() and _write() 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: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz , Stefan Hajnoczi , "Denis V . Lunev" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This patch splits do_perform_cow() into three separate functions to read, encrypt and write the COW regions. perform_cow() can now read both regions first, then encrypt them and finally write them to disk. The memory allocation is also done in this function now, using one single buffer large enough to hold both regions. Signed-off-by: Alberto Garcia --- block/qcow2-cluster.c | 117 +++++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 4c03639a72..3c9ace8a96 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -403,34 +403,26 @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t = sector_num, return 0; } =20 -static int coroutine_fn do_perform_cow(BlockDriverState *bs, - uint64_t src_cluster_offset, - uint64_t cluster_offset, - unsigned offset_in_cluster, - unsigned bytes) +static int coroutine_fn do_perform_cow_read(BlockDriverState *bs, + uint64_t src_cluster_offset, + unsigned offset_in_cluster, + uint8_t *buffer, + unsigned bytes) { - BDRVQcow2State *s =3D bs->opaque; QEMUIOVector qiov; - struct iovec iov; + struct iovec iov =3D { .iov_base =3D buffer, .iov_len =3D bytes }; int ret; =20 if (bytes =3D=3D 0) { return 0; } =20 - iov.iov_len =3D bytes; - iov.iov_base =3D qemu_try_blockalign(bs, iov.iov_len); - if (iov.iov_base =3D=3D NULL) { - return -ENOMEM; - } - qemu_iovec_init_external(&qiov, &iov, 1); =20 BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); =20 if (!bs->drv) { - ret =3D -ENOMEDIUM; - goto out; + return -ENOMEDIUM; } =20 /* Call .bdrv_co_readv() directly instead of using the public block-la= yer @@ -440,39 +432,63 @@ static int coroutine_fn do_perform_cow(BlockDriverSta= te *bs, ret =3D bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_clu= ster, bytes, &qiov, 0); if (ret < 0) { - goto out; + return ret; } =20 - if (bs->encrypted) { + return 0; +} + +static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs, + uint64_t src_cluster_offse= t, + unsigned offset_in_cluster, + uint8_t *buffer, + unsigned bytes) +{ + if (bytes && bs->encrypted) { + BDRVQcow2State *s =3D bs->opaque; int64_t sector =3D (src_cluster_offset + offset_in_cluster) >> BDRV_SECTOR_BITS; assert(s->cipher); assert((offset_in_cluster & ~BDRV_SECTOR_MASK) =3D=3D 0); assert((bytes & ~BDRV_SECTOR_MASK) =3D=3D 0); - if (qcow2_encrypt_sectors(s, sector, iov.iov_base, iov.iov_base, + if (qcow2_encrypt_sectors(s, sector, buffer, buffer, bytes >> BDRV_SECTOR_BITS, true, NULL) <= 0) { - ret =3D -EIO; - goto out; + return false; } } + return true; +} + +static int coroutine_fn do_perform_cow_write(BlockDriverState *bs, + uint64_t cluster_offset, + unsigned offset_in_cluster, + uint8_t *buffer, + unsigned bytes) +{ + QEMUIOVector qiov; + struct iovec iov =3D { .iov_base =3D buffer, .iov_len =3D bytes }; + int ret; + + if (bytes =3D=3D 0) { + return 0; + } + + qemu_iovec_init_external(&qiov, &iov, 1); =20 ret =3D qcow2_pre_write_overlap_check(bs, 0, cluster_offset + offset_in_cluster, bytes); if (ret < 0) { - goto out; + return ret; } =20 BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE); ret =3D bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster, bytes, &qiov, 0); if (ret < 0) { - goto out; + return ret; } =20 - ret =3D 0; -out: - qemu_vfree(iov.iov_base); - return ret; + return 0; } =20 =20 @@ -760,22 +776,62 @@ static int perform_cow(BlockDriverState *bs, QCowL2Me= ta *m) BDRVQcow2State *s =3D bs->opaque; Qcow2COWRegion *start =3D &m->cow_start; Qcow2COWRegion *end =3D &m->cow_end; + unsigned buffer_size; + uint8_t *start_buffer, *end_buffer; int ret; =20 + assert(start->nb_bytes <=3D UINT_MAX - end->nb_bytes); + if (start->nb_bytes =3D=3D 0 && end->nb_bytes =3D=3D 0) { return 0; } =20 + /* Reserve a buffer large enough to store the data from both the + * start and end COW regions. Add some padding in the middle if + * necessary to make sure that the end region is optimally aligned */ + buffer_size =3D QEMU_ALIGN_UP(start->nb_bytes, bdrv_opt_mem_align(bs))= + + end->nb_bytes; + start_buffer =3D qemu_try_blockalign(bs, buffer_size); + if (start_buffer =3D=3D NULL) { + return -ENOMEM; + } + /* The part of the buffer where the end region is located */ + end_buffer =3D start_buffer + buffer_size - end->nb_bytes; + qemu_co_mutex_unlock(&s->lock); - ret =3D do_perform_cow(bs, m->offset, m->alloc_offset, - start->offset, start->nb_bytes); + /* First we read the existing data from both COW regions */ + ret =3D do_perform_cow_read(bs, m->offset, start->offset, + start_buffer, start->nb_bytes); if (ret < 0) { goto fail; } =20 - ret =3D do_perform_cow(bs, m->offset, m->alloc_offset, - end->offset, end->nb_bytes); + ret =3D do_perform_cow_read(bs, m->offset, end->offset, + end_buffer, end->nb_bytes); + if (ret < 0) { + goto fail; + } + + /* Encrypt the data if necessary before writing it */ + if (bs->encrypted) { + if (!do_perform_cow_encrypt(bs, m->offset, start->offset, + start_buffer, start->nb_bytes) || + !do_perform_cow_encrypt(bs, m->offset, end->offset, + end_buffer, end->nb_bytes)) { + ret =3D -EIO; + goto fail; + } + } + + /* And now we can write everything */ + ret =3D do_perform_cow_write(bs, m->alloc_offset, start->offset, + start_buffer, start->nb_bytes); + if (ret < 0) { + goto fail; + } =20 + ret =3D do_perform_cow_write(bs, m->alloc_offset, end->offset, + end_buffer, end->nb_bytes); fail: qemu_co_mutex_lock(&s->lock); =20 @@ -788,6 +844,7 @@ fail: qcow2_cache_depends_on_flush(s->l2_table_cache); } =20 + qemu_vfree(start_buffer); return ret; } =20 --=20 2.11.0 From nobody Sun May 5 14:19:35 2024 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.zoho.com; dkim=fail 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 1497620531474191.81986716499023; Fri, 16 Jun 2017 06:42:11 -0700 (PDT) Received: from localhost ([::1]:58956 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrVq-0008Oq-7s for importer@patchew.org; Fri, 16 Jun 2017 09:42:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54081) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrRd-00051d-CH for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dLrRY-0000g8-EX for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:49 -0400 Received: from fanzine.igalia.com ([91.117.99.155]:35110) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dLrRX-0000eJ-VI; Fri, 16 Jun 2017 09:37:44 -0400 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1dLrRU-0003tM-Td; Fri, 16 Jun 2017 15:37:41 +0200 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1dLrRD-000197-7Y; Fri, 16 Jun 2017 16:37:23 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=OI2bI+aXZl69OoVmfb6Zs4UNPl4aSorf/2hxDSnNc08=; b=EDUVOmpWihyVdo9O8wA5HYKagPRcs09MBRBTcjxC9cU4mMoSf1xm5Gtk7SH7lfDQfG9R6ZoXxwO+noGB5rxES6xK9kdtjSrJxZc4fHkRkL5SKcyg9uvO+SWIkq4nUIpj/gZphn5ZpwjBqBO0evV1YDTLOGMqt+Kfz+pkIRJ8jAR7v20Z0SAl+WaNvtNUNSWcXCTcfbk3R4ZclL1kYXtzGRny2Fn3wHaobj71xDOpTtZ7L1p2MPYZmeimOq2DOnV+AYdcBmLEq0bdm9RopFbl9cZwtSKMVHDHEmepvvVlvc4tMDtOogJM9hp0P5KnuM+icPZrrAax8FoYlDQxQyCEXw==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Fri, 16 Jun 2017 16:37:05 +0300 Message-Id: <0e6efbc82b41c83ea4845f37d7020a5a46fb834f.1497619885.git.berto@igalia.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH v3 5/7] qcow2: Allow reading both COW regions with only one request 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: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz , Stefan Hajnoczi , "Denis V . Lunev" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Reading both COW regions requires two separate requests, but it's perfectly possible to merge them and perform only one. This generally improves performance, particularly on rotating disk drives. The downside is that the data in the middle region is read but discarded. This patch takes a conservative approach and only merges reads when the size of the middle region is <=3D 16KB. Signed-off-by: Alberto Garcia --- block/qcow2-cluster.c | 51 ++++++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 3c9ace8a96..20fb531932 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -777,20 +777,38 @@ static int perform_cow(BlockDriverState *bs, QCowL2Me= ta *m) Qcow2COWRegion *start =3D &m->cow_start; Qcow2COWRegion *end =3D &m->cow_end; unsigned buffer_size; + unsigned data_bytes =3D end->offset - (start->offset + start->nb_bytes= ); + bool merge_reads; uint8_t *start_buffer, *end_buffer; int ret; =20 assert(start->nb_bytes <=3D UINT_MAX - end->nb_bytes); + assert(start->nb_bytes + end->nb_bytes <=3D UINT_MAX - data_bytes); + assert(start->offset + start->nb_bytes <=3D end->offset); =20 if (start->nb_bytes =3D=3D 0 && end->nb_bytes =3D=3D 0) { return 0; } =20 - /* Reserve a buffer large enough to store the data from both the - * start and end COW regions. Add some padding in the middle if - * necessary to make sure that the end region is optimally aligned */ - buffer_size =3D QEMU_ALIGN_UP(start->nb_bytes, bdrv_opt_mem_align(bs))= + - end->nb_bytes; + /* If we have to read both the start and end COW regions and the + * middle region is not too large then perform just one read + * operation */ + merge_reads =3D start->nb_bytes && end->nb_bytes && data_bytes <=3D 16= 384; + if (merge_reads) { + buffer_size =3D start->nb_bytes + data_bytes + end->nb_bytes; + } else { + /* If we have to do two reads, add some padding in the middle + * if necessary to make sure that the end region is optimally + * aligned. */ + size_t align =3D bdrv_opt_mem_align(bs); + assert(align > 0 && align <=3D UINT_MAX); + assert(QEMU_ALIGN_UP(start->nb_bytes, align) <=3D + UINT_MAX - end->nb_bytes); + buffer_size =3D QEMU_ALIGN_UP(start->nb_bytes, align) + end->nb_by= tes; + } + + /* Reserve a buffer large enough to store all the data that we're + * going to read */ start_buffer =3D qemu_try_blockalign(bs, buffer_size); if (start_buffer =3D=3D NULL) { return -ENOMEM; @@ -799,15 +817,22 @@ static int perform_cow(BlockDriverState *bs, QCowL2Me= ta *m) end_buffer =3D start_buffer + buffer_size - end->nb_bytes; =20 qemu_co_mutex_unlock(&s->lock); - /* First we read the existing data from both COW regions */ - ret =3D do_perform_cow_read(bs, m->offset, start->offset, - start_buffer, start->nb_bytes); - if (ret < 0) { - goto fail; - } + /* First we read the existing data from both COW regions. We + * either read the whole region in one go, or the start and end + * regions separately. */ + if (merge_reads) { + ret =3D do_perform_cow_read(bs, m->offset, start->offset, + start_buffer, buffer_size); + } else { + ret =3D do_perform_cow_read(bs, m->offset, start->offset, + start_buffer, start->nb_bytes); + if (ret < 0) { + goto fail; + } =20 - ret =3D do_perform_cow_read(bs, m->offset, end->offset, - end_buffer, end->nb_bytes); + ret =3D do_perform_cow_read(bs, m->offset, end->offset, + end_buffer, end->nb_bytes); + } if (ret < 0) { goto fail; } --=20 2.11.0 From nobody Sun May 5 14:19:35 2024 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.zoho.com; dkim=fail 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 1497620383310241.64826618501058; Fri, 16 Jun 2017 06:39:43 -0700 (PDT) Received: from localhost ([::1]:58941 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrTR-0006Fc-8U for importer@patchew.org; Fri, 16 Jun 2017 09:39:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54092) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrRd-00051k-Ex for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dLrRY-0000gU-GF for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:49 -0400 Received: from fanzine.igalia.com ([91.117.99.155]:35111) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dLrRX-0000eK-V9; Fri, 16 Jun 2017 09:37:44 -0400 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1dLrRV-0003tN-0o; Fri, 16 Jun 2017 15:37:41 +0200 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1dLrRD-00019A-8Z; Fri, 16 Jun 2017 16:37:23 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=xteI+B5IK1oZ1Pyvq37OnTa9KBMbGYWCD16BKyGltEQ=; b=k/5XymOBXWqcuiMIWWcsw5H9WwYebua/Ns8TYoyP1mL49FeQs5ePVdZy2yKBkHqUIRYdDSNKAumKN27XdPB2+ZKRQZASr7exI1Cwr1Zhx4bLxNxVCHF9S3B14FadxcY1Fj2cbT7E26WgDCHd0gss9GrvoNkg3rK3DObXa0+3oiQW58XToQ5QwfIe8wTb4MnkJi7stMaQYerXf0IUFiEmMBb9ZyWBslBjTYwe4yEXxbRhxT0FO69opt7KjMGo/VcxVcjl84PmdLJpkLfvaQ4xrA8Icvy7A9KAiRByL58mCMtQC+fMoWH1vTRfuLMXVn8uN3ZxLs7rjaON63NyOsgqKg==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Fri, 16 Jun 2017 16:37:06 +0300 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH v3 6/7] qcow2: Pass a QEMUIOVector to do_perform_cow_{read, write}() 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: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz , Stefan Hajnoczi , "Denis V . Lunev" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Instead of passing a single buffer pointer to do_perform_cow_write(), pass a QEMUIOVector. This will allow us to merge the write requests for the COW regions and the actual data into a single one. Although do_perform_cow_read() does not strictly need to change its API, we're doing it here as well for consistency. Signed-off-by: Alberto Garcia Reviewed-by: Manos Pitsidianakis --- block/qcow2-cluster.c | 51 ++++++++++++++++++++++++-----------------------= ---- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 20fb531932..e1e45bd122 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -406,19 +406,14 @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t = sector_num, static int coroutine_fn do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset, unsigned offset_in_cluster, - uint8_t *buffer, - unsigned bytes) + QEMUIOVector *qiov) { - QEMUIOVector qiov; - struct iovec iov =3D { .iov_base =3D buffer, .iov_len =3D bytes }; int ret; =20 - if (bytes =3D=3D 0) { + if (qiov->size =3D=3D 0) { return 0; } =20 - qemu_iovec_init_external(&qiov, &iov, 1); - BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); =20 if (!bs->drv) { @@ -430,7 +425,7 @@ static int coroutine_fn do_perform_cow_read(BlockDriver= State *bs, * which can lead to deadlock when block layer copy-on-read is enabled. */ ret =3D bs->drv->bdrv_co_preadv(bs, src_cluster_offset + offset_in_clu= ster, - bytes, &qiov, 0); + qiov->size, qiov, 0); if (ret < 0) { return ret; } @@ -462,28 +457,23 @@ static bool coroutine_fn do_perform_cow_encrypt(Block= DriverState *bs, static int coroutine_fn do_perform_cow_write(BlockDriverState *bs, uint64_t cluster_offset, unsigned offset_in_cluster, - uint8_t *buffer, - unsigned bytes) + QEMUIOVector *qiov) { - QEMUIOVector qiov; - struct iovec iov =3D { .iov_base =3D buffer, .iov_len =3D bytes }; int ret; =20 - if (bytes =3D=3D 0) { + if (qiov->size =3D=3D 0) { return 0; } =20 - qemu_iovec_init_external(&qiov, &iov, 1); - ret =3D qcow2_pre_write_overlap_check(bs, 0, - cluster_offset + offset_in_cluster, bytes); + cluster_offset + offset_in_cluster, qiov->size); if (ret < 0) { return ret; } =20 BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE); ret =3D bdrv_co_pwritev(bs->file, cluster_offset + offset_in_cluster, - bytes, &qiov, 0); + qiov->size, qiov, 0); if (ret < 0) { return ret; } @@ -780,6 +770,7 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta= *m) unsigned data_bytes =3D end->offset - (start->offset + start->nb_bytes= ); bool merge_reads; uint8_t *start_buffer, *end_buffer; + QEMUIOVector qiov; int ret; =20 assert(start->nb_bytes <=3D UINT_MAX - end->nb_bytes); @@ -816,22 +807,25 @@ static int perform_cow(BlockDriverState *bs, QCowL2Me= ta *m) /* The part of the buffer where the end region is located */ end_buffer =3D start_buffer + buffer_size - end->nb_bytes; =20 + qemu_iovec_init(&qiov, 3); + qemu_co_mutex_unlock(&s->lock); /* First we read the existing data from both COW regions. We * either read the whole region in one go, or the start and end * regions separately. */ if (merge_reads) { - ret =3D do_perform_cow_read(bs, m->offset, start->offset, - start_buffer, buffer_size); + qemu_iovec_add(&qiov, start_buffer, buffer_size); + ret =3D do_perform_cow_read(bs, m->offset, start->offset, &qiov); } else { - ret =3D do_perform_cow_read(bs, m->offset, start->offset, - start_buffer, start->nb_bytes); + qemu_iovec_add(&qiov, start_buffer, start->nb_bytes); + ret =3D do_perform_cow_read(bs, m->offset, start->offset, &qiov); if (ret < 0) { goto fail; } =20 - ret =3D do_perform_cow_read(bs, m->offset, end->offset, - end_buffer, end->nb_bytes); + qemu_iovec_reset(&qiov); + qemu_iovec_add(&qiov, end_buffer, end->nb_bytes); + ret =3D do_perform_cow_read(bs, m->offset, end->offset, &qiov); } if (ret < 0) { goto fail; @@ -849,14 +843,16 @@ static int perform_cow(BlockDriverState *bs, QCowL2Me= ta *m) } =20 /* And now we can write everything */ - ret =3D do_perform_cow_write(bs, m->alloc_offset, start->offset, - start_buffer, start->nb_bytes); + qemu_iovec_reset(&qiov); + qemu_iovec_add(&qiov, start_buffer, start->nb_bytes); + ret =3D do_perform_cow_write(bs, m->alloc_offset, start->offset, &qiov= ); if (ret < 0) { goto fail; } =20 - ret =3D do_perform_cow_write(bs, m->alloc_offset, end->offset, - end_buffer, end->nb_bytes); + qemu_iovec_reset(&qiov); + qemu_iovec_add(&qiov, end_buffer, end->nb_bytes); + ret =3D do_perform_cow_write(bs, m->alloc_offset, end->offset, &qiov); fail: qemu_co_mutex_lock(&s->lock); =20 @@ -870,6 +866,7 @@ fail: } =20 qemu_vfree(start_buffer); + qemu_iovec_destroy(&qiov); return ret; } =20 --=20 2.11.0 From nobody Sun May 5 14:19:35 2024 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.zoho.com; dkim=fail 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 1497620665537438.05375568034776; Fri, 16 Jun 2017 06:44:25 -0700 (PDT) Received: from localhost ([::1]:58977 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrY0-0001iA-7D for importer@patchew.org; Fri, 16 Jun 2017 09:44:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54086) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dLrRd-00051h-DA for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dLrRY-0000ge-GN for qemu-devel@nongnu.org; Fri, 16 Jun 2017 09:37:49 -0400 Received: from fanzine.igalia.com ([91.117.99.155]:35104) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dLrRX-0000eO-Ul; Fri, 16 Jun 2017 09:37:44 -0400 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1dLrRV-0003tO-1A; Fri, 16 Jun 2017 15:37:41 +0200 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1dLrRD-00019D-9V; Fri, 16 Jun 2017 16:37:23 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=kCkDoWHAcBfihZ2ZkNonbGvdFm8G9F/Y0N1s7VSgMCE=; b=d4ygvqtdzmrAyG+G0uDwOhuF1GeX0MQsbs5cVsNkmjLkvidfNKaA17KrtyrWMu/ZoILsTbW0fcfbvTIzn1U2ME+dacp0bjttRmaexjA9tbMNJBrq92/K1RConrimd6Lx1jZwldx0tw3yIdpVw6txRhBe4kJGDpnfe000zx4t8fJMAnwaY2qZ0vTRpZInNiMNHsd/lTV8h8hltNVSLuGkuiyWUGHsYndfLiFM5/rhF182WXcYIT+ZYP6KYkHJfnDX7y3qkU4y0lmR2URXSkPY6EHJEwGcdDGA5vdurlsDlvGFZMVLhNCiCy0IauK3wbbdZ+FpEZAsH91797S0ptaL/w==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Fri, 16 Jun 2017 16:37:07 +0300 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH v3 7/7] qcow2: Merge the writing of the COW regions with the guest data 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: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Max Reitz , Stefan Hajnoczi , "Denis V . Lunev" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" If the guest tries to write data that results on the allocation of a new cluster, instead of writing the guest data first and then the data from the COW regions, write everything together using one single I/O operation. This can improve the write performance by 25% or more, depending on several factors such as the media type, the cluster size and the I/O request size. Signed-off-by: Alberto Garcia --- block/qcow2-cluster.c | 38 ++++++++++++++++++++++-------- block/qcow2.c | 64 +++++++++++++++++++++++++++++++++++++++++++----= ---- block/qcow2.h | 7 ++++++ 3 files changed, 90 insertions(+), 19 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index e1e45bd122..3e2dc77372 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -776,6 +776,7 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta= *m) assert(start->nb_bytes <=3D UINT_MAX - end->nb_bytes); assert(start->nb_bytes + end->nb_bytes <=3D UINT_MAX - data_bytes); assert(start->offset + start->nb_bytes <=3D end->offset); + assert(!m->data_qiov || m->data_qiov->size =3D=3D data_bytes); =20 if (start->nb_bytes =3D=3D 0 && end->nb_bytes =3D=3D 0) { return 0; @@ -842,17 +843,36 @@ static int perform_cow(BlockDriverState *bs, QCowL2Me= ta *m) } } =20 - /* And now we can write everything */ - qemu_iovec_reset(&qiov); - qemu_iovec_add(&qiov, start_buffer, start->nb_bytes); - ret =3D do_perform_cow_write(bs, m->alloc_offset, start->offset, &qiov= ); - if (ret < 0) { - goto fail; + /* And now we can write everything. If we have the guest data we + * can write everything in one single operation */ + if (m->data_qiov) { + qemu_iovec_reset(&qiov); + if (start->nb_bytes) { + qemu_iovec_add(&qiov, start_buffer, start->nb_bytes); + } + qemu_iovec_concat(&qiov, m->data_qiov, 0, data_bytes); + if (end->nb_bytes) { + qemu_iovec_add(&qiov, end_buffer, end->nb_bytes); + } + /* NOTE: we have a write_aio blkdebug event here followed by + * a cow_write one in do_perform_cow_write(), but there's only + * one single I/O operation */ + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); + ret =3D do_perform_cow_write(bs, m->alloc_offset, start->offset, &= qiov); + } else { + /* If there's no guest data then write both COW regions separately= */ + qemu_iovec_reset(&qiov); + qemu_iovec_add(&qiov, start_buffer, start->nb_bytes); + ret =3D do_perform_cow_write(bs, m->alloc_offset, start->offset, &= qiov); + if (ret < 0) { + goto fail; + } + + qemu_iovec_reset(&qiov); + qemu_iovec_add(&qiov, end_buffer, end->nb_bytes); + ret =3D do_perform_cow_write(bs, m->alloc_offset, end->offset, &qi= ov); } =20 - qemu_iovec_reset(&qiov); - qemu_iovec_add(&qiov, end_buffer, end->nb_bytes); - ret =3D do_perform_cow_write(bs, m->alloc_offset, end->offset, &qiov); fail: qemu_co_mutex_lock(&s->lock); =20 diff --git a/block/qcow2.c b/block/qcow2.c index b3ba5daa93..89be2083d4 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1575,6 +1575,44 @@ fail: return ret; } =20 +/* Check if it's possible to merge a write request with the writing of + * the data from the COW regions */ +static bool can_merge_cow(uint64_t offset, unsigned bytes, + QEMUIOVector *hd_qiov, QCowL2Meta *l2meta) +{ + QCowL2Meta *m; + + for (m =3D l2meta; m !=3D NULL; m =3D m->next) { + /* If both COW regions are empty then there's nothing to merge */ + if (m->cow_start.nb_bytes =3D=3D 0 && m->cow_end.nb_bytes =3D=3D 0= ) { + continue; + } + + /* The data (middle) region must be immediately after the + * start region */ + if (l2meta_cow_start(m) + m->cow_start.nb_bytes !=3D offset) { + continue; + } + + /* The end region must be immediately after the data (middle) + * region */ + if (m->offset + m->cow_end.offset !=3D offset + bytes) { + continue; + } + + /* Make sure that adding both COW regions to the QEMUIOVector + * does not exceed IOV_MAX */ + if (hd_qiov->niov > IOV_MAX - 2) { + continue; + } + + m->data_qiov =3D hd_qiov; + return true; + } + + return false; +} + static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t of= fset, uint64_t bytes, QEMUIOVector *qio= v, int flags) @@ -1657,16 +1695,22 @@ static coroutine_fn int qcow2_co_pwritev(BlockDrive= rState *bs, uint64_t offset, goto fail; } =20 - qemu_co_mutex_unlock(&s->lock); - BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); - trace_qcow2_writev_data(qemu_coroutine_self(), - cluster_offset + offset_in_cluster); - ret =3D bdrv_co_pwritev(bs->file, - cluster_offset + offset_in_cluster, - cur_bytes, &hd_qiov, 0); - qemu_co_mutex_lock(&s->lock); - if (ret < 0) { - goto fail; + /* If we need to do COW, check if it's possible to merge the + * writing of the guest data together with that of the COW regions. + * If it's not possible (or not necessary) then write the + * guest data now. */ + if (!can_merge_cow(offset, cur_bytes, &hd_qiov, l2meta)) { + qemu_co_mutex_unlock(&s->lock); + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); + trace_qcow2_writev_data(qemu_coroutine_self(), + cluster_offset + offset_in_cluster); + ret =3D bdrv_co_pwritev(bs->file, + cluster_offset + offset_in_cluster, + cur_bytes, &hd_qiov, 0); + qemu_co_mutex_lock(&s->lock); + if (ret < 0) { + goto fail; + } } =20 while (l2meta !=3D NULL) { diff --git a/block/qcow2.h b/block/qcow2.h index c26ee0a33d..87b15eb4aa 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -343,6 +343,13 @@ typedef struct QCowL2Meta */ Qcow2COWRegion cow_end; =20 + /** + * The I/O vector with the data from the actual guest write request. + * If non-NULL, this is meant to be merged together with the data + * from @cow_start and @cow_end into one single write operation. + */ + QEMUIOVector *data_qiov; + /** Pointer to next L2Meta of the same write request */ struct QCowL2Meta *next; =20 --=20 2.11.0