From nobody Sun Feb 8 15:54:05 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 14999609865851011.8764147282526; Thu, 13 Jul 2017 08:49:46 -0700 (PDT) Received: from localhost ([::1]:60803 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVgN6-0007v3-UM for importer@patchew.org; Thu, 13 Jul 2017 11:49:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53749) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVgL0-0004d8-6N for qemu-devel@nongnu.org; Thu, 13 Jul 2017 11:47:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dVgKx-0005hW-Ol for qemu-devel@nongnu.org; Thu, 13 Jul 2017 11:47:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37940) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dVgKu-0005f7-Ko; Thu, 13 Jul 2017 11:47:28 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 62779C057FA8; Thu, 13 Jul 2017 15:47:27 +0000 (UTC) Received: from red.redhat.com (ovpn-121-60.rdu2.redhat.com [10.10.121.60]) by smtp.corp.redhat.com (Postfix) with ESMTP id C24DC709F3; Thu, 13 Jul 2017 15:47:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 62779C057FA8 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=eblake@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 62779C057FA8 From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 13 Jul 2017 10:46:50 -0500 Message-Id: <20170713154711.32374-3-eblake@redhat.com> In-Reply-To: <20170713154711.32374-1-eblake@redhat.com> References: <20170713154711.32374-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 13 Jul 2017 15:47:27 +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] [PATCH v3 02/23] block: Add flag to avoid wasted work in bdrv_is_allocated() 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, famz@redhat.com, qemu-block@nongnu.org, el13635@mail.ntua.gr, Max Reitz , Stefan Hajnoczi , 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" Not all callers care about which BDS owns the mapping for a given range of the file. In particular, bdrv_is_allocated() cares more about finding the largest run of allocated data from the guest perspective, whether or not that data is consecutive from the host perspective. Therefore, doing subsequent refinements such as checking how much of the format-layer allocation also satisfies BDRV_BLOCK_ZERO at the protocol layer is wasted work - in the best case, it just costs extra CPU cycles during a single bdrv_is_allocated(), but in the worst case, it results in a smaller *pnum, and forces callers to iterate through more status probes when visiting the entire file for even more extra CPU cycles. This patch only optimizes the block layer. But subsequent patches will tweak the driver callback to be byte-based, and in the process, can also pass this hint through to the driver. Signed-off-by: Eric Blake --- v3: s/allocation/mapping/ and flip sense of bool v2: new patch --- block/io.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/block/io.c b/block/io.c index 0305e61..e8a1b5c 100644 --- a/block/io.c +++ b/block/io.c @@ -1685,6 +1685,7 @@ typedef struct BdrvCoGetBlockStatusData { int nb_sectors; int *pnum; int64_t ret; + bool mapping; bool done; } BdrvCoGetBlockStatusData; @@ -1719,6 +1720,11 @@ int64_t coroutine_fn bdrv_co_get_block_status_from_b= acking(BlockDriverState *bs, * Drivers not implementing the functionality are assumed to not support * backing files, hence all their sectors are reported as allocated. * + * If 'mapping' is true, the caller is querying for mapping purposes, + * and the result should include BDRV_BLOCK_OFFSET_VALID where + * possible; otherwise, the result may omit that bit particularly if + * it allows for a larger value in 'pnum'. + * * If 'sector_num' is beyond the end of the disk image the return value is * BDRV_BLOCK_EOF and 'pnum' is set to 0. * @@ -1735,6 +1741,7 @@ int64_t coroutine_fn bdrv_co_get_block_status_from_ba= cking(BlockDriverState *bs, * is allocated in. */ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + bool mapping, int64_t sector_num, int nb_sectors, int *= pnum, BlockDriverState **fi= le) @@ -1793,14 +1800,15 @@ static int64_t coroutine_fn bdrv_co_get_block_statu= s(BlockDriverState *bs, if (ret & BDRV_BLOCK_RAW) { assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file); - ret =3D bdrv_co_get_block_status(local_file, ret >> BDRV_SECTOR_BI= TS, + ret =3D bdrv_co_get_block_status(local_file, mapping, + ret >> BDRV_SECTOR_BITS, *pnum, pnum, &local_file); goto out; } if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) { ret |=3D BDRV_BLOCK_ALLOCATED; - } else { + } else if (mapping) { if (bdrv_unallocated_blocks_are_zero(bs)) { ret |=3D BDRV_BLOCK_ZERO; } else if (bs->backing) { @@ -1812,12 +1820,13 @@ static int64_t coroutine_fn bdrv_co_get_block_statu= s(BlockDriverState *bs, } } - if (local_file && local_file !=3D bs && + if (mapping && local_file && local_file !=3D bs && (ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) && (ret & BDRV_BLOCK_OFFSET_VALID)) { int file_pnum; - ret2 =3D bdrv_co_get_block_status(local_file, ret >> BDRV_SECTOR_B= ITS, + ret2 =3D bdrv_co_get_block_status(local_file, mapping, + ret >> BDRV_SECTOR_BITS, *pnum, &file_pnum, NULL); if (ret2 >=3D 0) { /* Ignore errors. This is just providing extra information, it @@ -1852,6 +1861,7 @@ out: static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverStat= e *bs, BlockDriverState *base, + bool mapping, int64_t sector_num, int nb_sectors, int *pnum, @@ -1863,7 +1873,8 @@ static int64_t coroutine_fn bdrv_co_get_block_status_= above(BlockDriverState *bs, assert(bs !=3D base); for (p =3D bs; p !=3D base; p =3D backing_bs(p)) { - ret =3D bdrv_co_get_block_status(p, sector_num, nb_sectors, pnum, = file); + ret =3D bdrv_co_get_block_status(p, mapping, sector_num, nb_sector= s, + pnum, file); if (ret < 0) { break; } @@ -1893,6 +1904,7 @@ static void coroutine_fn bdrv_get_block_status_above_= co_entry(void *opaque) BdrvCoGetBlockStatusData *data =3D opaque; data->ret =3D bdrv_co_get_block_status_above(data->bs, data->base, + data->mapping, data->sector_num, data->nb_sectors, data->pnum, @@ -1905,11 +1917,12 @@ static void coroutine_fn bdrv_get_block_status_abov= e_co_entry(void *opaque) * * See bdrv_co_get_block_status_above() for details. */ -int64_t bdrv_get_block_status_above(BlockDriverState *bs, - BlockDriverState *base, - int64_t sector_num, - int nb_sectors, int *pnum, - BlockDriverState **file) +static int64_t bdrv_common_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + bool mapping, + int64_t sector_num, + int nb_sectors, int *pnum, + BlockDriverState **file) { Coroutine *co; BdrvCoGetBlockStatusData data =3D { @@ -1919,6 +1932,7 @@ int64_t bdrv_get_block_status_above(BlockDriverState = *bs, .sector_num =3D sector_num, .nb_sectors =3D nb_sectors, .pnum =3D pnum, + .mapping =3D mapping, .done =3D false, }; @@ -1934,6 +1948,16 @@ int64_t bdrv_get_block_status_above(BlockDriverState= *bs, return data.ret; } +int64_t bdrv_get_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + int64_t sector_num, + int nb_sectors, int *pnum, + BlockDriverState **file) +{ + return bdrv_common_block_status_above(bs, base, true, sector_num, + nb_sectors, pnum, file); +} + int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum, @@ -1946,15 +1970,15 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum) { - int64_t sector_num =3D offset >> BDRV_SECTOR_BITS; - int nb_sectors =3D bytes >> BDRV_SECTOR_BITS; int64_t ret; int psectors; assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE) && bytes < INT_MAX); - ret =3D bdrv_get_block_status(bs, sector_num, nb_sectors, &psectors, - NULL); + ret =3D bdrv_common_block_status_above(bs, backing_bs(bs), false, + offset >> BDRV_SECTOR_BITS, + bytes >> BDRV_SECTOR_BITS, &psect= ors, + NULL); if (ret < 0) { return ret; } --=20 2.9.4