From nobody Mon Feb 9 09:08:39 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.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 1495540505721832.94441455994; Tue, 23 May 2017 04:55:05 -0700 (PDT) Received: from localhost ([::1]:48012 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dD8P2-00018a-FT for importer@patchew.org; Tue, 23 May 2017 07:55:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46662) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dD7ux-0000AX-Dq for qemu-devel@nongnu.org; Tue, 23 May 2017 07:24:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dD7us-0000Hc-Gi for qemu-devel@nongnu.org; Tue, 23 May 2017 07:23:59 -0400 Received: from fanzine.igalia.com ([91.117.99.155]:55467) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dD7us-00085I-12; Tue, 23 May 2017 07:23:54 -0400 Received: from [192.168.13.244] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1dD7uD-0002iY-Te; Tue, 23 May 2017 13:23:13 +0200 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1dD7uD-0005Lr-RM; Tue, 23 May 2017 14:23:13 +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=SSRXc/4b/QF1sLwoRspYZVebbK8vJJiolbKVHg0E/zs=; b=mm2/fL3Ggnv+zV4HPJLEsQ+4ZEAf/iibx8ugd0uErztqOa1PSkuH2V6peA3rgmP7sSkfpeTrcLCvW+CdpvByponx5tH9jD06sWu5sxUT2RyXHQx2L7cG2ap9aqXCJgDzxmmj6yHM/JCTgOB+luMpjtVr8z22KW89RoVg0r0+Zv5OZQLKSl7apoIB9dB95oSZ2YtYFXsBVtBVQrycp7s/X+sE1npBqyynJfMjxbNLjDp02/zRejnirBaa/33pv0KTapUusgImSM35SFFMZjrmnLfrofanQhmS/ObWESxEXXYhktRSNO1BVj07N240KhMM24Gtz2siLK/0HeavmMlthQ==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Tue, 23 May 2017 13:23:00 +0200 Message-Id: <47a9c0b2ade031f343757c1cd8b8aa475b34e595.1495536228.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 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 | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 643c48088b..67a761731d 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -777,34 +777,53 @@ static int perform_cow(BlockDriverState *bs, QCowL2Me= ta *m) Qcow2COWRegion *start =3D &m->cow_start; Qcow2COWRegion *end =3D &m->cow_end; unsigned buffer_size =3D start->nb_bytes + end->nb_bytes; + unsigned data_bytes =3D end->offset - (start->offset + start->nb_bytes= ); + bool merge_reads =3D false; uint8_t *start_buffer, *end_buffer; int ret; =20 assert(start->nb_bytes <=3D UINT_MAX - end->nb_bytes); + assert(buffer_size <=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 */ + /* 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 */ + if (start->nb_bytes && end->nb_bytes && data_bytes <=3D 16384) { + merge_reads =3D true; + buffer_size +=3D data_bytes; + } + + /* 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; } /* The part of the buffer where the end region is located */ - end_buffer =3D start_buffer + start->nb_bytes; + 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