All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image
@ 2014-04-01 14:06 Jun Lee
  2014-04-02  2:24 ` Fam Zheng
  0 siblings, 1 reply; 7+ messages in thread
From: Jun Lee @ 2014-04-01 14:06 UTC (permalink / raw)
  To: kwolf, stefanha; +Cc: qemu-devel

Signed-off-by: Jun Li <junmuzi@gmail.com>

This patch can make sure the data still existing after shrinking. And only discard the unused (guest) clusters. If shrinking to the size which stored data, It will return an error and will not do any change.
As this patch can support shrinking, so changed the func name of qcow2_grow_l1_table to qcow2_truncate_l1_table.
---
 block/qcow2-cluster.c  | 20 ++++++++++++++------
 block/qcow2-snapshot.c |  2 +-
 block/qcow2.c          |  8 +-------
 block/qcow2.h          |  2 +-
 4 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9499df9..70e61ea 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -29,7 +29,7 @@
 #include "block/qcow2.h"
 #include "trace.h"
 
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
                         bool exact_size)
 {
     BDRVQcowState *s = bs->opaque;
@@ -39,9 +39,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
     int64_t new_l1_table_offset, new_l1_size;
     uint8_t data[12];
 
-    if (min_size <= s->l1_size)
-        return 0;
-
     if (exact_size) {
         new_l1_size = min_size;
     } else {
@@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
 
     new_l1_size2 = sizeof(uint64_t) * new_l1_size;
     new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
-    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
+
+    /* shrinking the image */
+    if (min_size <= s->l1_size) {
+        if (s->l1_table[new_l1_size] != 0) {
+            error_report("Could not shrink to this size, "
+                        "it will destory image data");
+            return -ENOTSUP;
+        }
+        memcpy(new_l1_table, s->l1_table, new_l1_size2);
+    }
+
+   memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
 
     /* write new table (align to cluster) */
     BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
@@ -559,7 +567,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
 
     l1_index = offset >> (s->l2_bits + s->cluster_bits);
     if (l1_index >= s->l1_size) {
-        ret = qcow2_grow_l1_table(bs, l1_index + 1, false);
+        ret = qcow2_truncate_l1_table(bs, l1_index + 1, false);
         if (ret < 0) {
             return ret;
         }
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 2fc6320..ab16c52 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -491,7 +491,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
      * L1 table of the snapshot. If the snapshot L1 table is smaller, the
      * current one must be padded with zeros.
      */
-    ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
+    ret = qcow2_truncate_l1_table(bs, sn->l1_size, true);
     if (ret < 0) {
         goto fail;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index b9dc960..4797879 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1764,14 +1764,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
         return -ENOTSUP;
     }
 
-    /* shrinking is currently not supported */
-    if (offset < bs->total_sectors * 512) {
-        error_report("qcow2 doesn't support shrinking images yet");
-        return -ENOTSUP;
-    }
-
     new_l1_size = size_to_l1(s, offset);
-    ret = qcow2_grow_l1_table(bs, new_l1_size, true);
+    ret = qcow2_truncate_l1_table(bs, new_l1_size, true);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/qcow2.h b/block/qcow2.h
index 0b0eac8..298d84e 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -455,7 +455,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
                                   int64_t size);
 
 /* qcow2-cluster.c functions */
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
                         bool exact_size);
 int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
 void qcow2_l2_cache_reset(BlockDriverState *bs);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image
  2014-04-01 14:06 [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image Jun Lee
@ 2014-04-02  2:24 ` Fam Zheng
  2014-04-03 11:28   ` Jun Lee
  0 siblings, 1 reply; 7+ messages in thread
From: Fam Zheng @ 2014-04-02  2:24 UTC (permalink / raw)
  To: Jun Lee; +Cc: kwolf, qemu-devel, stefanha

On Tue, 04/01 10:06, Jun Lee wrote:
> Signed-off-by: Jun Li <junmuzi@gmail.com>
> 
> This patch can make sure the data still existing after shrinking. And only discard the unused (guest) clusters. If shrinking to the size which stored data, It will return an error and will not do any change.
> As this patch can support shrinking, so changed the func name of qcow2_grow_l1_table to qcow2_truncate_l1_table.

Signed-off-by line is missing.

> ---
>  block/qcow2-cluster.c  | 20 ++++++++++++++------
>  block/qcow2-snapshot.c |  2 +-
>  block/qcow2.c          |  8 +-------
>  block/qcow2.h          |  2 +-
>  4 files changed, 17 insertions(+), 15 deletions(-)
> 
> diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
> index 9499df9..70e61ea 100644
> --- a/block/qcow2-cluster.c
> +++ b/block/qcow2-cluster.c
> @@ -29,7 +29,7 @@
>  #include "block/qcow2.h"
>  #include "trace.h"
>  
> -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
> +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
>                          bool exact_size)

Parameter alignment is changed.

>  {
>      BDRVQcowState *s = bs->opaque;
> @@ -39,9 +39,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
>      int64_t new_l1_table_offset, new_l1_size;
>      uint8_t data[12];
>  
> -    if (min_size <= s->l1_size)
> -        return 0;
> -
>      if (exact_size) {
>          new_l1_size = min_size;
>      } else {
> @@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
>  
>      new_l1_size2 = sizeof(uint64_t) * new_l1_size;
>      new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
> -    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
> +
> +    /* shrinking the image */
> +    if (min_size <= s->l1_size) {
> +        if (s->l1_table[new_l1_size] != 0) {

Is this safe as advertised? Do we need to scan all the dropped l1 entries,
instead of only the first one?

> +            error_report("Could not shrink to this size, "
> +                        "it will destory image data");

Better to align by quote mark.

> +            return -ENOTSUP;
> +        }
> +        memcpy(new_l1_table, s->l1_table, new_l1_size2);
> +    }
> +
> +   memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));

Redundant (and wrong size) memcpy for shrinking case?

Fam

>  
>      /* write new table (align to cluster) */
>      BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
> @@ -559,7 +567,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
>  
>      l1_index = offset >> (s->l2_bits + s->cluster_bits);
>      if (l1_index >= s->l1_size) {
> -        ret = qcow2_grow_l1_table(bs, l1_index + 1, false);
> +        ret = qcow2_truncate_l1_table(bs, l1_index + 1, false);
>          if (ret < 0) {
>              return ret;
>          }
> diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
> index 2fc6320..ab16c52 100644
> --- a/block/qcow2-snapshot.c
> +++ b/block/qcow2-snapshot.c
> @@ -491,7 +491,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
>       * L1 table of the snapshot. If the snapshot L1 table is smaller, the
>       * current one must be padded with zeros.
>       */
> -    ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
> +    ret = qcow2_truncate_l1_table(bs, sn->l1_size, true);
>      if (ret < 0) {
>          goto fail;
>      }
> diff --git a/block/qcow2.c b/block/qcow2.c
> index b9dc960..4797879 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -1764,14 +1764,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
>          return -ENOTSUP;
>      }
>  
> -    /* shrinking is currently not supported */
> -    if (offset < bs->total_sectors * 512) {
> -        error_report("qcow2 doesn't support shrinking images yet");
> -        return -ENOTSUP;
> -    }
> -
>      new_l1_size = size_to_l1(s, offset);
> -    ret = qcow2_grow_l1_table(bs, new_l1_size, true);
> +    ret = qcow2_truncate_l1_table(bs, new_l1_size, true);
>      if (ret < 0) {
>          return ret;
>      }
> diff --git a/block/qcow2.h b/block/qcow2.h
> index 0b0eac8..298d84e 100644
> --- a/block/qcow2.h
> +++ b/block/qcow2.h
> @@ -455,7 +455,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
>                                    int64_t size);
>  
>  /* qcow2-cluster.c functions */
> -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
> +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
>                          bool exact_size);
>  int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
>  void qcow2_l2_cache_reset(BlockDriverState *bs);
> -- 
> 1.8.3.1
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image
  2014-04-02  2:24 ` Fam Zheng
@ 2014-04-03 11:28   ` Jun Lee
  2014-04-04  0:51     ` Fam Zheng
  0 siblings, 1 reply; 7+ messages in thread
From: Jun Lee @ 2014-04-03 11:28 UTC (permalink / raw)
  To: Fam Zheng; +Cc: kwolf, qemu-devel, stefanha



----- Original Message -----
From: "Fam Zheng" <famz@redhat.com>
To: "Jun Lee" <juli@redhat.com>
Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org
Sent: Wednesday, April 2, 2014 10:24:34 AM
Subject: Re: [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image

On Tue, 04/01 10:06, Jun Lee wrote:
> Signed-off-by: Jun Li <junmuzi@gmail.com>
> 
> This patch can make sure the data still existing after shrinking. And only discard the unused (guest) clusters. If shrinking to the size which stored data, It will return an error and will not do any change.
> As this patch can support shrinking, so changed the func name of qcow2_grow_l1_table to qcow2_truncate_l1_table.

Signed-off-by line is missing.

-sorry, agree with you.
> ---
>  block/qcow2-cluster.c  | 20 ++++++++++++++------
>  block/qcow2-snapshot.c |  2 +-
>  block/qcow2.c          |  8 +-------
>  block/qcow2.h          |  2 +-
>  4 files changed, 17 insertions(+), 15 deletions(-)
> 
> diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
> index 9499df9..70e61ea 100644
> --- a/block/qcow2-cluster.c
> +++ b/block/qcow2-cluster.c
> @@ -29,7 +29,7 @@
>  #include "block/qcow2.h"
>  #include "trace.h"
>  
> -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
> +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
>                          bool exact_size)

Parameter alignment is changed.

-sorry, agree with you. I will change it.
>  {
>      BDRVQcowState *s = bs->opaque;
> @@ -39,9 +39,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
>      int64_t new_l1_table_offset, new_l1_size;
>      uint8_t data[12];
>  
> -    if (min_size <= s->l1_size)
> -        return 0;
> -
>      if (exact_size) {
>          new_l1_size = min_size;
>      } else {
> @@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
>  
>      new_l1_size2 = sizeof(uint64_t) * new_l1_size;
>      new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
> -    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
> +
> +    /* shrinking the image */
> +    if (min_size <= s->l1_size) {
> +        if (s->l1_table[new_l1_size] != 0) {

Is this safe as advertised? Do we need to scan all the dropped l1 entries,
instead of only the first one?
-maybe this is the fastest way to drop. I think no need to scan all the dropped l1 entries.
-As the dropped l1 entries will not contain any value data.
> +            error_report("Could not shrink to this size, "
> +                        "it will destory image data");

Better to align by quote mark.
-Sorry, agree with you. Thank you very much.

> +            return -ENOTSUP;
> +        }
> +        memcpy(new_l1_table, s->l1_table, new_l1_size2);
> +    }
> +
> +   memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));

Redundant (and wrong size) memcpy for shrinking case?
-Sorry, this is my carelessness. I will submit the update version. Thanks again.

>  
>      /* write new table (align to cluster) */
>      BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
> @@ -559,7 +567,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
>  
>      l1_index = offset >> (s->l2_bits + s->cluster_bits);
>      if (l1_index >= s->l1_size) {
> -        ret = qcow2_grow_l1_table(bs, l1_index + 1, false);
> +        ret = qcow2_truncate_l1_table(bs, l1_index + 1, false);
>          if (ret < 0) {
>              return ret;
>          }
> diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
> index 2fc6320..ab16c52 100644
> --- a/block/qcow2-snapshot.c
> +++ b/block/qcow2-snapshot.c
> @@ -491,7 +491,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
>       * L1 table of the snapshot. If the snapshot L1 table is smaller, the
>       * current one must be padded with zeros.
>       */
> -    ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
> +    ret = qcow2_truncate_l1_table(bs, sn->l1_size, true);
>      if (ret < 0) {
>          goto fail;
>      }
> diff --git a/block/qcow2.c b/block/qcow2.c
> index b9dc960..4797879 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -1764,14 +1764,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
>          return -ENOTSUP;
>      }
>  
> -    /* shrinking is currently not supported */
> -    if (offset < bs->total_sectors * 512) {
> -        error_report("qcow2 doesn't support shrinking images yet");
> -        return -ENOTSUP;
> -    }
> -
>      new_l1_size = size_to_l1(s, offset);
> -    ret = qcow2_grow_l1_table(bs, new_l1_size, true);
> +    ret = qcow2_truncate_l1_table(bs, new_l1_size, true);
>      if (ret < 0) {
>          return ret;
>      }
> diff --git a/block/qcow2.h b/block/qcow2.h
> index 0b0eac8..298d84e 100644
> --- a/block/qcow2.h
> +++ b/block/qcow2.h
> @@ -455,7 +455,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
>                                    int64_t size);
-This parameter should to align.
>  
>  /* qcow2-cluster.c functions */
> -int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
> +int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
>                          bool exact_size);
-This parameter should to align, too. Thanks Fam.

Jun Li
>  int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
>  void qcow2_l2_cache_reset(BlockDriverState *bs);
> -- 
> 1.8.3.1
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image
  2014-04-03 11:28   ` Jun Lee
@ 2014-04-04  0:51     ` Fam Zheng
  0 siblings, 0 replies; 7+ messages in thread
From: Fam Zheng @ 2014-04-04  0:51 UTC (permalink / raw)
  To: Jun Lee; +Cc: kwolf, qemu-devel, stefanha

On Thu, 04/03 07:28, Jun Lee wrote:
> > @@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
> >  
> >      new_l1_size2 = sizeof(uint64_t) * new_l1_size;
> >      new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
> > -    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
> > +
> > +    /* shrinking the image */
> > +    if (min_size <= s->l1_size) {
> > +        if (s->l1_table[new_l1_size] != 0) {
> 
> Is this safe as advertised? Do we need to scan all the dropped l1 entries,
> instead of only the first one?
> -As the dropped l1 entries will not contain any value data.

I don't understand, how do you make sure of that without checking it?

Fam

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image
@ 2014-04-01 14:03 Jun Li
  0 siblings, 0 replies; 7+ messages in thread
From: Jun Li @ 2014-04-01 14:03 UTC (permalink / raw)
  To: stefanha, kwolf; +Cc: qemu-devel, junli

[-- Attachment #1: Type: text/plain, Size: 4211 bytes --]



Signed-off-by: Jun Li <junmuzi@gmail.com>


This patch can make sure the data still existing after shrinking. And only discard the unused (guest) clusters. If shrinking to the size which stored data, It will return an error and will not do any change.
As this patch can support shrinking, so changed the func name of qcow2_grow_l1_table to qcow2_truncate_l1_table.
---
 block/qcow2-cluster.c  | 20 ++++++++++++++------
 block/qcow2-snapshot.c |  2 +-
 block/qcow2.c          |  8 +-------
 block/qcow2.h          |  2 +-
 4 files changed, 17 insertions(+), 15 deletions(-)


diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9499df9..70e61ea 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -29,7 +29,7 @@
 #include "block/qcow2.h"
 #include "trace.h"
 
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
                         bool exact_size)
 {
     BDRVQcowState *s = bs->opaque;
@@ -39,9 +39,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
     int64_t new_l1_table_offset, new_l1_size;
     uint8_t data[12];
 
-    if (min_size <= s->l1_size)
-        return 0;
-
     if (exact_size) {
         new_l1_size = min_size;
     } else {
@@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
 
     new_l1_size2 = sizeof(uint64_t) * new_l1_size;
     new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
-    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
+
+    /* shrinking the image */
+    if (min_size <= s->l1_size) {
+        if (s->l1_table[new_l1_size] != 0) {
+            error_report("Could not shrink to this size, "
+                        "it will destory image data");
+            return -ENOTSUP;
+        }
+        memcpy(new_l1_table, s->l1_table, new_l1_size2);
+    }
+
+   memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
 
     /* write new table (align to cluster) */
     BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
@@ -559,7 +567,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
 
     l1_index = offset >> (s->l2_bits + s->cluster_bits);
     if (l1_index >= s->l1_size) {
-        ret = qcow2_grow_l1_table(bs, l1_index + 1, false);
+        ret = qcow2_truncate_l1_table(bs, l1_index + 1, false);
         if (ret < 0) {
             return ret;
         }
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 2fc6320..ab16c52 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -491,7 +491,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
      * L1 table of the snapshot. If the snapshot L1 table is smaller, the
      * current one must be padded with zeros.
      */
-    ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
+    ret = qcow2_truncate_l1_table(bs, sn->l1_size, true);
     if (ret < 0) {
         goto fail;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index b9dc960..4797879 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1764,14 +1764,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
         return -ENOTSUP;
     }
 
-    /* shrinking is currently not supported */
-    if (offset < bs->total_sectors * 512) {
-        error_report("qcow2 doesn't support shrinking images yet");
-        return -ENOTSUP;
-    }
-
     new_l1_size = size_to_l1(s, offset);
-    ret = qcow2_grow_l1_table(bs, new_l1_size, true);
+    ret = qcow2_truncate_l1_table(bs, new_l1_size, true);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/qcow2.h b/block/qcow2.h
index 0b0eac8..298d84e 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -455,7 +455,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
                                   int64_t size);
 
 /* qcow2-cluster.c functions */
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
                         bool exact_size);
 int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
 void qcow2_l2_cache_reset(BlockDriverState *bs);
-- 
1.8.3.1


[-- Attachment #2: Type: text/html, Size: 6873 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image
@ 2014-04-01 13:55 Jun Li
  0 siblings, 0 replies; 7+ messages in thread
From: Jun Li @ 2014-04-01 13:55 UTC (permalink / raw)
  To: kwolf, stefanha; +Cc: Jun Li, juli, qemu-devel, junmuzi

Signed-off-by: Jun Li <junmuzi@gmail.com>

This patch can make sure the data still existing after shrinking. And only discard the unused (guest) clusters. If shrinking to the size which stored data, It will return an error and will not do any change.
As this patch can support shrinking, so changed the func name of qcow2_grow_l1_table to qcow2_truncate_l1_table.
---
 block/qcow2-cluster.c  | 20 ++++++++++++++------
 block/qcow2-snapshot.c |  2 +-
 block/qcow2.c          |  8 +-------
 block/qcow2.h          |  2 +-
 4 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9499df9..70e61ea 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -29,7 +29,7 @@
 #include "block/qcow2.h"
 #include "trace.h"
 
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
                         bool exact_size)
 {
     BDRVQcowState *s = bs->opaque;
@@ -39,9 +39,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
     int64_t new_l1_table_offset, new_l1_size;
     uint8_t data[12];
 
-    if (min_size <= s->l1_size)
-        return 0;
-
     if (exact_size) {
         new_l1_size = min_size;
     } else {
@@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
 
     new_l1_size2 = sizeof(uint64_t) * new_l1_size;
     new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
-    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
+
+    /* shrinking the image */
+    if (min_size <= s->l1_size) {
+        if (s->l1_table[new_l1_size] != 0) {
+            error_report("Could not shrink to this size, "
+                        "it will destory image data");
+            return -ENOTSUP;
+        }
+        memcpy(new_l1_table, s->l1_table, new_l1_size2);
+    }
+
+   memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
 
     /* write new table (align to cluster) */
     BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
@@ -559,7 +567,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
 
     l1_index = offset >> (s->l2_bits + s->cluster_bits);
     if (l1_index >= s->l1_size) {
-        ret = qcow2_grow_l1_table(bs, l1_index + 1, false);
+        ret = qcow2_truncate_l1_table(bs, l1_index + 1, false);
         if (ret < 0) {
             return ret;
         }
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 2fc6320..ab16c52 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -491,7 +491,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
      * L1 table of the snapshot. If the snapshot L1 table is smaller, the
      * current one must be padded with zeros.
      */
-    ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
+    ret = qcow2_truncate_l1_table(bs, sn->l1_size, true);
     if (ret < 0) {
         goto fail;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index b9dc960..4797879 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1764,14 +1764,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
         return -ENOTSUP;
     }
 
-    /* shrinking is currently not supported */
-    if (offset < bs->total_sectors * 512) {
-        error_report("qcow2 doesn't support shrinking images yet");
-        return -ENOTSUP;
-    }
-
     new_l1_size = size_to_l1(s, offset);
-    ret = qcow2_grow_l1_table(bs, new_l1_size, true);
+    ret = qcow2_truncate_l1_table(bs, new_l1_size, true);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/qcow2.h b/block/qcow2.h
index 0b0eac8..298d84e 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -455,7 +455,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
                                   int64_t size);
 
 /* qcow2-cluster.c functions */
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
                         bool exact_size);
 int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
 void qcow2_l2_cache_reset(BlockDriverState *bs);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image
@ 2014-04-01 13:48 Jun Li
  0 siblings, 0 replies; 7+ messages in thread
From: Jun Li @ 2014-04-01 13:48 UTC (permalink / raw)
  To: kwolf, stefanha; +Cc: Jun Li, juli, qemu-devel, junmuzi

Signed-off-by: Jun Li <junmuzi@gmail.com>

This patch can make sure the data still existing after shrinking. And only discard the unused (guest) clusters. If shrinking to the size which stored data, It will return an error and will not do any change.
As this patch can support shrinking, so changed the func name of qcow2_grow_l1_table to qcow2_truncate_l1_table.
---
 block/qcow2-cluster.c  | 20 ++++++++++++++------
 block/qcow2-snapshot.c |  2 +-
 block/qcow2.c          |  8 +-------
 block/qcow2.h          |  2 +-
 4 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9499df9..70e61ea 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -29,7 +29,7 @@
 #include "block/qcow2.h"
 #include "trace.h"
 
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
                         bool exact_size)
 {
     BDRVQcowState *s = bs->opaque;
@@ -39,9 +39,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
     int64_t new_l1_table_offset, new_l1_size;
     uint8_t data[12];
 
-    if (min_size <= s->l1_size)
-        return 0;
-
     if (exact_size) {
         new_l1_size = min_size;
     } else {
@@ -66,7 +63,18 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
 
     new_l1_size2 = sizeof(uint64_t) * new_l1_size;
     new_l1_table = g_malloc0(align_offset(new_l1_size2, 512));
-    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
+
+    /* shrinking the image */
+    if (min_size <= s->l1_size) {
+        if (s->l1_table[new_l1_size] != 0) {
+            error_report("Could not shrink to this size, "
+                        "it will destory image data");
+            return -ENOTSUP;
+        }
+        memcpy(new_l1_table, s->l1_table, new_l1_size2);
+    }
+
+   memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
 
     /* write new table (align to cluster) */
     BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
@@ -559,7 +567,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
 
     l1_index = offset >> (s->l2_bits + s->cluster_bits);
     if (l1_index >= s->l1_size) {
-        ret = qcow2_grow_l1_table(bs, l1_index + 1, false);
+        ret = qcow2_truncate_l1_table(bs, l1_index + 1, false);
         if (ret < 0) {
             return ret;
         }
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 2fc6320..ab16c52 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -491,7 +491,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
      * L1 table of the snapshot. If the snapshot L1 table is smaller, the
      * current one must be padded with zeros.
      */
-    ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
+    ret = qcow2_truncate_l1_table(bs, sn->l1_size, true);
     if (ret < 0) {
         goto fail;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index b9dc960..4797879 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1764,14 +1764,8 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
         return -ENOTSUP;
     }
 
-    /* shrinking is currently not supported */
-    if (offset < bs->total_sectors * 512) {
-        error_report("qcow2 doesn't support shrinking images yet");
-        return -ENOTSUP;
-    }
-
     new_l1_size = size_to_l1(s, offset);
-    ret = qcow2_grow_l1_table(bs, new_l1_size, true);
+    ret = qcow2_truncate_l1_table(bs, new_l1_size, true);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/qcow2.h b/block/qcow2.h
index 0b0eac8..298d84e 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -455,7 +455,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
                                   int64_t size);
 
 /* qcow2-cluster.c functions */
-int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
+int qcow2_truncate_l1_table(BlockDriverState *bs, uint64_t min_size,
                         bool exact_size);
 int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
 void qcow2_l2_cache_reset(BlockDriverState *bs);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-04-04  0:51 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-01 14:06 [Qemu-devel] [PATCH] qcow2: Patch for shrinking qcow2 disk image Jun Lee
2014-04-02  2:24 ` Fam Zheng
2014-04-03 11:28   ` Jun Lee
2014-04-04  0:51     ` Fam Zheng
  -- strict thread matches above, loose matches on Subject: below --
2014-04-01 14:03 Jun Li
2014-04-01 13:55 Jun Li
2014-04-01 13:48 Jun Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.