From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:40962) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UYEYB-0003Jm-2q for qemu-devel@nongnu.org; Fri, 03 May 2013 07:53:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UYEY8-000116-6V for qemu-devel@nongnu.org; Fri, 03 May 2013 07:53:18 -0400 Received: from mx1.redhat.com ([209.132.183.28]:6976) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UYEY7-000106-U4 for qemu-devel@nongnu.org; Fri, 03 May 2013 07:53:16 -0400 From: Stefan Hajnoczi Date: Fri, 3 May 2013 13:52:44 +0200 Message-Id: <1367581972-4208-8-git-send-email-stefanha@redhat.com> In-Reply-To: <1367581972-4208-1-git-send-email-stefanha@redhat.com> References: <1367581972-4208-1-git-send-email-stefanha@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] =?utf-8?q?=5BPATCH_07/15=5D_vmdk=3A_add_support_for_?= =?utf-8?b?4oCcemVyb2Vk4oCQZ3JhaW7igJ0gR1RF?= List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Anthony Liguori , Fam Zheng , Stefan Hajnoczi From: Fam Zheng Introduced support for zeroed-grain GTE, as specified in Virtual Disk Format 5.0[1]. Recent VMware hosted platform products support a new =E2=80=9Czeroed=E2= =80=90grain=E2=80=9D grain table entry (GTE). The zeroed=E2=80=90grain GTE returns all zer= os on read. In other words, the zeroed=E2=80=90grain GTE indicates that a = grain in the child disk is zero=E2=80=90filled but does not actually occupy= space in storage. A sparse extent with zeroed=E2=80=90grain GTE has the fo= llowing in its header: * SparseExtentHeader.version =3D 2 * SparseExtentHeader.flags has bit 2 set Other than the new flag and the possibly zeroed=E2=80=90grain GTE, ve= rsion 2 sparse extents are identical to version 1. Also, a zeroed=E2=80=90gr= ain GTE has value 0x1 in the GT table. [1] Virtual Disk Format 5.0, http://www.vmware.com/support/developer/vddk= /vmdk_50_technote.pdf?src=3Dvmdk Signed-off-by: Fam Zheng Signed-off-by: Stefan Hajnoczi --- block/vmdk.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 16aa29c..7e07c0f 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -33,10 +33,13 @@ #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V') #define VMDK4_COMPRESSION_DEFLATE 1 #define VMDK4_FLAG_RGD (1 << 1) +/* Zeroed-grain enable bit */ +#define VMDK4_FLAG_ZERO_GRAIN (1 << 2) #define VMDK4_FLAG_COMPRESS (1 << 16) #define VMDK4_FLAG_MARKER (1 << 17) #define VMDK4_GD_AT_END 0xffffffffffffffffULL =20 +#define VMDK_GTE_ZEROED 0x1 =20 /* VMDK internal error codes */ #define VMDK_OK 0 @@ -81,6 +84,8 @@ typedef struct VmdkExtent { bool flat; bool compressed; bool has_marker; + bool has_zero_grain; + int version; int64_t sectors; int64_t end_sector; int64_t flat_start_offset; @@ -569,6 +574,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, extent->compressed =3D le16_to_cpu(header.compressAlgorithm) =3D=3D VMDK4_COMPRESSION_D= EFLATE; extent->has_marker =3D le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER= ; + extent->version =3D le32_to_cpu(header.version); + extent->has_zero_grain =3D le32_to_cpu(header.flags) & VMDK4_FLAG_ZE= RO_GRAIN; ret =3D vmdk_init_tables(bs, extent); if (ret) { /* free extent allocated by vmdk_add_extent */ @@ -839,6 +846,7 @@ static int get_cluster_offset(BlockDriverState *bs, unsigned int l1_index, l2_offset, l2_index; int min_index, i, j; uint32_t min_count, *l2_table, tmp =3D 0; + bool zeroed =3D false; =20 if (m_data) { m_data->valid =3D 0; @@ -894,9 +902,13 @@ static int get_cluster_offset(BlockDriverState *bs, l2_index =3D ((offset >> 9) / extent->cluster_sectors) % extent->l2_= size; *cluster_offset =3D le32_to_cpu(l2_table[l2_index]); =20 - if (!*cluster_offset) { + if (extent->has_zero_grain && *cluster_offset =3D=3D VMDK_GTE_ZEROED= ) { + zeroed =3D true; + } + + if (!*cluster_offset || zeroed) { if (!allocate) { - return VMDK_UNALLOC; + return zeroed ? VMDK_ZEROED : VMDK_UNALLOC; } =20 /* Avoid the L2 tables update for the images that have snapshots= . */ @@ -967,8 +979,8 @@ static int coroutine_fn vmdk_co_is_allocated(BlockDri= verState *bs, ret =3D get_cluster_offset(bs, extent, NULL, sector_num * 512, 0, &offset); qemu_co_mutex_unlock(&s->lock); - /* get_cluster_offset returning 0 means success */ - ret =3D !ret; + + ret =3D (ret =3D=3D VMDK_OK || ret =3D=3D VMDK_ZEROED); =20 index_in_cluster =3D sector_num % extent->cluster_sectors; n =3D extent->cluster_sectors - index_in_cluster; @@ -1111,9 +1123,9 @@ static int vmdk_read(BlockDriverState *bs, int64_t = sector_num, if (n > nb_sectors) { n =3D nb_sectors; } - if (ret) { + if (ret !=3D VMDK_OK) { /* if not allocated, try to read from parent image, if exist= */ - if (bs->backing_hd) { + if (bs->backing_hd && ret !=3D VMDK_ZEROED) { if (!vmdk_is_cid_valid(bs)) { return -EINVAL; } --=20 1.8.1.4