9ae3a8
From 26c4eb4923589b410b1aec705b8665afb5e78794 Mon Sep 17 00:00:00 2001
9ae3a8
From: Fam Zheng <famz@redhat.com>
9ae3a8
Date: Mon, 19 Aug 2013 18:54:27 +0800
9ae3a8
Subject: [PATCH 12/13] vmdk: support vmfsSparse files
9ae3a8
9ae3a8
Message-id: <1377573001-27070-13-git-send-email-famz@redhat.com>
9ae3a8
Patchwork-id: 53792
9ae3a8
O-Subject: [RHEL-7 qemu-kvm PATCH 12/13] vmdk: support vmfsSparse files
9ae3a8
Bugzilla: 995866
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
9ae3a8
VMware ESX hosts use a variant of the VMDK3 format, identified by the
9ae3a8
vmfsSparse create type ad the VMFSSPARSE extent type.
9ae3a8
9ae3a8
It has 16 KB grain tables (L2) and a variable-size grain directory (L1).
9ae3a8
In addition, the grain size is always 512, but that is not a problem
9ae3a8
because it is included in the header.
9ae3a8
9ae3a8
The format of the extents is documented in the VMDK spec.  The format
9ae3a8
of the descriptor file is not documented precisely, but it can be
9ae3a8
found at http://kb.vmware.com/kb/10026353 (Recreating a missing virtual
9ae3a8
machine disk (VMDK) descriptor file for delta disks).
9ae3a8
9ae3a8
With these patches, vmfsSparse files only work if opened through the
9ae3a8
descriptor file.  Data files without descriptor files, as far as I
9ae3a8
could understand, are not supported by ESX.
9ae3a8
9ae3a8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
9ae3a8
--
9ae3a8
v2: Rebase to patch 01.
9ae3a8
    Change le64_to_cpu to le32_to_cpu.
9ae3a8
    Rename vmdk_open_vmdk3 to vmdk_open_vmfs_sparse, which represents the
9ae3a8
    current usage of this format.
9ae3a8
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
(cherry picked from commit daac8fdc68c5f0118ce24fcac5873ddaa0d0c9f9)
9ae3a8
Signed-off-by: Fam Zheng <famz@redhat.com>
9ae3a8
---
9ae3a8
 block/vmdk.c |   17 +++++++++--------
9ae3a8
 1 files changed, 9 insertions(+), 8 deletions(-)
9ae3a8
9ae3a8
diff --git a/block/vmdk.c b/block/vmdk.c
9ae3a8
index 4997da4..4d0c82a 100644
9ae3a8
--- a/block/vmdk.c
9ae3a8
+++ b/block/vmdk.c
9ae3a8
@@ -481,9 +481,9 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
9ae3a8
     return ret;
9ae3a8
 }
9ae3a8
 
9ae3a8
-static int vmdk_open_vmdk3(BlockDriverState *bs,
9ae3a8
-                           BlockDriverState *file,
9ae3a8
-                           int flags)
9ae3a8
+static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
9ae3a8
+                                 BlockDriverState *file,
9ae3a8
+                                 int flags)
9ae3a8
 {
9ae3a8
     int ret;
9ae3a8
     uint32_t magic;
9ae3a8
@@ -674,7 +674,7 @@ static int vmdk_open_sparse(BlockDriverState *bs,
9ae3a8
     magic = be32_to_cpu(magic);
9ae3a8
     switch (magic) {
9ae3a8
         case VMDK3_MAGIC:
9ae3a8
-            return vmdk_open_vmdk3(bs, file, flags);
9ae3a8
+            return vmdk_open_vmfs_sparse(bs, file, flags);
9ae3a8
             break;
9ae3a8
         case VMDK4_MAGIC:
9ae3a8
             return vmdk_open_vmdk4(bs, file, flags);
9ae3a8
@@ -718,7 +718,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
9ae3a8
         }
9ae3a8
 
9ae3a8
         if (sectors <= 0 ||
9ae3a8
-            (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) ||
9ae3a8
+            (strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&
9ae3a8
+             strcmp(type, "VMFSSPARSE")) ||
9ae3a8
             (strcmp(access, "RW"))) {
9ae3a8
             goto next_line;
9ae3a8
         }
9ae3a8
@@ -741,8 +742,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
9ae3a8
                 return ret;
9ae3a8
             }
9ae3a8
             extent->flat_start_offset = flat_offset << 9;
9ae3a8
-        } else if (!strcmp(type, "SPARSE")) {
9ae3a8
-            /* SPARSE extent */
9ae3a8
+        } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {
9ae3a8
+            /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/
9ae3a8
             ret = vmdk_open_sparse(bs, extent_file, bs->open_flags);
9ae3a8
             if (ret) {
9ae3a8
                 bdrv_delete(extent_file);
9ae3a8
@@ -789,6 +790,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
9ae3a8
         goto exit;
9ae3a8
     }
9ae3a8
     if (strcmp(ct, "monolithicFlat") &&
9ae3a8
+        strcmp(ct, "vmfsSparse") &&
9ae3a8
         strcmp(ct, "twoGbMaxExtentSparse") &&
9ae3a8
         strcmp(ct, "twoGbMaxExtentFlat")) {
9ae3a8
         fprintf(stderr,
9ae3a8
@@ -1381,7 +1383,6 @@ static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
9ae3a8
     return ret;
9ae3a8
 }
9ae3a8
 
9ae3a8
-
9ae3a8
 static int vmdk_create_extent(const char *filename, int64_t filesize,
9ae3a8
                               bool flat, bool compress, bool zeroed_grain)
9ae3a8
 {
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8