From patchwork Tue Apr 25 19:59:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ashijeet Acharya X-Patchwork-Id: 755025 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wCDZr4StRz9s7h for ; Wed, 26 Apr 2017 06:00:04 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="EEt6toWV"; dkim-atps=neutral Received: from localhost ([::1]:51175 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d36d0-000747-46 for incoming@patchwork.ozlabs.org; Tue, 25 Apr 2017 16:00:02 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52585) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d36cE-00071u-S8 for qemu-devel@nongnu.org; Tue, 25 Apr 2017 15:59:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d36cD-00041l-R8 for qemu-devel@nongnu.org; Tue, 25 Apr 2017 15:59:14 -0400 Received: from mail-pf0-x241.google.com ([2607:f8b0:400e:c00::241]:35942) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1d36cD-00041f-JC; Tue, 25 Apr 2017 15:59:13 -0400 Received: by mail-pf0-x241.google.com with SMTP id v14so11217518pfd.3; Tue, 25 Apr 2017 12:59:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2n/DnCZ8ehdmy5uxUKPHvSyeXAoL+Ns9QpAIX6kKEKk=; b=EEt6toWVKucMDgCkII/zCiApF+0j4CO1gDh6D/mESBkdfbuht62w82zoePokxqOnfl xCvkqJ3+oFZ3DeULRPToVOb36Oz/D+6P3EXMKY/EzA+k+uBOlxOnuU8k/P24/aKsFGL1 iEcMpCDaTcmaiqBTGfLLe0m4B/Wwij8gRIig04QUIywaMl5f58FH77xUJ3NgCahQtbQd FUBsIQ1a4ffOutSSs3AKNcVmB0B18PS4lU8GUx7zA8gDH+iC/R+NB0vNa3nFtM/ek/1y RGCsiLMLfRyxD492PtH8GrKtjf4ohRAMToSqxrMncXHFEL6DJbc5xjiZCrCbnbLT6HAd YXxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2n/DnCZ8ehdmy5uxUKPHvSyeXAoL+Ns9QpAIX6kKEKk=; b=ITq3LAHvbgZi9hp/qMAVCVfId/CykEZk4utGUAprm79D84FkR8KfiSsi4oTtzdWweZ zkRqscYfQDoqExgL6WLcNbuHIhVYvDEeTP8ny8QxguewzVjtnYW9du/YAcZRyUvEa7jO LmMpSU6KbWIyNPV0FwebJuWkezTvlOdv4DN0Rf+AJ8X0Qydu7GNDEKfINfXF70EGsY9J TsGgBJnLqGpcDWyQFdVYzSX5BAeS/f8PJ67R0U+UTG/nH5NMrRDDo+sYM9Ew1UsNWsff I4mk7bVg9jW5sZ5+qrv2bfMGiS5hjgQgsdP9JaelTtPtSrEIEXEXuFc2VCATajFgwKvp RjBw== X-Gm-Message-State: AN3rC/7+UlOeRdYApszsr6ekFhD3a1bs3ky+yjS/6TvMr5GmK7mlkbS7 Tu4TeayYEQvp3A== X-Received: by 10.99.129.194 with SMTP id t185mr29390175pgd.57.1493150352591; Tue, 25 Apr 2017 12:59:12 -0700 (PDT) Received: from linux.local ([157.51.23.94]) by smtp.gmail.com with ESMTPSA id y187sm37931530pfy.67.2017.04.25.12.59.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 25 Apr 2017 12:59:12 -0700 (PDT) From: Ashijeet Acharya To: stefanha@gmail.com Date: Wed, 26 Apr 2017 01:29:07 +0530 Message-Id: <1493150351-28918-5-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1493150351-28918-1-git-send-email-ashijeetacharya@gmail.com> References: <1493150351-28918-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::241 Subject: [Qemu-devel] [PATCH v1 4/8] dmg: Refactor and prepare dmg_read_chunk() to cache random access points 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, qemu-devel@nongnu.org, mreitz@redhat.com, peter@lekensteyn.nl, Ashijeet Acharya , jsnow@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Refactor dmg_read_chunk() to start making use of the new DMGReadState structure and do chunk and sector related calculations based on it. Add a new argument "DMGReadState *drs" to it. Signed-off-by: Ashijeet Acharya --- block/dmg.c | 153 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 91 insertions(+), 62 deletions(-) diff --git a/block/dmg.c b/block/dmg.c index 7ae30e3..dc356b0 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -578,78 +578,106 @@ static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num) return s->n_chunks; /* error */ } -static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) +static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num, + DMGReadState *drs) { BDRVDMGState *s = bs->opaque; + int ret; + uint32_t sector_offset; + uint64_t sectors_read; + uint32_t chunk; + if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) { - int ret; - uint32_t chunk = search_chunk(s, sector_num); + chunk = search_chunk(s, sector_num); + } else { + chunk = drs->saved_chunk_type; + } - if (chunk >= s->n_chunks) { + if (chunk >= s->n_chunks) { + return -1; + } + + /* reset our access point cache if we had a change in current chunk */ + if (chunk != drs->saved_chunk_type) { + cache_access_point(drs, NULL, -1, -1, -1, -1); + } + + sector_offset = sector_num - s->sectors[chunk]; + + if ((s->sectorcounts[chunk] - sector_offset) > DMG_SECTOR_MAX) { + sectors_read = DMG_SECTOR_MAX; + } else { + sectors_read = s->sectorcounts[chunk] - sector_offset; + } + + /* truncate sectors read if it exceeds the 2MB buffer of qemu-img + * convert */ + if ((sector_num % DMG_SECTOR_MAX) + sectors_read > DMG_SECTOR_MAX) { + sectors_read = DMG_SECTOR_MAX - (sector_num % DMG_SECTOR_MAX); + } + + s->current_chunk = s->n_chunks; + + switch (s->types[chunk]) { /* block entry type */ + case 0x80000005: { /* zlib compressed */ + /* we need to buffer, because only the chunk as whole can be + * inflated. */ + ret = bdrv_pread(bs->file, s->offsets[chunk], + s->compressed_chunk, s->lengths[chunk]); + if (ret != s->lengths[chunk]) { return -1; } - s->current_chunk = s->n_chunks; - switch (s->types[chunk]) { /* block entry type */ - case 0x80000005: { /* zlib compressed */ - /* we need to buffer, because only the chunk as whole can be - * inflated. */ - ret = bdrv_pread(bs->file, s->offsets[chunk], - s->compressed_chunk, s->lengths[chunk]); - if (ret != s->lengths[chunk]) { - return -1; - } - - s->zstream.next_in = s->compressed_chunk; - s->zstream.avail_in = s->lengths[chunk]; - s->zstream.next_out = s->uncompressed_chunk; - s->zstream.avail_out = 512 * s->sectorcounts[chunk]; - ret = inflateReset(&s->zstream); - if (ret != Z_OK) { - return -1; - } - ret = inflate(&s->zstream, Z_FINISH); - if (ret != Z_STREAM_END || - s->zstream.total_out != 512 * s->sectorcounts[chunk]) { - return -1; - } - break; } - case 0x80000006: /* bzip2 compressed */ - if (!dmg_uncompress_bz2) { - break; - } - /* we need to buffer, because only the chunk as whole can be - * inflated. */ - ret = bdrv_pread(bs->file, s->offsets[chunk], - s->compressed_chunk, s->lengths[chunk]); - if (ret != s->lengths[chunk]) { - return -1; - } - - ret = dmg_uncompress_bz2((char *)s->compressed_chunk, - (unsigned int) s->lengths[chunk], - (char *)s->uncompressed_chunk, - (unsigned int) - (512 * s->sectorcounts[chunk])); - if (ret < 0) { - return ret; - } - break; - case 1: /* copy */ - ret = bdrv_pread(bs->file, s->offsets[chunk], - s->uncompressed_chunk, s->lengths[chunk]); - if (ret != s->lengths[chunk]) { - return -1; - } - break; - case 2: /* zero */ - /* see dmg_read, it is treated specially. No buffer needs to be - * pre-filled, the zeroes can be set directly. */ + s->zstream.next_in = s->compressed_chunk; + s->zstream.avail_in = s->lengths[chunk]; + s->zstream.next_out = s->uncompressed_chunk; + s->zstream.avail_out = 512 * s->sectorcounts[chunk]; + ret = inflateReset(&s->zstream); + if (ret != Z_OK) { + return -1; + } + ret = inflate(&s->zstream, Z_FINISH); + if (ret != Z_STREAM_END || + s->zstream.total_out != 512 * s->sectorcounts[chunk]) { + return -1; + } + break; } + case 0x80000006: /* bzip2 compressed */ + if (!dmg_uncompress_bz2) { break; } - s->current_chunk = chunk; + /* we need to buffer, because only the chunk as whole can be + * inflated. */ + ret = bdrv_pread(bs->file, s->offsets[chunk], + s->compressed_chunk, s->lengths[chunk]); + if (ret != s->lengths[chunk]) { + return -1; + } + + ret = dmg_uncompress_bz2((char *)s->compressed_chunk, + (unsigned int) s->lengths[chunk], + (char *)s->uncompressed_chunk, + (unsigned int) + (512 * s->sectorcounts[chunk])); + if (ret < 0) { + return ret; + } + break; + case 1: /* copy */ + ret = bdrv_pread(bs->file, s->offsets[chunk], + s->uncompressed_chunk, s->lengths[chunk]); + if (ret != s->lengths[chunk]) { + return -1; + } + break; + case 2: /* zero */ + /* see dmg_read, it is treated specially. No buffer needs to be + * pre-filled, the zeroes can be set directly. */ + break; } + s->current_chunk = chunk; + return 0; } @@ -661,6 +689,7 @@ dmg_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, uint64_t sector_num = offset >> BDRV_SECTOR_BITS; int nb_sectors = bytes >> BDRV_SECTOR_BITS; int ret, i; + DMGReadState *drs = s->drs; assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); @@ -671,7 +700,7 @@ dmg_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, uint32_t sector_offset_in_chunk; void *data; - if (dmg_read_chunk(bs, sector_num + i) != 0) { + if (dmg_read_chunk(bs, sector_num + i, drs) != 0) { ret = -EIO; goto fail; }