qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/5] Fix conversion from ISO to VMDK streamOptimized
@ 2014-02-11  3:28 Fam Zheng
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 1/5] qemu-img: Convert by cluster size if target is compressed Fam Zheng
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Fam Zheng @ 2014-02-11  3:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, jcody, gentoo.integer, stefanha

Previouly, conversion from ISO to VMDK with subformat=streamOptimized fails:

    $ ./qemu-img convert -O vmdk -o subformat=streamOptimized foo.iso bar.vmdk
    VMDK: can't write to allocated cluster for streamOptimized
    qemu-img: error while writing sector 64: Input/output error

Current code in qemu-img.c picks the normal convert loop for this case, rather
than the "compress == true" loop, which writes in target cluster size. In VMDK
streamOptimized, writes must be in cluster unit, because write to an allocated
cluster is not supported.

This series adds an is_compressed field in BlockDriverInfo, and use compressed
convertion loop if the block driver set this field to true.

Implement .bdrv_get_info and .bdrv_write_compressed in VMDK driver to fit into
this procedure.

v2: Rebase to current master.



Fam Zheng (5):
  qemu-img: Convert by cluster size if target is compressed
  vmdk: Implement .bdrv_write_compressed
  block: Change BlockDriverInfo.cluster_size to 64 bits
  vmdk: Implement .bdrv_get_info()
  mirror: Check for bdrv_get_info result

 block/mirror.c             |  4 ++--
 block/vmdk.c               | 33 +++++++++++++++++++++++++++++++++
 include/block/block.h      |  3 ++-
 qemu-img.c                 |  3 +++
 tests/qemu-iotests/059.out |  4 ++++
 5 files changed, 44 insertions(+), 3 deletions(-)

-- 
1.8.5.4

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

* [Qemu-devel] [PATCH v2 1/5] qemu-img: Convert by cluster size if target is compressed
  2014-02-11  3:28 [Qemu-devel] [PATCH v2 0/5] Fix conversion from ISO to VMDK streamOptimized Fam Zheng
@ 2014-02-11  3:28 ` Fam Zheng
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 2/5] vmdk: Implement .bdrv_write_compressed Fam Zheng
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Fam Zheng @ 2014-02-11  3:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, jcody, gentoo.integer, stefanha

If target block driver forces compression (bdi.is_compressed == true),
qemu-img convert needs to write by cluster size as well as "-c" option.

Particularly, this applies for converting to VMDK streamOptimized
format.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 include/block/block.h | 1 +
 qemu-img.c            | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/include/block/block.h b/include/block/block.h
index 963a61f..826b5da 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -34,6 +34,7 @@ typedef struct BlockDriverInfo {
      * opened with BDRV_O_UNMAP flag for this to work.
      */
     bool can_write_zeroes_with_unmap;
+    bool is_compressed;
 } BlockDriverInfo;
 
 typedef struct BlockFragInfo {
diff --git a/qemu-img.c b/qemu-img.c
index c989850..859b927 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1425,11 +1425,14 @@ static int img_convert(int argc, char **argv)
     cluster_sectors = 0;
     ret = bdrv_get_info(out_bs, &bdi);
     if (ret < 0) {
+        /* We don't care whether bdrv_get_info() fails or not unless we are to
+         * compress */
         if (compress) {
             error_report("could not get block driver info");
             goto out;
         }
     } else {
+        compress = compress || bdi.is_compressed;
         cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
     }
 
-- 
1.8.5.4

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

* [Qemu-devel] [PATCH v2 2/5] vmdk: Implement .bdrv_write_compressed
  2014-02-11  3:28 [Qemu-devel] [PATCH v2 0/5] Fix conversion from ISO to VMDK streamOptimized Fam Zheng
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 1/5] qemu-img: Convert by cluster size if target is compressed Fam Zheng
@ 2014-02-11  3:28 ` Fam Zheng
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 3/5] block: Change BlockDriverInfo.cluster_size to 64 bits Fam Zheng
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Fam Zheng @ 2014-02-11  3:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, jcody, gentoo.integer, stefanha

Add a wrapper function to support "compressed" path in qemu-img convert.
Only support streamOptimized subformat case for now (num_extents == 1
and extent compression is true).

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 block/vmdk.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/block/vmdk.c b/block/vmdk.c
index e809e2e..cf5a98f 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1457,6 +1457,19 @@ static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
     return ret;
 }
 
+static int vmdk_write_compressed(BlockDriverState *bs,
+                                 int64_t sector_num,
+                                 const uint8_t *buf,
+                                 int nb_sectors)
+{
+    BDRVVmdkState *s = bs->opaque;
+    if (s->num_extents == 1 && s->extents[0].compressed) {
+        return vmdk_write(bs, sector_num, buf, nb_sectors, false, false);
+    } else {
+        return -ENOTSUP;
+    }
+}
+
 static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
                                              int64_t sector_num,
                                              int nb_sectors,
@@ -2066,6 +2079,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_reopen_prepare          = vmdk_reopen_prepare,
     .bdrv_read                    = vmdk_co_read,
     .bdrv_write                   = vmdk_co_write,
+    .bdrv_write_compressed        = vmdk_write_compressed,
     .bdrv_co_write_zeroes         = vmdk_co_write_zeroes,
     .bdrv_close                   = vmdk_close,
     .bdrv_create                  = vmdk_create,
-- 
1.8.5.4

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

* [Qemu-devel] [PATCH v2 3/5] block: Change BlockDriverInfo.cluster_size to 64 bits
  2014-02-11  3:28 [Qemu-devel] [PATCH v2 0/5] Fix conversion from ISO to VMDK streamOptimized Fam Zheng
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 1/5] qemu-img: Convert by cluster size if target is compressed Fam Zheng
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 2/5] vmdk: Implement .bdrv_write_compressed Fam Zheng
@ 2014-02-11  3:28 ` Fam Zheng
  2014-02-27 13:06   ` Stefan Hajnoczi
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 4/5] vmdk: Implement .bdrv_get_info() Fam Zheng
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 5/5] mirror: Check for bdrv_get_info result Fam Zheng
  4 siblings, 1 reply; 7+ messages in thread
From: Fam Zheng @ 2014-02-11  3:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, jcody, gentoo.integer, stefanha

VMDK could have big cluster_size for monolithicFlat. It implements
.bdrv_get_info now, a 32 bit field is likely to overflow.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 include/block/block.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/block/block.h b/include/block/block.h
index 826b5da..3eb4e54 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -14,7 +14,7 @@ typedef struct BlockJob BlockJob;
 
 typedef struct BlockDriverInfo {
     /* in bytes, 0 if irrelevant */
-    int cluster_size;
+    int64_t cluster_size;
     /* offset at which the VM state can be saved (0 if not possible) */
     int64_t vm_state_offset;
     bool is_dirty;
-- 
1.8.5.4

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

* [Qemu-devel] [PATCH v2 4/5] vmdk: Implement .bdrv_get_info()
  2014-02-11  3:28 [Qemu-devel] [PATCH v2 0/5] Fix conversion from ISO to VMDK streamOptimized Fam Zheng
                   ` (2 preceding siblings ...)
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 3/5] block: Change BlockDriverInfo.cluster_size to 64 bits Fam Zheng
@ 2014-02-11  3:28 ` Fam Zheng
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 5/5] mirror: Check for bdrv_get_info result Fam Zheng
  4 siblings, 0 replies; 7+ messages in thread
From: Fam Zheng @ 2014-02-11  3:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, jcody, gentoo.integer, stefanha

This will return cluster_size and is_compressed to caller, if all the
extents has the same value (or there's only one extent). Otherwise
return -ENOTSUP.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 block/vmdk.c               | 19 +++++++++++++++++++
 tests/qemu-iotests/059.out |  4 ++++
 2 files changed, 23 insertions(+)

diff --git a/block/vmdk.c b/block/vmdk.c
index cf5a98f..63fe79c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -2033,6 +2033,24 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
     return spec_info;
 }
 
+static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    int i;
+    BDRVVmdkState *s = bs->opaque;
+    assert(s->num_extents);
+    bdi->is_compressed = s->extents[0].compressed;
+    bdi->cluster_size = s->extents[0].cluster_sectors << BDRV_SECTOR_BITS;
+    /* See if we have multiple extents but they have different cases */
+    for (i = 1; i < s->num_extents; i++) {
+        if (bdi->is_compressed != s->extents[i].compressed ||
+            bdi->cluster_size !=
+                s->extents[i].cluster_sectors << BDRV_SECTOR_BITS) {
+            return -ENOTSUP;
+        }
+    }
+    return 0;
+}
+
 static QEMUOptionParameter vmdk_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -2089,6 +2107,7 @@ static BlockDriver bdrv_vmdk = {
     .bdrv_has_zero_init           = vmdk_has_zero_init,
     .bdrv_get_specific_info       = vmdk_get_specific_info,
     .bdrv_refresh_limits          = vmdk_refresh_limits,
+    .bdrv_get_info                = vmdk_get_info,
 
     .create_options               = vmdk_create_options,
 };
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 4ffeb54..6d8e4c1 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -21,6 +21,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
 image: TEST_DIR/t.IMGFMT
 file format: IMGFMT
 virtual size: 2.0G (2147483648 bytes)
+cluster_size: 2147483648
 
 === Testing monolithicFlat with zeroed_grain ===
 qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
@@ -32,6 +33,7 @@ image: TEST_DIR/t.vmdk
 file format: vmdk
 virtual size: 1.0T (1073741824000 bytes)
 disk size: 16K
+cluster_size: 2147483648
 Format specific information:
     cid: XXXXXXXX
     parent cid: XXXXXXXX
@@ -2052,12 +2054,14 @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'TEST_DIR/t.IMGFMT'
 image: TEST_DIR/iotest-version3.IMGFMT
 file format: IMGFMT
 virtual size: 1.0G (1073741824 bytes)
+cluster_size: 65536
 
 === Testing 4TB monolithicFlat creation and IO ===
 Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=4398046511104
 image: TEST_DIR/iotest-version3.IMGFMT
 file format: IMGFMT
 virtual size: 4.0T (4398046511104 bytes)
+cluster_size: 4398046511104
 wrote 512/512 bytes at offset 966367641600
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 e100000000:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
-- 
1.8.5.4

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

* [Qemu-devel] [PATCH v2 5/5] mirror: Check for bdrv_get_info result
  2014-02-11  3:28 [Qemu-devel] [PATCH v2 0/5] Fix conversion from ISO to VMDK streamOptimized Fam Zheng
                   ` (3 preceding siblings ...)
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 4/5] vmdk: Implement .bdrv_get_info() Fam Zheng
@ 2014-02-11  3:28 ` Fam Zheng
  4 siblings, 0 replies; 7+ messages in thread
From: Fam Zheng @ 2014-02-11  3:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, jcody, gentoo.integer, stefanha

bdrv_get_info could fail. Add check before using the returned value.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 block/mirror.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 2a43334..bd3010b 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -325,8 +325,8 @@ static void coroutine_fn mirror_run(void *opaque)
     bdrv_get_backing_filename(s->target, backing_filename,
                               sizeof(backing_filename));
     if (backing_filename[0] && !s->target->backing_hd) {
-        bdrv_get_info(s->target, &bdi);
-        if (s->granularity < bdi.cluster_size) {
+        ret = bdrv_get_info(s->target, &bdi);
+        if (ret == 0 && s->granularity < bdi.cluster_size) {
             s->buf_size = MAX(s->buf_size, bdi.cluster_size);
             s->cow_bitmap = bitmap_new(length);
         }
-- 
1.8.5.4

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

* Re: [Qemu-devel] [PATCH v2 3/5] block: Change BlockDriverInfo.cluster_size to 64 bits
  2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 3/5] block: Change BlockDriverInfo.cluster_size to 64 bits Fam Zheng
@ 2014-02-27 13:06   ` Stefan Hajnoczi
  0 siblings, 0 replies; 7+ messages in thread
From: Stefan Hajnoczi @ 2014-02-27 13:06 UTC (permalink / raw)
  To: Fam Zheng; +Cc: kwolf, jcody, gentoo.integer, qemu-devel, stefanha

On Tue, Feb 11, 2014 at 11:28:37AM +0800, Fam Zheng wrote:
> VMDK could have big cluster_size for monolithicFlat. It implements
> .bdrv_get_info now, a 32 bit field is likely to overflow.
> 
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>  include/block/block.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/block/block.h b/include/block/block.h
> index 826b5da..3eb4e54 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -14,7 +14,7 @@ typedef struct BlockJob BlockJob;
>  
>  typedef struct BlockDriverInfo {
>      /* in bytes, 0 if irrelevant */
> -    int cluster_size;
> +    int64_t cluster_size;

Not sure if this commit is enough:

If the cluster size is really larger than 2 GB and a compressed image is
in use, then we will attempt 2 GB I/O.  There are also other codepaths
that use cluster_size and would similarly allocate 2 GB bounce buffers!

We need to think through what happens in those cases.  Should we refuse
after a certain size?  Will we need to enhance some code paths to
actually split up the bounce buffers (if possible)?

Stefan

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

end of thread, other threads:[~2014-02-27 13:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-11  3:28 [Qemu-devel] [PATCH v2 0/5] Fix conversion from ISO to VMDK streamOptimized Fam Zheng
2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 1/5] qemu-img: Convert by cluster size if target is compressed Fam Zheng
2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 2/5] vmdk: Implement .bdrv_write_compressed Fam Zheng
2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 3/5] block: Change BlockDriverInfo.cluster_size to 64 bits Fam Zheng
2014-02-27 13:06   ` Stefan Hajnoczi
2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 4/5] vmdk: Implement .bdrv_get_info() Fam Zheng
2014-02-11  3:28 ` [Qemu-devel] [PATCH v2 5/5] mirror: Check for bdrv_get_info result Fam Zheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).