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