Patchwork [v2,3/5] vmdk: Add option to create zeroed-grain image

login
register
mail settings
Submitter Fam Zheng
Date April 22, 2013, 2:07 a.m.
Message ID <1366596479-22212-4-git-send-email-famz@redhat.com>
Download mbox | patch
Permalink /patch/238280/
State New
Headers show

Comments

Fam Zheng - April 22, 2013, 2:07 a.m.
Add image create option "zeroed-grain" to enable zeroed-grain GTE
feature of vmdk sparse extents. When this option is on, header version
of newly created extent will be 2 and VMDK4_FLAG_ZG flag bit will be
set.
Signed-off-by: Fam Zheng <famz@redhat.com>
---
 block/vmdk.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)
Stefan Hajnoczi - April 22, 2013, 2:06 p.m.
On Mon, Apr 22, 2013 at 10:07:57AM +0800, Fam Zheng wrote:
> Add image create option "zeroed-grain" to enable zeroed-grain GTE
> feature of vmdk sparse extents. When this option is on, header version
> of newly created extent will be 2 and VMDK4_FLAG_ZG flag bit will be
> set.
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>  block/vmdk.c | 22 +++++++++++++++++-----
>  1 file changed, 17 insertions(+), 5 deletions(-)

Is there a way to upgrade an image file to use zeroed-grain GTEs once
the file has been created?

Stefan
Fam Zheng - April 23, 2013, 12:52 a.m.
On Mon, 04/22 16:06, Stefan Hajnoczi wrote:
> On Mon, Apr 22, 2013 at 10:07:57AM +0800, Fam Zheng wrote:
> > Add image create option "zeroed-grain" to enable zeroed-grain GTE
> > feature of vmdk sparse extents. When this option is on, header version
> > of newly created extent will be 2 and VMDK4_FLAG_ZG flag bit will be
> > set.
> > Signed-off-by: Fam Zheng <famz@redhat.com>
> > ---
> >  block/vmdk.c | 22 +++++++++++++++++-----
> >  1 file changed, 17 insertions(+), 5 deletions(-)
> 
> Is there a way to upgrade an image file to use zeroed-grain GTEs once
> the file has been created?
> 

Yes. We have discussed this on IRC.

Here's how we do it:
 - If file version is 2 and zeroed-grain GTE bit set in header, we can
   support bdrv_co_write_zeroes (this patch series implemented).
 - If the file version is 2, we can enable zeroed-grain flag in header
   on bdrv_co_write_zeroes, and use zeroed-grain GTE. (need another
   patch to update the header).
 - Otherwize, -ENOTSUP

For background, here's how vmware uses this feature:
 - On shrinking a *child* disk (e.g.: vmware-vdiskmanager -k
   child.vmdk), if the child cluster is filled with zero, then the image
   version is upgraded to 2 and zeroed-grian flag is set, and
   zeroed-grain GTE is used to clear out the cluster, no need to take
   care of parent cluster allocation and actual data at all. That's
   where the efficiency comes.
Stefan Hajnoczi - April 23, 2013, 7 a.m.
On Tue, Apr 23, 2013 at 08:52:02AM +0800, Fam Zheng wrote:
> On Mon, 04/22 16:06, Stefan Hajnoczi wrote:
> > On Mon, Apr 22, 2013 at 10:07:57AM +0800, Fam Zheng wrote:
> > > Add image create option "zeroed-grain" to enable zeroed-grain GTE
> > > feature of vmdk sparse extents. When this option is on, header version
> > > of newly created extent will be 2 and VMDK4_FLAG_ZG flag bit will be
> > > set.
> > > Signed-off-by: Fam Zheng <famz@redhat.com>
> > > ---
> > >  block/vmdk.c | 22 +++++++++++++++++-----
> > >  1 file changed, 17 insertions(+), 5 deletions(-)
> > 
> > Is there a way to upgrade an image file to use zeroed-grain GTEs once
> > the file has been created?
> > 
> 
> Yes. We have discussed this on IRC.
> 
> Here's how we do it:
>  - If file version is 2 and zeroed-grain GTE bit set in header, we can
>    support bdrv_co_write_zeroes (this patch series implemented).
>  - If the file version is 2, we can enable zeroed-grain flag in header
>    on bdrv_co_write_zeroes, and use zeroed-grain GTE. (need another
>    patch to update the header).
>  - Otherwize, -ENOTSUP
> 
> For background, here's how vmware uses this feature:
>  - On shrinking a *child* disk (e.g.: vmware-vdiskmanager -k
>    child.vmdk), if the child cluster is filled with zero, then the image
>    version is upgraded to 2 and zeroed-grian flag is set, and
>    zeroed-grain GTE is used to clear out the cluster, no need to take
>    care of parent cluster allocation and actual data at all. That's
>    where the efficiency comes.

The question is when QEMU should upgrade images.  It's safest to avoid
silently increasing the image file's version requirements.  But it would
be nice to allow upgrading if the users wishes to do that.

It doesn't need to be solved in this patch series.

Stefan

Patch

diff --git a/block/vmdk.c b/block/vmdk.c
index 7e07c0f..d8c6c70 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -48,6 +48,8 @@ 
 #define VMDK_UNALLOC (-2)
 #define VMDK_ZEROED  (-3)
 
+#define BLOCK_OPT_ZEROED_GRAIN "zeroed_grain"
+
 typedef struct {
     uint32_t version;
     uint32_t flags;
@@ -1262,7 +1264,7 @@  static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
 
 
 static int vmdk_create_extent(const char *filename, int64_t filesize,
-                              bool flat, bool compress)
+                              bool flat, bool compress, bool zeroed_grain)
 {
     int ret, i;
     int fd = 0;
@@ -1284,9 +1286,10 @@  static int vmdk_create_extent(const char *filename, int64_t filesize,
     }
     magic = cpu_to_be32(VMDK4_MAGIC);
     memset(&header, 0, sizeof(header));
-    header.version = 1;
-    header.flags =
-        3 | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0);
+    header.version = zeroed_grain ? 2 : 1;
+    header.flags = 3
+                   | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0)
+                   | (zeroed_grain ? VMDK4_FLAG_ZG : 0);
     header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
     header.capacity = filesize / 512;
     header.granularity = 128;
@@ -1467,6 +1470,7 @@  static int vmdk_create(const char *filename, QEMUOptionParameter *options)
     char parent_desc_line[BUF_SIZE] = "";
     uint32_t parent_cid = 0xffffffff;
     uint32_t number_heads = 16;
+    bool zeroed_grain = false;
     const char desc_template[] =
         "# Disk DescriptorFile\n"
         "version=1\n"
@@ -1502,6 +1506,8 @@  static int vmdk_create(const char *filename, QEMUOptionParameter *options)
             flags |= options->value.n ? BLOCK_FLAG_COMPAT6 : 0;
         } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
             fmt = options->value.s;
+        } else if (!strcmp(options->name, BLOCK_OPT_ZEROED_GRAIN)) {
+            zeroed_grain |= options->value.n;
         }
         options++;
     }
@@ -1588,7 +1594,8 @@  static int vmdk_create(const char *filename, QEMUOptionParameter *options)
         snprintf(ext_filename, sizeof(ext_filename), "%s%s",
                 path, desc_filename);
 
-        if (vmdk_create_extent(ext_filename, size, flat, compress)) {
+        if (vmdk_create_extent(ext_filename, size,
+                               flat, compress, zeroed_grain)) {
             return -EINVAL;
         }
         filesize -= size;
@@ -1714,6 +1721,11 @@  static QEMUOptionParameter vmdk_create_options[] = {
             "VMDK flat extent format, can be one of "
             "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
     },
+    {
+        .name = BLOCK_OPT_ZEROED_GRAIN,
+        .type = OPT_FLAG,
+        .help = "Enable efficient zero writes using the zeroed-grain GTE feature"
+    },
     { NULL }
 };