From patchwork Thu Apr 27 08:06:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ashijeet Acharya X-Patchwork-Id: 9702491 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F18F0603F7 for ; Thu, 27 Apr 2017 08:12:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E2043268AE for ; Thu, 27 Apr 2017 08:12:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D3530285EE; Thu, 27 Apr 2017 08:12:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 39365268AE for ; Thu, 27 Apr 2017 08:12:52 +0000 (UTC) Received: from localhost ([::1]:59323 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d3eXj-0000Bi-GL for patchwork-qemu-devel@patchwork.kernel.org; Thu, 27 Apr 2017 04:12:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56430) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d3eRP-0003Kb-1S for qemu-devel@nongnu.org; Thu, 27 Apr 2017 04:06:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d3eRN-0008Ih-Bd for qemu-devel@nongnu.org; Thu, 27 Apr 2017 04:06:19 -0400 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:36596) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1d3eRN-0008IH-3i; Thu, 27 Apr 2017 04:06:17 -0400 Received: by mail-pf0-x242.google.com with SMTP id v14so7446110pfd.3; Thu, 27 Apr 2017 01:06:17 -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=ygC6I0sIqx8FBJtUh03LV3FpDHCP+pBT7gRt6bQYFhw=; b=WZZXaH8GK//bHF8cgFBJKURiTpH/RWH7nwwsgwEUlxz+eTx+2IU2XXspGNcQvzAUXP MTiYu2w0JH68x+QcE4Nnp/5vf9KIzVxwLz6Rk49UdrXA/iY9x+7Xny9T7ozNcxCv7Oun nXV60sEq/qG2jX4/HrusjLd3Kzacqf78/OLYu3a7Yc0JtwwEF18U9ENN0zarfrDuPF5s n5ZfWDqBPAt3l74fEAgTMe8JgShUC7MQF0AjKd7Zha4EjiAu4/wbmWWR6aZM9bdDxjWT mbxRkOn516mh8PtsUHGKRPd6gD37d5mt2vMRea9ONZgfAQf6m9jaKA67TOe4iA9sv3Oz xApg== 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=ygC6I0sIqx8FBJtUh03LV3FpDHCP+pBT7gRt6bQYFhw=; b=NU8QCu+KROLQDQ8HAkNY2EtHHjuyUyBwAk+A9/lIo2l/ZAyQg/XVdi9JcGkEi9HqZu PHsShmbnRlGypqCW1uXKXH+A451NEGfg919Z/W2Rg5gnlBLEjg6YVgNZLJRfC6wtmpjb XnlpuGT44CehVacJOpXCbAbTaWdGKT/xgBQ3V1aNZPotc6sto1Rp3/CfgsKnroAmOmnx PBje7BLZ7bSPuYm7cozDlMvAEc9imd70xTR+Xhk6d+f3xMmtwE5mXiZvrPJ59NNjubmm 5Xq8ivgsHa9CbT0DPCy4wK2vedAzC4tLvY1w/KmsX9vYRUfWN6anQ+27XrXvGAI7KSV1 cCyw== X-Gm-Message-State: AN3rC/5oKRT8qt27njZhEWBt+oIVAKkncB17ibwxT+5X3g4UmJ7xx1BJ TBfRvh7XR4+p0QFD X-Received: by 10.84.214.22 with SMTP id h22mr5458846pli.96.1493280376243; Thu, 27 Apr 2017 01:06:16 -0700 (PDT) Received: from linux.local ([157.51.104.251]) by smtp.gmail.com with ESMTPSA id 12sm3295277pgb.35.2017.04.27.01.06.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 27 Apr 2017 01:06:15 -0700 (PDT) From: Ashijeet Acharya To: stefanha@gmail.com Date: Thu, 27 Apr 2017 13:36:33 +0530 Message-Id: <1493280397-9622-4-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1493280397-9622-1-git-send-email-ashijeetacharya@gmail.com> References: <1493280397-9622-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::242 Subject: [Qemu-devel] [PATCH v2 3/7] 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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. Also, rename DMG_SECTORCOUNTS_MAX to DMG_SECTOR_MAX to avoid indentaion problems at some places inside dmg_read_chunk() Signed-off-by: Ashijeet Acharya --- block/dmg.c | 159 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 94 insertions(+), 65 deletions(-) diff --git a/block/dmg.c b/block/dmg.c index c6fe8b0..32623e2 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -38,7 +38,7 @@ enum { * or truncating when converting to 32-bit types */ DMG_LENGTHS_MAX = 64 * 1024 * 1024, /* 64 MB */ - DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512, + DMG_SECTOR_MAX = DMG_LENGTHS_MAX / 512, }; static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename) @@ -260,10 +260,10 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, /* all-zeroes sector (type 2) does not need to be "uncompressed" and can * therefore be unbounded. */ - if (s->types[i] != 2 && s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) { + if (s->types[i] != 2 && s->sectorcounts[i] > DMG_SECTOR_MAX) { error_report("sector count %" PRIu64 " for chunk %" PRIu32 " is larger than max (%u)", - s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX); + s->sectorcounts[i], i, DMG_SECTOR_MAX); ret = -EINVAL; goto fail; } @@ -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; }