From nobody Wed May 1 22:51:30 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 1490440801346396.71667349903885; Sat, 25 Mar 2017 04:20:01 -0700 (PDT) Received: from localhost ([::1]:36733 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjjj-0002AC-UG for importer@patchew.org; Sat, 25 Mar 2017 07:19:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35096) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crji3-000158-Ow for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1crji2-0000ny-SZ for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:15 -0400 Received: from mail-pf0-x243.google.com ([2607:f8b0:400e:c00::243]:36351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1crji2-0000nk-OL; Sat, 25 Mar 2017 07:18:14 -0400 Received: by mail-pf0-x243.google.com with SMTP id r137so2246959pfr.3; Sat, 25 Mar 2017 04:18:14 -0700 (PDT) Received: from linux.local ([27.251.197.196]) by smtp.gmail.com with ESMTPSA id p189sm9952620pfb.128.2017.03.25.04.18.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 25 Mar 2017 04:18: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=m5yLX96dRycwNS98RwieSaA0rh2xKlghZOtXQhBx/jM=; b=etqOCoF96CJxX/PutMEt47QLcYlzvKQmdUH0OXC4Cxu+o7rRK2ozc18722TvhyOhCb 6+nkL9lqHP+ncgupNB+xgCsi72jqojarE76FZXSd8XyJwP1iyGns1aCiFkuB/NbjQYxg /XNGoczE5/x/OhtNxzJ7rme5EOhLqHNBVKSwCgUIJD5pRiXLrKCQIU08ed3kj5JTjFaJ v1Npz7ybh5FvohpPF/c1XPRAfthajohMmRsZBfD3Aj0kx0EBPzU1w/OK2hm3ZkgTEEnn va+6F1DHjb8NxjOHTZUvR0uGu4N/5nJj4qpge8OYQ7m6mENTqS9MDH5Cg9tHL77xaitr wIUQ== 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=m5yLX96dRycwNS98RwieSaA0rh2xKlghZOtXQhBx/jM=; b=bzc/ncs53w9ZI6Rrf+S9zTtB5GKLjwrLYzLyZvgcb/B8xfuSmU5Xuhi4BIIT5VSlyY hCTNT32OTJ3bftszB/gtE8ynAEc0g79yeKxhLU28bBIs6CvF0loWvimNQeIhtL1dGotM vnCLIjSQCji28y6XVLed2prHrq/eXLaXguOdeGduvdN85qa+ICznkSm7YmhkMVJNfqKn XvtDzEX5r4nt3K+XJzxJjrgfW55tBQwcyWc9NDKHEHcAU2j7Kkh7uqyjb0CZrI7ZKtcF aljllGNoX/Mf5CmB1/Tm93/hNrofLAg0b/CbdwJq2M3RiGw2Sw22KMe/qJJCciSa4Mms D7cA== X-Gm-Message-State: AFeK/H11S8dtxFlMiV6Gb+cYx2x6vz1aLesbow6z618HHWY+oX66AC8/oMmLqLQqOJyZSw== X-Received: by 10.99.8.194 with SMTP id 185mr13930302pgi.37.1490440694023; Sat, 25 Mar 2017 04:18:14 -0700 (PDT) From: Ashijeet Acharya To: famz@redhat.com Date: Sat, 25 Mar 2017 16:48:15 +0530 Message-Id: <1490440701-12037-2-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> References: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c00::243 Subject: [Qemu-devel] [PATCH v2 1/7] vmdk: Refactor and introduce new helper functions 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, qemu-block@nongnu.org, stefanha@gmail.com, qemu-devel@nongnu.org, mreitz@redhat.com, Ashijeet Acharya , jsnow@redhat.com 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" Move the existing vmdk_find_offset_in_cluster() function to the top of the driver. Also, introduce a new helper function size_to_clusters() which returns the number of clusters for a given size in bytes. Here, we leave the last cluster as we need to perform COW for that one. Signed-off-by: Ashijeet Acharya --- block/vmdk.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index a9bd22b..7795c5f 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -242,6 +242,26 @@ static void vmdk_free_last_extent(BlockDriverState *bs) s->extents =3D g_renew(VmdkExtent, s->extents, s->num_extents); } =20 +static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent, + int64_t offset) +{ + uint64_t extent_begin_offset, extent_relative_offset; + uint64_t cluster_size =3D extent->cluster_sectors * BDRV_SECTOR_SIZE; + + extent_begin_offset =3D + (extent->end_sector - extent->sectors) * BDRV_SECTOR_SIZE; + extent_relative_offset =3D offset - extent_begin_offset; + return extent_relative_offset % cluster_size; +} + +static inline uint64_t size_to_clusters(VmdkExtent *extent, uint64_t size) +{ + uint64_t cluster_size, round_off_size; + cluster_size =3D extent->cluster_sectors * BDRV_SECTOR_SIZE; + round_off_size =3D cluster_size - (size % cluster_size); + return ((size + round_off_size) >> 16) - 1; +} + static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent) { char *desc; @@ -1266,18 +1286,6 @@ static VmdkExtent *find_extent(BDRVVmdkState *s, return NULL; } =20 -static inline uint64_t vmdk_find_offset_in_cluster(VmdkExtent *extent, - int64_t offset) -{ - uint64_t extent_begin_offset, extent_relative_offset; - uint64_t cluster_size =3D extent->cluster_sectors * BDRV_SECTOR_SIZE; - - extent_begin_offset =3D - (extent->end_sector - extent->sectors) * BDRV_SECTOR_SIZE; - extent_relative_offset =3D offset - extent_begin_offset; - return extent_relative_offset % cluster_size; -} - static inline uint64_t vmdk_find_index_in_cluster(VmdkExtent *extent, int64_t sector_num) { --=20 2.6.2 From nobody Wed May 1 22:51:30 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 1490440953785412.7595599612539; Sat, 25 Mar 2017 04:22:33 -0700 (PDT) Received: from localhost ([::1]:36750 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjmB-0004If-Ju for importer@patchew.org; Sat, 25 Mar 2017 07:22:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35140) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjiA-0001AK-H6 for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1crji7-0000p6-Ek for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:22 -0400 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]:36219) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1crji7-0000p0-9D; Sat, 25 Mar 2017 07:18:19 -0400 Received: by mail-pg0-x242.google.com with SMTP id 81so2544345pgh.3; Sat, 25 Mar 2017 04:18:19 -0700 (PDT) Received: from linux.local ([27.251.197.196]) by smtp.gmail.com with ESMTPSA id p189sm9952620pfb.128.2017.03.25.04.18.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 25 Mar 2017 04:18: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=xmAvbiK6IHDtP0hifSMWIuAskjnZ1ZW/lZfePpBbvOY=; b=MaqTKBbLJRFz5Lr3IGh4M/3u+dqvUoujnaRlrnsw4/igXOV+9IWCozurXZUY9zw8tl +qjPFZjavOaUN633e3jxB+Av6HPggp5ojNMJzo5i0VQEhbRqFggHM8iQSu/6JB3n3VvU r1REPi3dHvvP2ZukEad0fXojCmTw2JezQZz2bURcO+cdRtRimKHDunXrqLyHK37C2J+S H8AnSPS26YH8+hS6qnnbr1ZlUYgW8vaWKtu82FgMUfkb9xsdjuixb+8AIS3Uo591luN3 JJa/D0dgrbm4/8ikh1VW0eRMHFw9O1bPVtkyqKV3gR2WobVlPjOMVcLsnfjjt9IxBTBd 0SWA== 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=xmAvbiK6IHDtP0hifSMWIuAskjnZ1ZW/lZfePpBbvOY=; b=nvb/BRnxSRAD6Xr6hw4L4SbEZZ3Q7/RMU8yh71WgsGhId6n0fHMeskog0PDZzXNrwG AStxJh8Uk6hzvSTZjpRHOobNOFRjbhqWFMvwf68miaonsCpVy83P3FKwG9t7b9tMaky5 LAQkaQlSrv/WVoKWUxXrorPGTWI8K3WwqbXK/lBNv7CAFDwscjhv5sAm3ceCojF3+VFF Cs9aLCeWeT2+eugaMdDRzYCrktCcxt0bVogr5KcDMogxWavTU6P8a4dcNSPk494YNXwa R28lCWFAKmCsnFwLuklr+NtWSfHE4neYiPhT0pgz7REgetqyJlB442ql2NXV8b20CXnl OpJQ== X-Gm-Message-State: AFeK/H1MmDczBEbPMwkW1F1LCPXmW7HavL22ExllwSFwZ1ArFA5OADbke0q2GW/Qpmo1+Q== X-Received: by 10.98.55.66 with SMTP id e63mr15026691pfa.100.1490440698371; Sat, 25 Mar 2017 04:18:18 -0700 (PDT) From: Ashijeet Acharya To: famz@redhat.com Date: Sat, 25 Mar 2017 16:48:16 +0530 Message-Id: <1490440701-12037-3-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> References: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c05::242 Subject: [Qemu-devel] [PATCH v2 2/7] vmdk: Rename get_whole_cluster() to vmdk_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: kwolf@redhat.com, qemu-block@nongnu.org, stefanha@gmail.com, qemu-devel@nongnu.org, mreitz@redhat.com, Ashijeet Acharya , jsnow@redhat.com 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" Rename the existing function get_whole_cluster() to vmdk_perform_cow() as its sole purpose is to perform COW for the first and the last allocated clusters if needed. Signed-off-by: Ashijeet Acharya --- block/vmdk.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 7795c5f..f5fda2c 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1036,8 +1036,8 @@ static void vmdk_refresh_limits(BlockDriverState *bs,= Error **errp) } } =20 -/** - * get_whole_cluster +/* + * vmdk_perform_cow * * Copy backing file's cluster that covers @sector_num, otherwise write ze= ro, * to the cluster at @cluster_sector_num. @@ -1045,13 +1045,18 @@ static void vmdk_refresh_limits(BlockDriverState *b= s, Error **errp) * If @skip_start_sector < @skip_end_sector, the relative range * [@skip_start_sector, @skip_end_sector) is not copied or written, and le= ave * it for call to write user data in the request. + * + * Returns: + * VMDK_OK: on success + * + * VMDK_ERROR: in error cases */ -static int get_whole_cluster(BlockDriverState *bs, - VmdkExtent *extent, - uint64_t cluster_offset, - uint64_t offset, - uint64_t skip_start_bytes, - uint64_t skip_end_bytes) +static int vmdk_perform_cow(BlockDriverState *bs, + VmdkExtent *extent, + uint64_t cluster_offset, + uint64_t offset, + uint64_t skip_start_bytes, + uint64_t skip_end_bytes) { int ret =3D VMDK_OK; int64_t cluster_bytes; --=20 2.6.2 From nobody Wed May 1 22:51:30 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 1490440815640507.81636262481504; Sat, 25 Mar 2017 04:20:15 -0700 (PDT) Received: from localhost ([::1]:36734 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjjy-0002M2-Fm for importer@patchew.org; Sat, 25 Mar 2017 07:20:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35176) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjiF-0001CU-01 for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1crjiD-0000q8-W1 for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:27 -0400 Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]:35496) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1crjiD-0000pn-Pp; Sat, 25 Mar 2017 07:18:25 -0400 Received: by mail-pg0-x241.google.com with SMTP id g2so2552124pge.2; Sat, 25 Mar 2017 04:18:25 -0700 (PDT) Received: from linux.local ([27.251.197.196]) by smtp.gmail.com with ESMTPSA id p189sm9952620pfb.128.2017.03.25.04.18.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 25 Mar 2017 04:18:24 -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=e1yCXwtD3/vYsb3zxKicRIvBtcSq4yunTLXhi9NQPio=; b=OCaEPZhKRaoPoQj90HazS92T35EjC49x6bWxfrwJEk86iHxumcSdihe+n1tCPJS0kJ QUaWg24s2eDrIAFR85a8vaKI5LdIPgPeB0PNUj6T0hj4gGDsu7kylUNqUYHMeMygZESZ kHQ7/za8q5bXaSgmGTh30VlAED+bms+ALav5Lv+4MKVwrGtYGyx+D1R52LvgC79DhyPK QrWlxVByAq2HTAAx96Fp2pQew+GFvxF/9n56j1ukYOgYNvXlKBHH14IGzt7mFF3Rv7I3 tAvmCJh2L2/tWdC5ei2pIl5S34GudxbuyzVC2Lne22Rn60erQEa6cRIl4xEeXM1/pRMA jPRA== 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=e1yCXwtD3/vYsb3zxKicRIvBtcSq4yunTLXhi9NQPio=; b=Lji9uAHEaFSZm62gBskbDEqhxb509xS8029lA0j1yOP78lsTfHOXVz+d0uSuCa6Xqq bwFKw6FicMs+fHOURDKZOgqOw0t0WRUjkESZnLlJlX4ckvJz/SeKaXF4mu2ftm5JSEa6 DECtwAZPePFTcy5LhQvTGbrSSJ3rXGBaYrlW3H7yDB3Fu5Ah9tmH6ZdMlGQdqHsIpZ/V DjEV2bYPwsSF0HWx3/YelAZLYXrplyj8y88/b2JFwG+WX/7Bvvfon02yDlP+GXcq225E j93TYG26hJQzBje0bHYUkmqDgeoavZSFgsOpHj24O0ylNGp91lOR7bfgb8Z8fepzp+gh WD3w== X-Gm-Message-State: AFeK/H21R1vI4fzux6yrBy3nHI+ndQjJSeZLKTLMDMFAezVH4HTibGd5G95GFnfhURv5Gg== X-Received: by 10.98.96.65 with SMTP id u62mr14809184pfb.219.1490440704904; Sat, 25 Mar 2017 04:18:24 -0700 (PDT) From: Ashijeet Acharya To: famz@redhat.com Date: Sat, 25 Mar 2017 16:48:17 +0530 Message-Id: <1490440701-12037-4-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> References: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c05::241 Subject: [Qemu-devel] [PATCH v2 3/7] vmdk: Factor out metadata loading code out of get_cluster_offset() 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, qemu-block@nongnu.org, stefanha@gmail.com, qemu-devel@nongnu.org, mreitz@redhat.com, Ashijeet Acharya , jsnow@redhat.com 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" Move the cluster tables loading code out of the existing get_cluster_offset() function and implement it in separate get_cluster_table() and vmdk_L2load() functions. This patch will help us avoid code duplication in future patches of this series. Signed-off-by: Ashijeet Acharya --- block/vmdk.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 99 insertions(+) diff --git a/block/vmdk.c b/block/vmdk.c index f5fda2c..a42322e 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1037,6 +1037,105 @@ static void vmdk_refresh_limits(BlockDriverState *b= s, Error **errp) } =20 /* + * vmdk_L2load + * + * Loads a new L2 table into memory. If the table is in the cache, the cac= he + * is used; otherwise the L2 table is loaded from the image file. + * + * Returns: + * VMDK_OK: on success + * VMDK_ERROR: in error cases + */ +static int vmdk_L2load(VmdkExtent *extent, uint64_t offset, int l2_offset, + uint32_t **new_l2_table, int *new_l2_index) +{ + int min_index, i, j; + uint32_t *l2_table; + uint32_t min_count; + + for (i =3D 0; i < L2_CACHE_SIZE; i++) { + if (l2_offset =3D=3D extent->l2_cache_offsets[i]) { + /* increment the hit count */ + if (++extent->l2_cache_counts[i] =3D=3D 0xffffffff) { + for (j =3D 0; j < L2_CACHE_SIZE; j++) { + extent->l2_cache_counts[j] >>=3D 1; + } + } + l2_table =3D extent->l2_cache + (i * extent->l2_size); + goto found; + } + } + /* not found: load a new entry in the least used one */ + min_index =3D 0; + min_count =3D 0xffffffff; + for (i =3D 0; i < L2_CACHE_SIZE; i++) { + if (extent->l2_cache_counts[i] < min_count) { + min_count =3D extent->l2_cache_counts[i]; + min_index =3D i; + } + } + l2_table =3D extent->l2_cache + (min_index * extent->l2_size); + if (bdrv_pread(extent->file, + (int64_t)l2_offset * 512, + l2_table, + extent->l2_size * sizeof(uint32_t) + ) !=3D extent->l2_size * sizeof(uint32_t)) { + return VMDK_ERROR; + } + + extent->l2_cache_offsets[min_index] =3D l2_offset; + extent->l2_cache_counts[min_index] =3D 1; +found: + *new_l2_index =3D ((offset >> 9) / extent->cluster_sectors) % extent->= l2_size; + *new_l2_table =3D l2_table; + + return VMDK_OK; +} + +/* + * get_cluster_table + * + * for a given offset, load (and allocate if needed) the l2 table. + * + * Returns: + * VMDK_OK: on success + * + * VMDK_UNALLOC: if cluster is not mapped + * + * VMDK_ERROR: in error cases + */ +static int get_cluster_table(VmdkExtent *extent, uint64_t offset, + int *new_l1_index, int *new_l2_offset, + int *new_l2_index, uint32_t **new_l2_table) +{ + int l1_index, l2_offset, l2_index; + uint32_t *l2_table; + int ret; + + offset -=3D (extent->end_sector - extent->sectors) * SECTOR_SIZE; + l1_index =3D (offset >> 9) / extent->l1_entry_sectors; + if (l1_index >=3D extent->l1_size) { + return VMDK_ERROR; + } + l2_offset =3D extent->l1_table[l1_index]; + if (!l2_offset) { + return VMDK_UNALLOC; + } + + ret =3D vmdk_L2load(extent, offset, l2_offset, &l2_table, &l2_index); + if (ret < 0) { + return ret; + } + + *new_l1_index =3D l1_index; + *new_l2_offset =3D l2_offset; + *new_l2_index =3D l2_index; + *new_l2_table =3D l2_table; + + return VMDK_OK; +} + +/* * vmdk_perform_cow * * Copy backing file's cluster that covers @sector_num, otherwise write ze= ro, --=20 2.6.2 From nobody Wed May 1 22:51:30 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 1490440834360691.3215735079965; Sat, 25 Mar 2017 04:20:34 -0700 (PDT) Received: from localhost ([::1]:36740 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjkH-0002bJ-48 for importer@patchew.org; Sat, 25 Mar 2017 07:20:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35206) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjiJ-0001Hh-Cu for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1crjiI-0000r3-0a for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:31 -0400 Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]:34564) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1crjiH-0000qw-OM; Sat, 25 Mar 2017 07:18:29 -0400 Received: by mail-pg0-x241.google.com with SMTP id w20so2563701pgc.1; Sat, 25 Mar 2017 04:18:29 -0700 (PDT) Received: from linux.local ([27.251.197.196]) by smtp.gmail.com with ESMTPSA id p189sm9952620pfb.128.2017.03.25.04.18.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 25 Mar 2017 04:18:28 -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=1aemnwh64PNofCEXHxmUSKcurDJt++aH6t2t8xwe1BA=; b=o8zzGubU8wJgwSrebKW7zoBNg+hO6/QzNQVcK1Ww+omj7kVBVp8lV0KIfS6PqBCTGq nRcnpH//EfOFXJwQdCdSTf5cdQsT7sgYnxFSHri5cds4EzCHG4cj0XbKB2/ba/BJNZr/ VZ8+1ucRX17+uC+9r/3DtKy7I4VAlkZkVJmZPGFeXr0hNnoDajdrnhTNdGzEzmH8mLxr IPP6WX2+sFozXzhvhTt4vN48BtdAOiy9VWT6NjUg5mDvQreqMpu3ZChKmvI3X39mNFTg DMyeLod/HIAzUOEF46NsJPF6du57HHQnBKhLuux+3V4+MqMjFA5VeJeGgdV3eYIRe0Gk l1cg== 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=1aemnwh64PNofCEXHxmUSKcurDJt++aH6t2t8xwe1BA=; b=RNE6VV+Tl1Tc7/G7qYUvyedK3wp74Ds6ggfkBl/ZF6sisCq+dI+GO40fGGspB0zTxY 9SiX4hLSFhKNAO8Hl5uOJWRg55WTFS4kB4WOyHq1tzUPfBTN1/2/wzqDJRdMUdcet4Hs YtvAcOmbuPcJ4k/lvVkKpiYdLQdyOGRFB32N7RjzJAef/woCt4ReZn0pehFzUAlLJsDK L8hCjAUnh/cjvLsYx3Km/e8/R1wLe0g1eBuRzT1mdlE0d1ZUptNK/z1WREIVg9tCFyn0 wcf7QeavPFCEfrGqZEHqPAFnJBPdX52gkQ6Cgj/2NPi8Pb55xnSia1SOTcfhE/TkGZw9 GiwQ== X-Gm-Message-State: AFeK/H1RhOh+1S1CNvC8FPHLV3ptm8/d//1D9KaYaOKhy3b3CkaLWSbaC9kmPhATm+qOyw== X-Received: by 10.98.108.196 with SMTP id h187mr14750087pfc.233.1490440708886; Sat, 25 Mar 2017 04:18:28 -0700 (PDT) From: Ashijeet Acharya To: famz@redhat.com Date: Sat, 25 Mar 2017 16:48:18 +0530 Message-Id: <1490440701-12037-5-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> References: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c05::241 Subject: [Qemu-devel] [PATCH v2 4/7] vmdk: New functions to allocate multiple clusters and cluster offset 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, qemu-block@nongnu.org, stefanha@gmail.com, qemu-devel@nongnu.org, mreitz@redhat.com, Ashijeet Acharya , jsnow@redhat.com 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" Introduce two new helper functions handle_alloc() and vmdk_alloc_cluster_offset(). handle_alloc() helps to allocate multiple clusters at once starting from a given offset on disk and performs COW if necessary for first and last allocated clusters. vmdk_alloc_cluster_offset() helps to return the offset of the first of the many newly allocated clusters. Also, provide proper documentation for both. Signed-off-by: Ashijeet Acharya --- block/vmdk.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++--= ---- 1 file changed, 187 insertions(+), 19 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index a42322e..5a95929 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -136,6 +136,7 @@ typedef struct VmdkMetaData { unsigned int l2_offset; int valid; uint32_t *l2_cache_entry; + uint32_t nb_clusters; } VmdkMetaData; =20 typedef struct VmdkGrainMarker { @@ -1036,6 +1037,34 @@ static void vmdk_refresh_limits(BlockDriverState *bs= , Error **errp) } } =20 +static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, + uint32_t offset) +{ + offset =3D cpu_to_le32(offset); + /* update L2 table */ + if (bdrv_pwrite_sync(extent->file, + ((int64_t)m_data->l2_offset * 512) + + (m_data->l2_index * sizeof(offset)), + &offset, sizeof(offset)) < 0) { + return VMDK_ERROR; + } + /* update backup L2 table */ + if (extent->l1_backup_table_offset !=3D 0) { + m_data->l2_offset =3D extent->l1_backup_table[m_data->l1_index]; + if (bdrv_pwrite_sync(extent->file, + ((int64_t)m_data->l2_offset * 512) + + (m_data->l2_index * sizeof(offset)), + &offset, sizeof(offset)) < 0) { + return VMDK_ERROR; + } + } + if (m_data->l2_cache_entry) { + *m_data->l2_cache_entry =3D offset; + } + + return VMDK_OK; +} + /* * vmdk_L2load * @@ -1222,29 +1251,168 @@ exit: return ret; } =20 -static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, - uint32_t offset) +/* + * handle_alloc + * + * Allocates new clusters for an area that either is yet unallocated or ne= eds a + * copy on write. If *cluster_offset is non_zero, clusters are only alloca= ted if + * the new allocation can match the specified host offset. + * + * Returns: + * VMDK_OK: if new clusters were allocated, *bytes may be decrease= d if + * the new allocation doesn't cover all of the requested = area. + * *cluster_offset is updated to contain the offset of the + * first newly allocated cluster. + * + * VMDK_UNALLOC: if no clusters could be allocated. *cluster_offset is = left + * unchanged. + * + * VMDK_ERROR: in error cases + */ +static int handle_alloc(BlockDriverState *bs, VmdkExtent *extent, + uint64_t offset, uint64_t *cluster_offset, + int64_t *bytes, VmdkMetaData *m_data, + bool allocate, uint32_t *total_alloc_clusters) { - offset =3D cpu_to_le32(offset); - /* update L2 table */ - if (bdrv_pwrite_sync(extent->file, - ((int64_t)m_data->l2_offset * 512) - + (m_data->l2_index * sizeof(offset)), - &offset, sizeof(offset)) < 0) { - return VMDK_ERROR; + int l1_index, l2_offset, l2_index; + uint32_t *l2_table; + uint32_t cluster_sector; + uint32_t nb_clusters; + bool zeroed =3D false; + uint64_t skip_start_bytes, skip_end_bytes; + int ret; + + ret =3D get_cluster_table(extent, offset, &l1_index, &l2_offset, + &l2_index, &l2_table); + if (ret < 0) { + return ret; } - /* update backup L2 table */ - if (extent->l1_backup_table_offset !=3D 0) { - m_data->l2_offset =3D extent->l1_backup_table[m_data->l1_index]; - if (bdrv_pwrite_sync(extent->file, - ((int64_t)m_data->l2_offset * 512) - + (m_data->l2_index * sizeof(offset)), - &offset, sizeof(offset)) < 0) { - return VMDK_ERROR; + + cluster_sector =3D le32_to_cpu(l2_table[l2_index]); + + skip_start_bytes =3D vmdk_find_offset_in_cluster(extent, offset); + /* Calculate the number of clusters to look for. Here it will return o= ne + * cluster less than the actual value calculated as we may need to per= from + * COW for the last one. */ + nb_clusters =3D size_to_clusters(extent, skip_start_bytes + *bytes); + + nb_clusters =3D MIN(nb_clusters, extent->l2_size - l2_index); + assert(nb_clusters <=3D INT_MAX); + + /* update bytes according to final nb_clusters value */ + if (nb_clusters !=3D 0) { + *bytes =3D ((nb_clusters * extent->cluster_sectors) << 9) + - skip_start_bytes; + } else { + nb_clusters =3D 1; + } + *total_alloc_clusters +=3D nb_clusters; + skip_end_bytes =3D skip_start_bytes + MIN(*bytes, + extent->cluster_sectors * BDRV_SECTOR_SIZE + - skip_start_bytes); + + if (extent->has_zero_grain && cluster_sector =3D=3D VMDK_GTE_ZEROED) { + zeroed =3D true; + } + + if (!cluster_sector || zeroed) { + if (!allocate) { + return zeroed ? VMDK_ZEROED : VMDK_UNALLOC; + } + + cluster_sector =3D extent->next_cluster_sector; + extent->next_cluster_sector +=3D extent->cluster_sectors + * nb_clusters; + + ret =3D vmdk_perform_cow(bs, extent, cluster_sector * BDRV_SECTOR_= SIZE, + offset, skip_start_bytes, + skip_end_bytes); + if (ret < 0) { + return ret; + } + if (m_data) { + m_data->valid =3D 1; + m_data->l1_index =3D l1_index; + m_data->l2_index =3D l2_index; + m_data->l2_offset =3D l2_offset; + m_data->l2_cache_entry =3D &l2_table[l2_index]; + m_data->nb_clusters =3D nb_clusters; } } - if (m_data->l2_cache_entry) { - *m_data->l2_cache_entry =3D offset; + *cluster_offset =3D cluster_sector << BDRV_SECTOR_BITS; + return VMDK_OK; +} + +/* + * vmdk_alloc_cluster_offset + * + * For a given offset on the virtual disk, find the cluster offset in vmdk + * file. If the offset is not found, allocate a new cluster. + * + * If the cluster is newly allocated, m_data->nb_clusters is set to the nu= mber + * of contiguous clusters that have been allocated. In this case, the other + * fields of m_data are valid and contain information about the first allo= cated + * cluster. + * + * Returns: + * + * VMDK_OK: on success and @cluster_offset was set + * + * VMDK_UNALLOC: if no clusters were allocated and @cluster_offset = is + * set to zero + * + * VMDK_ERROR: in error cases + */ +static int vmdk_alloc_cluster_offset(BlockDriverState *bs, + VmdkExtent *extent, + VmdkMetaData *m_data, uint64_t offset, + bool allocate, uint64_t *cluster_offs= et, + int64_t bytes, + uint32_t *total_alloc_clusters) +{ + uint64_t start, remaining; + uint64_t new_cluster_offset; + int64_t n_bytes; + int ret; + + if (extent->flat) { + *cluster_offset =3D extent->flat_start_offset; + return VMDK_OK; + } + + start =3D offset; + remaining =3D bytes; + new_cluster_offset =3D 0; + *cluster_offset =3D 0; + n_bytes =3D 0; + if (m_data) { + m_data->valid =3D 0; + } + + /* due to L2 table margins all bytes may not get allocated at once */ + while (true) { + + if (!*cluster_offset) { + *cluster_offset =3D new_cluster_offset; + } + + start +=3D n_bytes; + remaining -=3D n_bytes; + new_cluster_offset +=3D n_bytes; + + if (remaining =3D=3D 0) { + break; + } + + n_bytes =3D remaining; + + ret =3D handle_alloc(bs, extent, start, &new_cluster_offset, &n_by= tes, + m_data, allocate, total_alloc_clusters); + + if (ret < 0) { + return ret; + + } } =20 return VMDK_OK; --=20 2.6.2 From nobody Wed May 1 22:51:30 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 149044099583626.719079444310182; Sat, 25 Mar 2017 04:23:15 -0700 (PDT) Received: from localhost ([::1]:36753 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjms-0004pv-J4 for importer@patchew.org; Sat, 25 Mar 2017 07:23:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35234) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjiN-0001Mn-Uu for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1crjiM-0000s2-GR for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:35 -0400 Received: from mail-pg0-x243.google.com ([2607:f8b0:400e:c05::243]:35506) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1crjiM-0000rk-7o; Sat, 25 Mar 2017 07:18:34 -0400 Received: by mail-pg0-x243.google.com with SMTP id g2so2552457pge.2; Sat, 25 Mar 2017 04:18:34 -0700 (PDT) Received: from linux.local ([27.251.197.196]) by smtp.gmail.com with ESMTPSA id p189sm9952620pfb.128.2017.03.25.04.18.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 25 Mar 2017 04:18:32 -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=2wGCm9WbUnZQr8S2AJIS0W79WxLwz23WH3BbpgR+Ln4=; b=aBv2JK+jjzMG2ijUo/a7ywdvUo60CsqI/F7sIsO8/dttQLXAev3sO4t+mejmAwmSCV 0EcBO+kWMHERog9C52ChsDe/HkcbTlvZHcz0QIfiuuk8nQGlxpTVAYmk7vJji4Oek8aO qHR0azdVuJ9QIP92vbqJ4MmMeYf9zRNYMSKF19D578AU7zQ1Pl8ieANREwPnLQXsk8hA 7I2mR5o2Xvee27WMDTSyOA8gTyanI87d6bZsVN2/mTu4Ejqg4Q2JMzd4ZDRz1w9uqUWZ DqDil6vKEqUhCf7NS85EbhtrY7Qx/4J4yRkHXchivi2kMSXS/PwCkrqeHNS+srpWuQLp H9Cw== 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=2wGCm9WbUnZQr8S2AJIS0W79WxLwz23WH3BbpgR+Ln4=; b=Bme+yq1nKOdXf9o0nJCoaeH9WbZ1+obXX+PcIEmzPndgMMlA34motXv84jZbkF/Hxt x0UclxMiruiTeH2dgsAHs8zi6E0aM61zq3QT370ceVXYUgBTIlHwVJUiZ/DHorwzLJBl d0tmaZrKVlcJHXpO0A+urk2PKSozfuwYfSIGLz89H7jdaCOwexv0irXuDBdm93FPB5MW 6u7xpVULJB+EDNyUXCrzVGYTQL1z4KYqhuuSgULbnIZch3SdBgF4fvgZFzwEHfDgwFO6 m7DAdY0GDlQicE2sPDSDaXk81yl+pzrI0gq3Z9UAJXiGC8/BzrjNvG9WNIuHbSvoYaNI rVmQ== X-Gm-Message-State: AFeK/H1WMJOo/tyOsD5hoD9b1Qdh6ZJzU4gLIMGLnJlQGF0An+kL6iSDWtFChQuVn0vEOQ== X-Received: by 10.99.5.133 with SMTP id 127mr14106328pgf.8.1490440713290; Sat, 25 Mar 2017 04:18:33 -0700 (PDT) From: Ashijeet Acharya To: famz@redhat.com Date: Sat, 25 Mar 2017 16:48:19 +0530 Message-Id: <1490440701-12037-6-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> References: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c05::243 Subject: [Qemu-devel] [PATCH v2 5/7] vmdk: Rename get_cluster_offset() to vmdk_get_cluster_offset() 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, qemu-block@nongnu.org, stefanha@gmail.com, qemu-devel@nongnu.org, mreitz@redhat.com, Ashijeet Acharya , jsnow@redhat.com 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" Rename the existing get_cluster_offset() function to vmdk_get_cluster_offset() and have it make use of the new get_cluster_table() to load the cluster tables. Also, it is no longer used to allocate new clusters and hence perform COW. Make the necessary renames at all the occurrences of get_cluster_offset(). Signed-off-by: Ashijeet Acharya --- block/vmdk.c | 117 +++++++++++--------------------------------------------= ---- 1 file changed, 21 insertions(+), 96 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 5a95929..387e45b 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1419,7 +1419,7 @@ static int vmdk_alloc_cluster_offset(BlockDriverState= *bs, } =20 /** - * get_cluster_offset + * vmdk_get_cluster_offset * * Look up cluster offset in extent file by sector number, and store in * @cluster_offset. @@ -1427,84 +1427,34 @@ static int vmdk_alloc_cluster_offset(BlockDriverSta= te *bs, * For flat extents, the start offset as parsed from the description file = is * returned. * - * For sparse extents, look up in L1, L2 table. If allocate is true, retur= n an - * offset for a new cluster and update L2 cache. If there is a backing fil= e, - * COW is done before returning; otherwise, zeroes are written to the allo= cated - * cluster. Both COW and zero writing skips the sector range - * [@skip_start_sector, @skip_end_sector) passed in by caller, because cal= ler - * has new data to write there. + * For sparse extents, look up in L1, L2 table. * * Returns: VMDK_OK if cluster exists and mapped in the image. - * VMDK_UNALLOC if cluster is not mapped and @allocate is false. - * VMDK_ERROR if failed. + * VMDK_UNALLOC if cluster is not mapped. + * VMDK_ERROR if failed */ -static int get_cluster_offset(BlockDriverState *bs, - VmdkExtent *extent, - VmdkMetaData *m_data, - uint64_t offset, - bool allocate, - uint64_t *cluster_offset, - uint64_t skip_start_bytes, - uint64_t skip_end_bytes) +static int vmdk_get_cluster_offset(BlockDriverState *bs, + VmdkExtent *extent, + uint64_t offset, + uint64_t *cluster_offset) { - unsigned int l1_index, l2_offset, l2_index; - int min_index, i, j; - uint32_t min_count, *l2_table; + int l1_index, l2_offset, l2_index; + uint32_t *l2_table; bool zeroed =3D false; int64_t ret; int64_t cluster_sector; =20 - if (m_data) { - m_data->valid =3D 0; - } if (extent->flat) { *cluster_offset =3D extent->flat_start_offset; return VMDK_OK; } =20 - offset -=3D (extent->end_sector - extent->sectors) * SECTOR_SIZE; - l1_index =3D (offset >> 9) / extent->l1_entry_sectors; - if (l1_index >=3D extent->l1_size) { - return VMDK_ERROR; - } - l2_offset =3D extent->l1_table[l1_index]; - if (!l2_offset) { - return VMDK_UNALLOC; - } - for (i =3D 0; i < L2_CACHE_SIZE; i++) { - if (l2_offset =3D=3D extent->l2_cache_offsets[i]) { - /* increment the hit count */ - if (++extent->l2_cache_counts[i] =3D=3D 0xffffffff) { - for (j =3D 0; j < L2_CACHE_SIZE; j++) { - extent->l2_cache_counts[j] >>=3D 1; - } - } - l2_table =3D extent->l2_cache + (i * extent->l2_size); - goto found; - } - } - /* not found: load a new entry in the least used one */ - min_index =3D 0; - min_count =3D 0xffffffff; - for (i =3D 0; i < L2_CACHE_SIZE; i++) { - if (extent->l2_cache_counts[i] < min_count) { - min_count =3D extent->l2_cache_counts[i]; - min_index =3D i; - } - } - l2_table =3D extent->l2_cache + (min_index * extent->l2_size); - if (bdrv_pread(extent->file, - (int64_t)l2_offset * 512, - l2_table, - extent->l2_size * sizeof(uint32_t) - ) !=3D extent->l2_size * sizeof(uint32_t)) { - return VMDK_ERROR; + ret =3D get_cluster_table(extent, offset, &l1_index, &l2_offset, + &l2_index, &l2_table); + if (ret < 0) { + return ret; } =20 - extent->l2_cache_offsets[min_index] =3D l2_offset; - extent->l2_cache_counts[min_index] =3D 1; - found: - l2_index =3D ((offset >> 9) / extent->cluster_sectors) % extent->l2_si= ze; cluster_sector =3D le32_to_cpu(l2_table[l2_index]); =20 if (extent->has_zero_grain && cluster_sector =3D=3D VMDK_GTE_ZEROED) { @@ -1512,31 +1462,9 @@ static int get_cluster_offset(BlockDriverState *bs, } =20 if (!cluster_sector || zeroed) { - if (!allocate) { - return zeroed ? VMDK_ZEROED : VMDK_UNALLOC; - } - - cluster_sector =3D extent->next_cluster_sector; - extent->next_cluster_sector +=3D extent->cluster_sectors; - - /* First of all we write grain itself, to avoid race condition - * that may to corrupt the image. - * This problem may occur because of insufficient space on host di= sk - * or inappropriate VM shutdown. - */ - ret =3D get_whole_cluster(bs, extent, cluster_sector * BDRV_SECTOR= _SIZE, - offset, skip_start_bytes, skip_end_bytes); - if (ret) { - return ret; - } - if (m_data) { - m_data->valid =3D 1; - m_data->l1_index =3D l1_index; - m_data->l2_index =3D l2_index; - m_data->l2_offset =3D l2_offset; - m_data->l2_cache_entry =3D &l2_table[l2_index]; - } + return zeroed ? VMDK_ZEROED : VMDK_UNALLOC; } + *cluster_offset =3D cluster_sector << BDRV_SECTOR_BITS; return VMDK_OK; } @@ -1579,9 +1507,7 @@ static int64_t coroutine_fn vmdk_co_get_block_status(= BlockDriverState *bs, return 0; } qemu_co_mutex_lock(&s->lock); - ret =3D get_cluster_offset(bs, extent, NULL, - sector_num * 512, false, &offset, - 0, 0); + ret =3D vmdk_get_cluster_offset(bs, extent, sector_num * 512, &offset); qemu_co_mutex_unlock(&s->lock); =20 index_in_cluster =3D vmdk_find_index_in_cluster(extent, sector_num); @@ -1772,13 +1698,13 @@ vmdk_co_preadv(BlockDriverState *bs, uint64_t offse= t, uint64_t bytes, ret =3D -EIO; goto fail; } - ret =3D get_cluster_offset(bs, extent, NULL, - offset, false, &cluster_offset, 0, 0); offset_in_cluster =3D vmdk_find_offset_in_cluster(extent, offset); =20 n_bytes =3D MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE - offset_in_cluster); =20 + ret =3D vmdk_get_cluster_offset(bs, extent, offset, &cluster_offse= t); + if (ret !=3D VMDK_OK) { /* if not allocated, try to read from parent image, if exist */ if (bs->backing && ret !=3D VMDK_ZEROED) { @@ -2504,9 +2430,8 @@ static int vmdk_check(BlockDriverState *bs, BdrvCheck= Result *result, sector_num); break; } - ret =3D get_cluster_offset(bs, extent, NULL, - sector_num << BDRV_SECTOR_BITS, - false, &cluster_offset, 0, 0); + ret =3D vmdk_get_cluster_offset(bs, extent, + sector_num << BDRV_SECTOR_BITS, &cluster_offset); if (ret =3D=3D VMDK_ERROR) { fprintf(stderr, "ERROR: could not get cluster_offset for sector %" --=20 2.6.2 From nobody Wed May 1 22:51:30 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 1490440965302461.3740079597495; Sat, 25 Mar 2017 04:22:45 -0700 (PDT) Received: from localhost ([::1]:36751 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjmN-0004SH-V9 for importer@patchew.org; Sat, 25 Mar 2017 07:22:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35264) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjiS-0001Rl-V9 for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1crjiR-0000tw-A8 for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:40 -0400 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:35724) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1crjiR-0000to-4O; Sat, 25 Mar 2017 07:18:39 -0400 Received: by mail-pf0-x242.google.com with SMTP id n11so2250880pfg.2; Sat, 25 Mar 2017 04:18:39 -0700 (PDT) Received: from linux.local ([27.251.197.196]) by smtp.gmail.com with ESMTPSA id p189sm9952620pfb.128.2017.03.25.04.18.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 25 Mar 2017 04:18:37 -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=2GL0B5OQlyf0zt7bwRYKfjjxPQBABmDg3Ytvdkm3J9c=; b=ieGLYeu+ZqDFvzLNnhxrnk5rA5CHJTyXknnfjzPT7SmMsMys0TPCb6LtKDaBTPsytO YGYaSGHSkRdg9y/qDBuw3gHOfVsU1OrP08WN/VCiQ6sOLQaQuGcDtF7DCE2hgXUBitEN MRxAFwEMRg3o8jNOrJvj9+N/n1/G8ORt3CMq3ikW4gUj70M3UTR4mxTHspiMt1KW6IB/ TyFJ0x62o10DKnQLfJCrgKwERVAUnPcC5C+rp4GQRVMrDikQNG/5WKQQ/aohHdfhfVFs 81BbXbJ4TI59e0ZXjUHMP1xq9hToctatbP1n7rLCVwwFHUyBcWo6b2kPtmFHUMfsUX8a lVVA== 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=2GL0B5OQlyf0zt7bwRYKfjjxPQBABmDg3Ytvdkm3J9c=; b=oAHQKJPC+447V8ngSQMs42vDXZf/VZ8Lmporg1YBwWJ2F5Pp555hvm175D2wFIW49x Pn3UHj8KEOOJzr6Fq0WB/H7b6yOUWL4yvEKAGlVHzg9HjrBdn8E42Jz40nfSB9QAkOVN 6ZhIL6226uXYYPwnBhKoXdWl9V6ehKyZHf7oZvPn4KFziYznxB+giQMZ3I1+zH7L37Sf GBFKokMIVBv+dSAqh+amNOAGeEdS4ulVx+gWwkRynZ4UfzklV2b5mQA4vvJJ7nBk8lQc 5OWo3c4dOkA14UepNo8fCIzysVXjL0Ct/LKRz95UemwMpP+J3l9Ik/syc+CEF2m2Zqev uFjw== X-Gm-Message-State: AFeK/H2XOlpeNboeCiHj1rMN3dtt3l1oYP0KQL/6vx4PTN1rYgbIHJZLdBXi010MTN3YUA== X-Received: by 10.99.132.73 with SMTP id k70mr14208164pgd.28.1490440718243; Sat, 25 Mar 2017 04:18:38 -0700 (PDT) From: Ashijeet Acharya To: famz@redhat.com Date: Sat, 25 Mar 2017 16:48:20 +0530 Message-Id: <1490440701-12037-7-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> References: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c00::242 Subject: [Qemu-devel] [PATCH v2 6/7] vmdk: Allocate multiple clusters at once 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, qemu-block@nongnu.org, stefanha@gmail.com, qemu-devel@nongnu.org, mreitz@redhat.com, Ashijeet Acharya , jsnow@redhat.com 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" Get vmdk_pwritev() to make use of the new multiple cluster allocation helper functions to allocate multiple clusters at once. Set the maximum bytes allowed to get allocated at once to be not more than the extent size boundary to handle writes at two separate extents appropriately. Signed-off-by: Ashijeet Acharya --- block/vmdk.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 387e45b..3de8b8f 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1767,7 +1767,9 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_= t offset, int64_t offset_in_cluster, n_bytes; uint64_t cluster_offset; uint64_t bytes_done =3D 0; + uint64_t extent_size; VmdkMetaData m_data; + uint32_t total_alloc_clusters =3D 0; =20 if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) { error_report("Wrong offset: offset=3D0x%" PRIx64 @@ -1781,14 +1783,22 @@ static int vmdk_pwritev(BlockDriverState *bs, uint6= 4_t offset, if (!extent) { return -EIO; } + extent_size =3D extent->end_sector * BDRV_SECTOR_SIZE; + offset_in_cluster =3D vmdk_find_offset_in_cluster(extent, offset); - n_bytes =3D MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_SIZE - - offset_in_cluster); =20 - ret =3D get_cluster_offset(bs, extent, &m_data, offset, - !(extent->compressed || zeroed), - &cluster_offset, offset_in_cluster, - offset_in_cluster + n_bytes); + /* truncate n_bytes to first cluster because we need to perform CO= W */ + if (offset_in_cluster > 0) { + n_bytes =3D MIN(bytes, extent->cluster_sectors * BDRV_SECTOR_S= IZE + - offset_in_cluster); + } else { + n_bytes =3D MIN(bytes, extent_size - offset); + } + + ret =3D vmdk_alloc_cluster_offset(bs, extent, &m_data, offset, + !(extent->compressed || zeroed), + &cluster_offset, n_bytes, + &total_alloc_clusters); if (extent->compressed) { if (ret =3D=3D VMDK_OK) { /* Refuse write to allocated cluster for streamOptimized */ @@ -1797,19 +1807,22 @@ static int vmdk_pwritev(BlockDriverState *bs, uint6= 4_t offset, return -EIO; } else { /* allocate */ - ret =3D get_cluster_offset(bs, extent, &m_data, offset, - true, &cluster_offset, 0, 0); + ret =3D vmdk_alloc_cluster_offset(bs, extent, &m_data, off= set, + true, &cluster_offset, n_b= ytes, + &total_alloc_clusters); } } if (ret =3D=3D VMDK_ERROR) { return -EINVAL; } + if (zeroed) { /* Do zeroed write, buf is ignored */ - if (extent->has_zero_grain && - offset_in_cluster =3D=3D 0 && - n_bytes >=3D extent->cluster_sectors * BDRV_SECTOR_SIZ= E) { - n_bytes =3D extent->cluster_sectors * BDRV_SECTOR_SIZE; + if (extent->has_zero_grain && offset_in_cluster =3D=3D 0 && + n_bytes >=3D extent->cluster_sectors * BDRV_SECTOR_SIZ= E * + total_alloc_clusters) { + n_bytes =3D extent->cluster_sectors * BDRV_SECTOR_SIZE * + total_alloc_clusters; if (!zero_dry_run) { /* update L2 tables */ if (vmdk_L2update(extent, &m_data, VMDK_GTE_ZEROED) --=20 2.6.2 From nobody Wed May 1 22:51:30 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 1490440971354875.7274984809319; Sat, 25 Mar 2017 04:22:51 -0700 (PDT) Received: from localhost ([::1]:36752 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjmU-0004Y0-1j for importer@patchew.org; Sat, 25 Mar 2017 07:22:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35302) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1crjiX-0001UM-Ip for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1crjiW-0000v2-BU for qemu-devel@nongnu.org; Sat, 25 Mar 2017 07:18:45 -0400 Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]:34587) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1crjiW-0000uw-3T; Sat, 25 Mar 2017 07:18:44 -0400 Received: by mail-pg0-x241.google.com with SMTP id w20so2564307pgc.1; Sat, 25 Mar 2017 04:18:44 -0700 (PDT) Received: from linux.local ([27.251.197.196]) by smtp.gmail.com with ESMTPSA id p189sm9952620pfb.128.2017.03.25.04.18.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 25 Mar 2017 04:18:42 -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=bo4m+9utIYBHOYhcngv8m3/qKl5iMHGdFZ3SVoppEsY=; b=rDi+4s6hZbu3hLTXkJBewt0e3lbf0HLduUXwPWR1mNGqpEoz53UHrCllTccNvk0ZuX IuYrF8qIUyrxuotQS/gE4gnnAwz++fD93Pg/MjZilwZi1yGeLaqDEhu+BRy/3jXI5cEe 2C1wM0P91w79e+ppjsWfMTyORfBIpUtxCVBcG5UZE9LDANAndtsHnfCZUBKgyz41iFCW 4CezpJ/W8tADQ2gs1iVW5TGurmfb/jvn9MIf66XiShOBD00IzGDmxzyg023GDNAOfCq3 GYFHASBYfzOFMYF7otYoa1v55DvRxSHCuJEqC6JKt0edzVq2813KlNyJ/MvZ8X2SLs3K i2Bg== 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=bo4m+9utIYBHOYhcngv8m3/qKl5iMHGdFZ3SVoppEsY=; b=EFqlUJXQThGrb0v+bRJQap7Y6phPeUhoC+p2BZ9qO7IKNFMGuKJK4CZ+5N9p96ejjG gVNg34ZvobqIBKOYpN7/1L/KN0YJNVLVxY/OcmCGXsaOctkZjJE8zXnsV2TKxa1p2Nd7 q8tsc9oH+4GPqDrvEVZWT7hfQLqvsBSfwAOYSc6F+/u1b3eu8rLxZcv7Fa2OnUpzkqqw 7EXEyBq8FkiUn+Kc6OOx5OvA64mnref9Ee8UKvW8Y3ZbQSZkRGCxsy8Na7gOoHSu2Ps1 TnWO4t/XjSumQRFUEg7q1Rpla3A/UWrDaL1Kb9733a7Hn79V15SqjD4r4nRRCQEmI4OL bM7A== X-Gm-Message-State: AFeK/H0ajpTP0Ngk5bQv0ovFuSejPEeOFG5HhUYfRsDc3qov0VGmx+gshOm70ws/6aEcDg== X-Received: by 10.99.212.69 with SMTP id i5mr13984846pgj.36.1490440723251; Sat, 25 Mar 2017 04:18:43 -0700 (PDT) From: Ashijeet Acharya To: famz@redhat.com Date: Sat, 25 Mar 2017 16:48:21 +0530 Message-Id: <1490440701-12037-8-git-send-email-ashijeetacharya@gmail.com> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> References: <1490440701-12037-1-git-send-email-ashijeetacharya@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c05::241 Subject: [Qemu-devel] [PATCH v2 7/7] vmdk: Update metadata for multiple clusters 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, qemu-block@nongnu.org, stefanha@gmail.com, qemu-devel@nongnu.org, mreitz@redhat.com, Ashijeet Acharya , jsnow@redhat.com 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" Include a next pointer in VmdkMetaData struct to point to the previous allocated L2 table. Modify vmdk_L2update to start updating metadata for allocation of multiple clusters at once. Signed-off-by: Ashijeet Acharya --- block/vmdk.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 102 insertions(+), 29 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 3de8b8f..4517409 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -137,6 +137,8 @@ typedef struct VmdkMetaData { int valid; uint32_t *l2_cache_entry; uint32_t nb_clusters; + uint32_t offset; + struct VmdkMetaData *next; } VmdkMetaData; =20 typedef struct VmdkGrainMarker { @@ -1037,29 +1039,81 @@ static void vmdk_refresh_limits(BlockDriverState *b= s, Error **errp) } } =20 -static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, - uint32_t offset) +static int vmdk_alloc_cluster_link_l2(VmdkExtent *extent, + VmdkMetaData *m_data, bool zeroed) { - offset =3D cpu_to_le32(offset); + int i; + uint32_t offset, temp_offset; + + if (zeroed) { + temp_offset =3D VMDK_GTE_ZEROED; + } else { + temp_offset =3D m_data->offset; + } + + temp_offset =3D cpu_to_le32(temp_offset); + /* update L2 table */ - if (bdrv_pwrite_sync(extent->file, + offset =3D temp_offset; + for (i =3D 0; i < m_data->nb_clusters; i++) { + if (bdrv_pwrite_sync(extent->file, ((int64_t)m_data->l2_offset * 512) - + (m_data->l2_index * sizeof(offset)), - &offset, sizeof(offset)) < 0) { - return VMDK_ERROR; + + ((m_data->l2_index + i) * sizeof(offset)), + &(offset), sizeof(offset)) < 0) { + return VMDK_ERROR; + } + if (!zeroed) { + offset +=3D 128; + } } + /* update backup L2 table */ + offset =3D temp_offset; if (extent->l1_backup_table_offset !=3D 0) { m_data->l2_offset =3D extent->l1_backup_table[m_data->l1_index]; - if (bdrv_pwrite_sync(extent->file, - ((int64_t)m_data->l2_offset * 512) - + (m_data->l2_index * sizeof(offset)), - &offset, sizeof(offset)) < 0) { - return VMDK_ERROR; + for (i =3D 0; i < m_data->nb_clusters; i++) { + if (bdrv_pwrite_sync(extent->file, + ((int64_t)m_data->l2_offset * 512) + + ((m_data->l2_index + i) * sizeof(offset)), + &(offset), sizeof(offset)) < 0) { + return VMDK_ERROR; + } + if (!zeroed) { + offset +=3D 128; + } } } + + offset =3D temp_offset; if (m_data->l2_cache_entry) { - *m_data->l2_cache_entry =3D offset; + for (i =3D 0; i < m_data->nb_clusters; i++) { + *m_data->l2_cache_entry =3D offset; + m_data->l2_cache_entry++; + + if (!zeroed) { + offset +=3D 128; + } + } + } + + return VMDK_OK; +} + +static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, + bool zeroed) +{ + int ret; + + while (m_data->next !=3D NULL) { + VmdkMetaData *next; + + ret =3D vmdk_alloc_cluster_link_l2(extent, m_data, zeroed); + if (ret < 0) { + return ret; + } + + next =3D m_data->next; + m_data =3D next; } =20 return VMDK_OK; @@ -1271,7 +1325,7 @@ exit: */ static int handle_alloc(BlockDriverState *bs, VmdkExtent *extent, uint64_t offset, uint64_t *cluster_offset, - int64_t *bytes, VmdkMetaData *m_data, + int64_t *bytes, VmdkMetaData **m_data, bool allocate, uint32_t *total_alloc_clusters) { int l1_index, l2_offset, l2_index; @@ -1280,6 +1334,7 @@ static int handle_alloc(BlockDriverState *bs, VmdkExt= ent *extent, uint32_t nb_clusters; bool zeroed =3D false; uint64_t skip_start_bytes, skip_end_bytes; + VmdkMetaData *old_m_data; int ret; =20 ret =3D get_cluster_table(extent, offset, &l1_index, &l2_offset, @@ -1330,13 +1385,21 @@ static int handle_alloc(BlockDriverState *bs, VmdkE= xtent *extent, if (ret < 0) { return ret; } - if (m_data) { - m_data->valid =3D 1; - m_data->l1_index =3D l1_index; - m_data->l2_index =3D l2_index; - m_data->l2_offset =3D l2_offset; - m_data->l2_cache_entry =3D &l2_table[l2_index]; - m_data->nb_clusters =3D nb_clusters; + + if (*m_data) { + old_m_data =3D *m_data; + *m_data =3D g_malloc0(sizeof(**m_data)); + + **m_data =3D (VmdkMetaData) { + .valid =3D 1, + .l1_index =3D l1_index, + .l2_index =3D l2_index, + .l2_offset =3D l2_offset, + .l2_cache_entry =3D &l2_table[l2_index], + .nb_clusters =3D nb_clusters, + .offset =3D cluster_sector, + .next =3D old_m_data, + }; } } *cluster_offset =3D cluster_sector << BDRV_SECTOR_BITS; @@ -1365,7 +1428,7 @@ static int handle_alloc(BlockDriverState *bs, VmdkExt= ent *extent, */ static int vmdk_alloc_cluster_offset(BlockDriverState *bs, VmdkExtent *extent, - VmdkMetaData *m_data, uint64_t offset, + VmdkMetaData **m_data, uint64_t offse= t, bool allocate, uint64_t *cluster_offs= et, int64_t bytes, uint32_t *total_alloc_clusters) @@ -1385,8 +1448,8 @@ static int vmdk_alloc_cluster_offset(BlockDriverState= *bs, new_cluster_offset =3D 0; *cluster_offset =3D 0; n_bytes =3D 0; - if (m_data) { - m_data->valid =3D 0; + if (*m_data) { + (*m_data)->valid =3D 0; } =20 /* due to L2 table margins all bytes may not get allocated at once */ @@ -1768,9 +1831,11 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64= _t offset, uint64_t cluster_offset; uint64_t bytes_done =3D 0; uint64_t extent_size; - VmdkMetaData m_data; + VmdkMetaData *m_data; uint32_t total_alloc_clusters =3D 0; =20 + m_data =3D g_malloc0(sizeof(*m_data)); + if (DIV_ROUND_UP(offset, BDRV_SECTOR_SIZE) > bs->total_sectors) { error_report("Wrong offset: offset=3D0x%" PRIx64 " total_sectors=3D0x%" PRIx64, @@ -1779,6 +1844,7 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_= t offset, } =20 while (bytes > 0) { + m_data->next =3D NULL; extent =3D find_extent(s, offset >> BDRV_SECTOR_BITS, extent); if (!extent) { return -EIO; @@ -1825,7 +1891,7 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_= t offset, total_alloc_clusters; if (!zero_dry_run) { /* update L2 tables */ - if (vmdk_L2update(extent, &m_data, VMDK_GTE_ZEROED) + if (vmdk_L2update(extent, m_data, zeroed) !=3D VMDK_OK) { return -EIO; } @@ -1839,10 +1905,9 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64= _t offset, if (ret) { return ret; } - if (m_data.valid) { + if (m_data->valid) { /* update L2 tables */ - if (vmdk_L2update(extent, &m_data, - cluster_offset >> BDRV_SECTOR_BITS) + if (vmdk_L2update(extent, m_data, zeroed) !=3D VMDK_OK) { return -EIO; } @@ -1852,6 +1917,13 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64= _t offset, offset +=3D n_bytes; bytes_done +=3D n_bytes; =20 + while (m_data->next !=3D NULL) { + VmdkMetaData *next; + next =3D m_data->next; + g_free(m_data); + m_data =3D next; + } + /* update CID on the first write every time the virtual disk is * opened */ if (!s->cid_updated) { @@ -1862,6 +1934,7 @@ static int vmdk_pwritev(BlockDriverState *bs, uint64_= t offset, s->cid_updated =3D true; } } + g_free(m_data); return 0; } =20 --=20 2.6.2