summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--aio-posix.c5
-rw-r--r--aio-win32.c5
-rw-r--r--block.c160
-rw-r--r--block/iscsi.c37
-rw-r--r--block/qcow2-cluster.c2
-rw-r--r--block/qcow2-refcount.c22
-rw-r--r--block/qcow2-snapshot.c10
-rw-r--r--block/qcow2.c39
-rw-r--r--block/qcow2.h5
-rw-r--r--block/qed.c3
-rw-r--r--block/raw-aio.h3
-rw-r--r--block/raw-posix.c175
-rw-r--r--block/snapshot.c77
-rw-r--r--block/vdi.c1
-rw-r--r--block/vhdx.c13
-rw-r--r--block/vmdk.c66
-rw-r--r--block/vpc.c15
-rw-r--r--hw/scsi/scsi-disk.c154
-rw-r--r--include/block/block.h4
-rw-r--r--include/block/block_int.h7
-rw-r--r--include/block/coroutine.h7
-rw-r--r--include/block/snapshot.h15
-rw-r--r--qemu-coroutine-lock.c8
-rw-r--r--qemu-img-cmds.hx4
-rw-r--r--qemu-img.c169
-rw-r--r--qemu-img.texi12
-rw-r--r--qemu-nbd.c47
-rw-r--r--qemu-nbd.texi10
-rwxr-xr-xtests/qemu-iotests/0263
-rwxr-xr-xtests/qemu-iotests/0393
-rwxr-xr-xtests/qemu-iotests/04827
-rw-r--r--tests/qemu-iotests/048.out16
-rw-r--r--tests/qemu-iotests/051.out112
-rwxr-xr-xtests/qemu-iotests/0524
-rwxr-xr-xtests/qemu-iotests/058138
-rw-r--r--tests/qemu-iotests/058.out44
-rwxr-xr-xtests/qemu-iotests/0595
-rw-r--r--tests/qemu-iotests/059.out2012
-rwxr-xr-xtests/qemu-iotests/07486
-rw-r--r--tests/qemu-iotests/074.out18
-rwxr-xr-xtests/qemu-iotests/check3
-rw-r--r--tests/qemu-iotests/common37
-rw-r--r--tests/qemu-iotests/common.filter3
-rw-r--r--tests/qemu-iotests/common.rc28
-rw-r--r--tests/qemu-iotests/group4
-rw-r--r--tests/qemu-iotests/iotests.py3
-rw-r--r--tests/test-aio.c1
-rw-r--r--trace-events4
48 files changed, 3238 insertions, 388 deletions
diff --git a/aio-posix.c b/aio-posix.c
index bd06f33c78..f921d4f538 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -217,11 +217,6 @@ bool aio_poll(AioContext *ctx, bool blocking)
 
     ctx->walking_handlers--;
 
-    /* early return if we only have the aio_notify() fd */
-    if (ctx->pollfds->len == 1) {
-        return progress;
-    }
-
     /* wait until next event */
     ret = qemu_poll_ns((GPollFD *)ctx->pollfds->data,
                          ctx->pollfds->len,
diff --git a/aio-win32.c b/aio-win32.c
index f9cfbb75ac..23f4e5ba19 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -161,11 +161,6 @@ bool aio_poll(AioContext *ctx, bool blocking)
 
     ctx->walking_handlers--;
 
-    /* early return if we only have the aio_notify() fd */
-    if (count == 1) {
-        return progress;
-    }
-
     /* wait until next event */
     while (count > 0) {
         int ret;
diff --git a/block.c b/block.c
index 3d78581c63..13f001ad69 100644
--- a/block.c
+++ b/block.c
@@ -79,6 +79,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
                                                int64_t sector_num,
                                                QEMUIOVector *qiov,
                                                int nb_sectors,
+                                               BdrvRequestFlags flags,
                                                BlockDriverCompletionFunc *cb,
                                                void *opaque,
                                                bool is_write);
@@ -1556,13 +1557,8 @@ void bdrv_drain_all(void)
     BlockDriverState *bs;
 
     while (busy) {
-        /* FIXME: We do not have timer support here, so this is effectively
-         * a busy wait.
-         */
         QTAILQ_FOREACH(bs, &bdrv_states, list) {
-            if (bdrv_start_throttled_reqs(bs)) {
-                busy = true;
-            }
+            bdrv_start_throttled_reqs(bs);
         }
 
         busy = bdrv_requests_pending_all();
@@ -2770,14 +2766,21 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
     while (nb_sectors > 0 && !ret) {
         int num = nb_sectors;
 
-        /* align request */
-        if (bs->bl.write_zeroes_alignment &&
-            num >= bs->bl.write_zeroes_alignment &&
-            sector_num % bs->bl.write_zeroes_alignment) {
-            if (num > bs->bl.write_zeroes_alignment) {
+        /* Align request.  Block drivers can expect the "bulk" of the request
+         * to be aligned.
+         */
+        if (bs->bl.write_zeroes_alignment
+            && num > bs->bl.write_zeroes_alignment) {
+            if (sector_num % bs->bl.write_zeroes_alignment != 0) {
+                /* Make a small request up to the first aligned sector.  */
                 num = bs->bl.write_zeroes_alignment;
+                num -= sector_num % bs->bl.write_zeroes_alignment;
+            } else if ((sector_num + num) % bs->bl.write_zeroes_alignment != 0) {
+                /* Shorten the request to the last aligned sector.  num cannot
+                 * underflow because num > bs->bl.write_zeroes_alignment.
+                 */
+                num -= (sector_num + num) % bs->bl.write_zeroes_alignment;
             }
-            num -= sector_num % bs->bl.write_zeroes_alignment;
         }
 
         /* limit request size */
@@ -2795,16 +2798,20 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
             /* Fall back to bounce buffer if write zeroes is unsupported */
             iov.iov_len = num * BDRV_SECTOR_SIZE;
             if (iov.iov_base == NULL) {
-                /* allocate bounce buffer only once and ensure that it
-                 * is big enough for this and all future requests.
-                 */
-                size_t bufsize = num <= nb_sectors ? num : max_write_zeroes;
-                iov.iov_base = qemu_blockalign(bs, bufsize * BDRV_SECTOR_SIZE);
-                memset(iov.iov_base, 0, bufsize * BDRV_SECTOR_SIZE);
+                iov.iov_base = qemu_blockalign(bs, num * BDRV_SECTOR_SIZE);
+                memset(iov.iov_base, 0, num * BDRV_SECTOR_SIZE);
             }
             qemu_iovec_init_external(&qiov, &iov, 1);
 
             ret = drv->bdrv_co_writev(bs, sector_num, num, &qiov);
+
+            /* Keep bounce buffer around if it is big enough for all
+             * all future requests.
+             */
+            if (num < max_write_zeroes) {
+                qemu_vfree(iov.iov_base);
+                iov.iov_base = NULL;
+            }
         }
 
         sector_num += num;
@@ -2887,7 +2894,7 @@ int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs,
                                       int64_t sector_num, int nb_sectors,
                                       BdrvRequestFlags flags)
 {
-    trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors);
+    trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors, flags);
 
     if (!(bs->open_flags & BDRV_O_UNMAP)) {
         flags &= ~BDRV_REQ_MAY_UNMAP;
@@ -3669,7 +3676,7 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
 {
     trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque);
 
-    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors,
+    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, 0,
                                  cb, opaque, false);
 }
 
@@ -3679,7 +3686,18 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
 {
     trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque);
 
-    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors,
+    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, 0,
+                                 cb, opaque, true);
+}
+
+BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, BdrvRequestFlags flags,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    trace_bdrv_aio_write_zeroes(bs, sector_num, nb_sectors, flags, opaque);
+
+    return bdrv_co_aio_rw_vector(bs, sector_num, NULL, nb_sectors,
+                                 BDRV_REQ_ZERO_WRITE | flags,
                                  cb, opaque, true);
 }
 
@@ -3851,8 +3869,10 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
     /* Run the aio requests. */
     mcb->num_requests = num_reqs;
     for (i = 0; i < num_reqs; i++) {
-        bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
-            reqs[i].nb_sectors, multiwrite_cb, mcb);
+        bdrv_co_aio_rw_vector(bs, reqs[i].sector, reqs[i].qiov,
+                              reqs[i].nb_sectors, reqs[i].flags,
+                              multiwrite_cb, mcb,
+                              true);
     }
 
     return 0;
@@ -3994,10 +4014,10 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)
 
     if (!acb->is_write) {
         acb->req.error = bdrv_co_do_readv(bs, acb->req.sector,
-            acb->req.nb_sectors, acb->req.qiov, 0);
+            acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
     } else {
         acb->req.error = bdrv_co_do_writev(bs, acb->req.sector,
-            acb->req.nb_sectors, acb->req.qiov, 0);
+            acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
     }
 
     acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
@@ -4008,6 +4028,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
                                                int64_t sector_num,
                                                QEMUIOVector *qiov,
                                                int nb_sectors,
+                                               BdrvRequestFlags flags,
                                                BlockDriverCompletionFunc *cb,
                                                void *opaque,
                                                bool is_write)
@@ -4019,6 +4040,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
     acb->req.sector = sector_num;
     acb->req.nb_sectors = nb_sectors;
     acb->req.qiov = qiov;
+    acb->req.flags = flags;
     acb->is_write = is_write;
     acb->done = NULL;
 
@@ -4302,6 +4324,8 @@ static void coroutine_fn bdrv_discard_co_entry(void *opaque)
 int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
                                  int nb_sectors)
 {
+    int max_discard;
+
     if (!bs->drv) {
         return -ENOMEDIUM;
     } else if (bdrv_check_request(bs, sector_num, nb_sectors)) {
@@ -4317,55 +4341,55 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
         return 0;
     }
 
-    if (bs->drv->bdrv_co_discard) {
-        int max_discard = bs->bl.max_discard ?
-                          bs->bl.max_discard : MAX_DISCARD_DEFAULT;
+    if (!bs->drv->bdrv_co_discard && !bs->drv->bdrv_aio_discard) {
+        return 0;
+    }
 
-        while (nb_sectors > 0) {
-            int ret;
-            int num = nb_sectors;
+    max_discard = bs->bl.max_discard ?  bs->bl.max_discard : MAX_DISCARD_DEFAULT;
+    while (nb_sectors > 0) {
+        int ret;
+        int num = nb_sectors;
 
-            /* align request */
-            if (bs->bl.discard_alignment &&
-                num >= bs->bl.discard_alignment &&
-                sector_num % bs->bl.discard_alignment) {
-                if (num > bs->bl.discard_alignment) {
-                    num = bs->bl.discard_alignment;
-                }
-                num -= sector_num % bs->bl.discard_alignment;
+        /* align request */
+        if (bs->bl.discard_alignment &&
+            num >= bs->bl.discard_alignment &&
+            sector_num % bs->bl.discard_alignment) {
+            if (num > bs->bl.discard_alignment) {
+                num = bs->bl.discard_alignment;
             }
+            num -= sector_num % bs->bl.discard_alignment;
+        }
 
-            /* limit request size */
-            if (num > max_discard) {
-                num = max_discard;
-            }
+        /* limit request size */
+        if (num > max_discard) {
+            num = max_discard;
+        }
 
+        if (bs->drv->bdrv_co_discard) {
             ret = bs->drv->bdrv_co_discard(bs, sector_num, num);
-            if (ret) {
-                return ret;
+        } else {
+            BlockDriverAIOCB *acb;
+            CoroutineIOCompletion co = {
+                .coroutine = qemu_coroutine_self(),
+            };
+
+            acb = bs->drv->bdrv_aio_discard(bs, sector_num, nb_sectors,
+                                            bdrv_co_io_em_complete, &co);
+            if (acb == NULL) {
+                return -EIO;
+            } else {
+                qemu_coroutine_yield();
+                ret = co.ret;
             }
-
-            sector_num += num;
-            nb_sectors -= num;
         }
-        return 0;
-    } else if (bs->drv->bdrv_aio_discard) {
-        BlockDriverAIOCB *acb;
-        CoroutineIOCompletion co = {
-            .coroutine = qemu_coroutine_self(),
-        };
-
-        acb = bs->drv->bdrv_aio_discard(bs, sector_num, nb_sectors,
-                                        bdrv_co_io_em_complete, &co);
-        if (acb == NULL) {
-            return -EIO;
-        } else {
-            qemu_coroutine_yield();
-            return co.ret;
+        if (ret && ret != -ENOTSUP) {
+            return ret;
         }
-    } else {
-        return 0;
+
+        sector_num += num;
+        nb_sectors -= num;
     }
+    return 0;
 }
 
 int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
@@ -4684,7 +4708,6 @@ void bdrv_img_create(const char *filename, const char *fmt,
 {
     QEMUOptionParameter *param = NULL, *create_options = NULL;
     QEMUOptionParameter *backing_fmt, *backing_file, *size;
-    BlockDriverState *bs = NULL;
     BlockDriver *drv, *proto_drv;
     BlockDriver *backing_drv = NULL;
     Error *local_err = NULL;
@@ -4763,6 +4786,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
     size = get_option_parameter(param, BLOCK_OPT_SIZE);
     if (size && size->value.n == -1) {
         if (backing_file && backing_file->value.s) {
+            BlockDriverState *bs;
             uint64_t size;
             char buf[32];
             int back_flags;
@@ -4781,6 +4805,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
                                  error_get_pretty(local_err));
                 error_free(local_err);
                 local_err = NULL;
+                bdrv_unref(bs);
                 goto out;
             }
             bdrv_get_geometry(bs, &size);
@@ -4788,6 +4813,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
 
             snprintf(buf, sizeof(buf), "%" PRId64, size);
             set_option_parameter(param, BLOCK_OPT_SIZE, buf);
+
+            bdrv_unref(bs);
         } else {
             error_setg(errp, "Image creation needs a size parameter");
             goto out;
@@ -4818,9 +4845,6 @@ out:
     free_option_parameters(create_options);
     free_option_parameters(param);
 
-    if (bs) {
-        bdrv_unref(bs);
-    }
     if (error_is_set(&local_err)) {
         error_propagate(errp, local_err);
     }
diff --git a/block/iscsi.c b/block/iscsi.c
index b7b52381d6..829d444733 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -2,6 +2,7 @@
  * QEMU Block driver for iSCSI images
  *
  * Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
+ * Copyright (c) 2012-2013 Peter Lieven <pl@kamp.de>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -54,6 +55,7 @@ typedef struct IscsiLun {
     QEMUTimer *nop_timer;
     uint8_t lbpme;
     uint8_t lbprz;
+    uint8_t has_write_same;
     struct scsi_inquiry_logical_block_provisioning lbp;
     struct scsi_inquiry_block_limits bl;
     unsigned char *zeroblock;
@@ -975,8 +977,13 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
         return -EINVAL;
     }
 
-    if (!iscsilun->lbp.lbpws) {
-        /* WRITE SAME is not supported by the target */
+    if (!(flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->has_write_same) {
+        /* WRITE SAME without UNMAP is not supported by the target */
+        return -ENOTSUP;
+    }
+
+    if ((flags & BDRV_REQ_MAY_UNMAP) && !iscsilun->lbp.lbpws) {
+        /* WRITE SAME with UNMAP is not supported by the target */
         return -ENOTSUP;
     }
 
@@ -1011,6 +1018,14 @@ retry:
     }
 
     if (iTask.status != SCSI_STATUS_GOOD) {
+        if (iTask.status == SCSI_STATUS_CHECK_CONDITION &&
+            iTask.task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
+            iTask.task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
+            /* WRITE SAME is not supported by the target */
+            iscsilun->has_write_same = false;
+            return -ENOTSUP;
+        }
+
         return -EIO;
     }
 
@@ -1374,6 +1389,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     iscsilun->type = inq->periperal_device_type;
+    iscsilun->has_write_same = true;
 
     if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
         goto out;
@@ -1441,6 +1457,9 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
         }
         bs->bl.write_zeroes_alignment = sector_lun2qemu(iscsilun->bl.opt_unmap_gran,
                                                         iscsilun);
+
+        bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
+                                                     iscsilun);
     }
 
 #if defined(LIBISCSI_FEATURE_NOP_COUNTER)
@@ -1505,11 +1524,6 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
     return 0;
 }
 
-static int iscsi_has_zero_init(BlockDriverState *bs)
-{
-    return 0;
-}
-
 static int iscsi_create(const char *filename, QEMUOptionParameter *options,
                         Error **errp)
 {
@@ -1569,6 +1583,13 @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
     IscsiLun *iscsilun = bs->opaque;
     bdi->unallocated_blocks_are_zero = !!iscsilun->lbprz;
     bdi->can_write_zeroes_with_unmap = iscsilun->lbprz && iscsilun->lbp.lbpws;
+    /* Guess the internal cluster (page) size of the iscsi target by the means
+     * of opt_unmap_gran. Transfer the unmap granularity only if it has a
+     * reasonable size for bdi->cluster_size */
+    if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 64 * 1024 &&
+        iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {
+        bdi->cluster_size = iscsilun->bl.opt_unmap_gran * iscsilun->block_size;
+    }
     return 0;
 }
 
@@ -1608,8 +1629,6 @@ static BlockDriver bdrv_iscsi = {
     .bdrv_aio_writev = iscsi_aio_writev,
     .bdrv_aio_flush  = iscsi_aio_flush,
 
-    .bdrv_has_zero_init = iscsi_has_zero_init,
-
 #ifdef __linux__
     .bdrv_ioctl       = iscsi_ioctl,
     .bdrv_aio_ioctl   = iscsi_aio_ioctl,
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 11f9c50aa7..853408438a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1401,7 +1401,7 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
 
     /* Round start up and end down */
     offset = align_offset(offset, s->cluster_size);
-    end_offset &= ~(s->cluster_size - 1);
+    end_offset = start_of_cluster(s, end_offset);
 
     if (offset > end_offset) {
         return 0;
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 1ff43d0906..c974abe795 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -515,8 +515,8 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
             s->l2_table_cache);
     }
 
-    start = offset & ~(s->cluster_size - 1);
-    last = (offset + length - 1) & ~(s->cluster_size - 1);
+    start = start_of_cluster(s, offset);
+    last = start_of_cluster(s, offset + length - 1);
     for(cluster_offset = start; cluster_offset <= last;
         cluster_offset += s->cluster_size)
     {
@@ -724,7 +724,7 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
     }
  redo:
     free_in_cluster = s->cluster_size -
-        (s->free_byte_offset & (s->cluster_size - 1));
+        offset_into_cluster(s, s->free_byte_offset);
     if (size <= free_in_cluster) {
         /* enough space in current cluster */
         offset = s->free_byte_offset;
@@ -732,7 +732,7 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
         free_in_cluster -= size;
         if (free_in_cluster == 0)
             s->free_byte_offset = 0;
-        if ((offset & (s->cluster_size - 1)) != 0)
+        if (offset_into_cluster(s, offset) != 0)
             qcow2_update_cluster_refcount(bs, offset >> s->cluster_bits, 1,
                                           QCOW2_DISCARD_NEVER);
     } else {
@@ -740,7 +740,7 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
         if (offset < 0) {
             return offset;
         }
-        cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1);
+        cluster_offset = start_of_cluster(s, s->free_byte_offset);
         if ((cluster_offset + s->cluster_size) == offset) {
             /* we are lucky: contiguous data */
             offset = s->free_byte_offset;
@@ -1010,8 +1010,8 @@ static void inc_refcounts(BlockDriverState *bs,
     if (size <= 0)
         return;
 
-    start = offset & ~(s->cluster_size - 1);
-    last = (offset + size - 1) & ~(s->cluster_size - 1);
+    start = start_of_cluster(s, offset);
+    last = start_of_cluster(s, offset + size - 1);
     for(cluster_offset = start; cluster_offset <= last;
         cluster_offset += s->cluster_size) {
         k = cluster_offset >> s->cluster_bits;
@@ -1122,7 +1122,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
                 offset, s->cluster_size);
 
             /* Correct offsets are cluster aligned */
-            if (offset & (s->cluster_size - 1)) {
+            if (offset_into_cluster(s, offset)) {
                 fprintf(stderr, "ERROR offset=%" PRIx64 ": Cluster is not "
                     "properly aligned; L2 entry corrupted.\n", offset);
                 res->corruptions++;
@@ -1194,7 +1194,7 @@ static int check_refcounts_l1(BlockDriverState *bs,
                 l2_offset, s->cluster_size);
 
             /* L2 tables are cluster aligned */
-            if (l2_offset & (s->cluster_size - 1)) {
+            if (offset_into_cluster(s, l2_offset)) {
                 fprintf(stderr, "ERROR l2_offset=%" PRIx64 ": Table is not "
                     "cluster aligned; L1 entry corrupted\n", l2_offset);
                 res->corruptions++;
@@ -1423,7 +1423,7 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index,
     }
 
     /* update refcount table */
-    assert(!(new_offset & (s->cluster_size - 1)));
+    assert(!offset_into_cluster(s, new_offset));
     s->refcount_table[reftable_index] = new_offset;
     ret = write_reftable_entry(bs, reftable_index);
     if (ret < 0) {
@@ -1507,7 +1507,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
         cluster = offset >> s->cluster_bits;
 
         /* Refcount blocks are cluster aligned */
-        if (offset & (s->cluster_size - 1)) {
+        if (offset_into_cluster(s, offset)) {
             fprintf(stderr, "ERROR refcount block %" PRId64 " is not "
                 "cluster aligned; refcount table entry corrupted\n", i);
             res->corruptions++;
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 3529c683c6..ad8bf3dcd9 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -675,7 +675,10 @@ int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
     return s->nb_snapshots;
 }
 
-int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name)
+int qcow2_snapshot_load_tmp(BlockDriverState *bs,
+                            const char *snapshot_id,
+                            const char *name,
+                            Error **errp)
 {
     int i, snapshot_index;
     BDRVQcowState *s = bs->opaque;
@@ -687,8 +690,10 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name)
     assert(bs->read_only);
 
     /* Search the snapshot */
-    snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_name);
+    snapshot_index = find_snapshot_by_id_and_name(bs, snapshot_id, name);
     if (snapshot_index < 0) {
+        error_setg(errp,
+                   "Can't find snapshot");
         return -ENOENT;
     }
     sn = &s->snapshots[snapshot_index];
@@ -699,6 +704,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name)
 
     ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table, new_l1_bytes);
     if (ret < 0) {
+        error_setg(errp, "Failed to read l1 table for snapshot");
         g_free(new_l1_table);
         return ret;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index 8e2b6c7548..f29aa88671 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -718,6 +718,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     qemu_opts_del(opts);
+    bs->bl.write_zeroes_alignment = s->cluster_sectors;
 
     if (s->use_lazy_refcounts && s->qcow_version < 3) {
         error_setg(errp, "Lazy refcounts require a qcow2 image with at least "
@@ -1471,7 +1472,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
      * size for any qcow2 image.
      */
     BlockDriverState* bs;
-    QCowHeader header;
+    QCowHeader *header;
     uint8_t* refcount_table;
     Error *local_err = NULL;
     int ret;
@@ -1489,30 +1490,34 @@ static int qcow2_create2(const char *filename, int64_t total_size,
     }
 
     /* Write the header */
-    memset(&header, 0, sizeof(header));
-    header.magic = cpu_to_be32(QCOW_MAGIC);
-    header.version = cpu_to_be32(version);
-    header.cluster_bits = cpu_to_be32(cluster_bits);
-    header.size = cpu_to_be64(0);
-    header.l1_table_offset = cpu_to_be64(0);
-    header.l1_size = cpu_to_be32(0);
-    header.refcount_table_offset = cpu_to_be64(cluster_size);
-    header.refcount_table_clusters = cpu_to_be32(1);
-    header.refcount_order = cpu_to_be32(3 + REFCOUNT_SHIFT);
-    header.header_length = cpu_to_be32(sizeof(header));
+    QEMU_BUILD_BUG_ON((1 << MIN_CLUSTER_BITS) < sizeof(*header));
+    header = g_malloc0(cluster_size);
+    *header = (QCowHeader) {
+        .magic                      = cpu_to_be32(QCOW_MAGIC),
+        .version                    = cpu_to_be32(version),
+        .cluster_bits               = cpu_to_be32(cluster_bits),
+        .size                       = cpu_to_be64(0),
+        .l1_table_offset            = cpu_to_be64(0),
+        .l1_size                    = cpu_to_be32(0),
+        .refcount_table_offset      = cpu_to_be64(cluster_size),
+        .refcount_table_clusters    = cpu_to_be32(1),
+        .refcount_order             = cpu_to_be32(3 + REFCOUNT_SHIFT),
+        .header_length              = cpu_to_be32(sizeof(*header)),
+    };
 
     if (flags & BLOCK_FLAG_ENCRYPT) {
-        header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
+        header->crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
     } else {
-        header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
+        header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
     }
 
     if (flags & BLOCK_FLAG_LAZY_REFCOUNTS) {
-        header.compatible_features |=
+        header->compatible_features |=
             cpu_to_be64(QCOW2_COMPAT_LAZY_REFCOUNTS);
     }
 
-    ret = bdrv_pwrite(bs, 0, &header, sizeof(header));
+    ret = bdrv_pwrite(bs, 0, header, cluster_size);
+    g_free(header);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Could not write qcow2 header");
         goto out;
@@ -1893,6 +1898,8 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
 static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 {
     BDRVQcowState *s = bs->opaque;
+    bdi->unallocated_blocks_are_zero = true;
+    bdi->can_write_zeroes_with_unmap = (s->qcow_version >= 3);
     bdi->cluster_size = s->cluster_size;
     bdi->vm_state_offset = qcow2_vm_state_offset(s);
     return 0;
diff --git a/block/qcow2.h b/block/qcow2.h
index 922e19062a..303eb26629 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -488,7 +488,10 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
                           const char *name,
                           Error **errp);
 int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab);
-int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name);
+int qcow2_snapshot_load_tmp(BlockDriverState *bs,
+                            const char *snapshot_id,
+                            const char *name,
+                            Error **errp);
 
 void qcow2_free_snapshots(BlockDriverState *bs);
 int qcow2_read_snapshots(BlockDriverState *bs);
diff --git a/block/qed.c b/block/qed.c
index adc2736dd7..450a1fa2e9 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -495,6 +495,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
         }
     }
 
+    bs->bl.write_zeroes_alignment = s->header.cluster_size >> BDRV_SECTOR_BITS;
     s->need_check_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
                                             qed_need_check_timer_cb, s);
 
@@ -1475,6 +1476,8 @@ static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
     memset(bdi, 0, sizeof(*bdi));
     bdi->cluster_size = s->header.cluster_size;
     bdi->is_dirty = s->header.features & QED_F_NEED_CHECK;
+    bdi->unallocated_blocks_are_zero = true;
+    bdi->can_write_zeroes_with_unmap = true;
     return 0;
 }
 
diff --git a/block/raw-aio.h b/block/raw-aio.h
index c61f1595d9..7ad0a8a0a7 100644
--- a/block/raw-aio.h
+++ b/block/raw-aio.h
@@ -21,9 +21,10 @@
 #define QEMU_AIO_IOCTL        0x0004
 #define QEMU_AIO_FLUSH        0x0008
 #define QEMU_AIO_DISCARD      0x0010
+#define QEMU_AIO_WRITE_ZEROES 0x0020
 #define QEMU_AIO_TYPE_MASK \
         (QEMU_AIO_READ|QEMU_AIO_WRITE|QEMU_AIO_IOCTL|QEMU_AIO_FLUSH| \
-         QEMU_AIO_DISCARD)
+         QEMU_AIO_DISCARD|QEMU_AIO_WRITE_ZEROES)
 
 /* AIO flags */
 #define QEMU_AIO_MISALIGNED   0x1000
diff --git a/block/raw-posix.c b/block/raw-posix.c
index f836c8e745..10c6b34ba9 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -139,9 +139,11 @@ typedef struct BDRVRawState {
     void *aio_ctx;
 #endif
 #ifdef CONFIG_XFS
-    bool is_xfs : 1;
+    bool is_xfs:1;
 #endif
-    bool has_discard : 1;
+    bool has_discard:1;
+    bool has_write_zeroes:1;
+    bool discard_zeroes:1;
 } BDRVRawState;
 
 typedef struct BDRVRawReopenState {
@@ -283,6 +285,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
     Error *local_err = NULL;
     const char *filename;
     int fd, ret;
+    struct stat st;
 
     opts = qemu_opts_create_nofail(&raw_runtime_opts);
     qemu_opts_absorb_qdict(opts, options, &local_err);
@@ -323,10 +326,38 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
     }
 #endif
 
-    s->has_discard = 1;
+    s->has_discard = true;
+    s->has_write_zeroes = true;
+
+    if (fstat(s->fd, &st) < 0) {
+        error_setg_errno(errp, errno, "Could not stat file");
+        goto fail;
+    }
+    if (S_ISREG(st.st_mode)) {
+        s->discard_zeroes = true;
+    }
+    if (S_ISBLK(st.st_mode)) {
+#ifdef BLKDISCARDZEROES
+        unsigned int arg;
+        if (ioctl(s->fd, BLKDISCARDZEROES, &arg) == 0 && arg) {
+            s->discard_zeroes = true;
+        }
+#endif
+#ifdef __linux__
+        /* On Linux 3.10, BLKDISCARD leaves stale data in the page cache.  Do
+         * not rely on the contents of discarded blocks unless using O_DIRECT.
+         * Same for BLKZEROOUT.
+         */
+        if (!(bs->open_flags & BDRV_O_NOCACHE)) {
+            s->discard_zeroes = false;
+            s->has_write_zeroes = false;
+        }
+#endif
+    }
+
 #ifdef CONFIG_XFS
     if (platform_test_xfs_fd(s->fd)) {
-        s->is_xfs = 1;
+        s->is_xfs = true;
     }
 #endif
 
@@ -675,6 +706,23 @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
 }
 
 #ifdef CONFIG_XFS
+static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes)
+{
+    struct xfs_flock64 fl;
+
+    memset(&fl, 0, sizeof(fl));
+    fl.l_whence = SEEK_SET;
+    fl.l_start = offset;
+    fl.l_len = bytes;
+
+    if (xfsctl(NULL, s->fd, XFS_IOC_ZERO_RANGE, &fl) < 0) {
+        DEBUG_BLOCK_PRINT("cannot write zero range (%s)\n", strerror(errno));
+        return -errno;
+    }
+
+    return 0;
+}
+
 static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes)
 {
     struct xfs_flock64 fl;
@@ -693,13 +741,49 @@ static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes)
 }
 #endif
 
+static ssize_t handle_aiocb_write_zeroes(RawPosixAIOData *aiocb)
+{
+    int ret = -EOPNOTSUPP;
+    BDRVRawState *s = aiocb->bs->opaque;
+
+    if (s->has_write_zeroes == 0) {
+        return -ENOTSUP;
+    }
+
+    if (aiocb->aio_type & QEMU_AIO_BLKDEV) {
+#ifdef BLKZEROOUT
+        do {
+            uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes };
+            if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) {
+                return 0;
+            }
+        } while (errno == EINTR);
+
+        ret = -errno;
+#endif
+    } else {
+#ifdef CONFIG_XFS
+        if (s->is_xfs) {
+            return xfs_write_zeroes(s, aiocb->aio_offset, aiocb->aio_nbytes);
+        }
+#endif
+    }
+
+    if (ret == -ENODEV || ret == -ENOSYS || ret == -EOPNOTSUPP ||
+        ret == -ENOTTY) {
+        s->has_write_zeroes = false;
+        ret = -ENOTSUP;
+    }
+    return ret;
+}
+
 static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
 {
     int ret = -EOPNOTSUPP;
     BDRVRawState *s = aiocb->bs->opaque;
 
-    if (s->has_discard == 0) {
-        return 0;
+    if (!s->has_discard) {
+        return -ENOTSUP;
     }
 
     if (aiocb->aio_type & QEMU_AIO_BLKDEV) {
@@ -734,8 +818,8 @@ static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
 
     if (ret == -ENODEV || ret == -ENOSYS || ret == -EOPNOTSUPP ||
         ret == -ENOTTY) {
-        s->has_discard = 0;
-        ret = 0;
+        s->has_discard = false;
+        ret = -ENOTSUP;
     }
     return ret;
 }
@@ -777,6 +861,9 @@ static int aio_worker(void *arg)
     case QEMU_AIO_DISCARD:
         ret = handle_aiocb_discard(aiocb);
         break;
+    case QEMU_AIO_WRITE_ZEROES:
+        ret = handle_aiocb_write_zeroes(aiocb);
+        break;
     default:
         fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
         ret = -EINVAL;
@@ -787,6 +874,29 @@ static int aio_worker(void *arg)
     return ret;
 }
 
+static int paio_submit_co(BlockDriverState *bs, int fd,
+        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+        int type)
+{
+    RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
+    ThreadPool *pool;
+
+    acb->bs = bs;
+    acb->aio_type = type;
+    acb->aio_fildes = fd;
+
+    if (qiov) {
+        acb->aio_iov = qiov->iov;
+        acb->aio_niov = qiov->niov;
+    }
+    acb->aio_nbytes = nb_sectors * 512;
+    acb->aio_offset = sector_num * 512;
+
+    trace_paio_submit_co(sector_num, nb_sectors, type);
+    pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
+    return thread_pool_submit_co(pool, aio_worker, acb);
+}
+
 static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque, int type)
@@ -1199,6 +1309,31 @@ static coroutine_fn BlockDriverAIOCB *raw_aio_discard(BlockDriverState *bs,
                        cb, opaque, QEMU_AIO_DISCARD);
 }
 
+static int coroutine_fn raw_co_write_zeroes(
+    BlockDriverState *bs, int64_t sector_num,
+    int nb_sectors, BdrvRequestFlags flags)
+{
+    BDRVRawState *s = bs->opaque;
+
+    if (!(flags & BDRV_REQ_MAY_UNMAP)) {
+        return paio_submit_co(bs, s->fd, sector_num, NULL, nb_sectors,
+                              QEMU_AIO_WRITE_ZEROES);
+    } else if (s->discard_zeroes) {
+        return paio_submit_co(bs, s->fd, sector_num, NULL, nb_sectors,
+                              QEMU_AIO_DISCARD);
+    }
+    return -ENOTSUP;
+}
+
+static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    BDRVRawState *s = bs->opaque;
+
+    bdi->unallocated_blocks_are_zero = s->discard_zeroes;
+    bdi->can_write_zeroes_with_unmap = s->discard_zeroes;
+    return 0;
+}
+
 static QEMUOptionParameter raw_create_options[] = {
     {
         .name = BLOCK_OPT_SIZE,
@@ -1222,6 +1357,7 @@ static BlockDriver bdrv_file = {
     .bdrv_create = raw_create,
     .bdrv_has_zero_init = bdrv_has_zero_init_1,
     .bdrv_co_get_block_status = raw_co_get_block_status,
+    .bdrv_co_write_zeroes = raw_co_write_zeroes,
 
     .bdrv_aio_readv = raw_aio_readv,
     .bdrv_aio_writev = raw_aio_writev,
@@ -1230,6 +1366,7 @@ static BlockDriver bdrv_file = {
 
     .bdrv_truncate = raw_truncate,
     .bdrv_getlength = raw_getlength,
+    .bdrv_get_info = raw_get_info,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
@@ -1525,6 +1662,26 @@ static coroutine_fn BlockDriverAIOCB *hdev_aio_discard(BlockDriverState *bs,
                        cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
 }
 
+static coroutine_fn int hdev_co_write_zeroes(BlockDriverState *bs,
+    int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
+{
+    BDRVRawState *s = bs->opaque;
+    int rc;
+
+    rc = fd_open(bs);
+    if (rc < 0) {
+        return rc;
+    }
+    if (!(flags & BDRV_REQ_MAY_UNMAP)) {
+        return paio_submit_co(bs, s->fd, sector_num, NULL, nb_sectors,
+                              QEMU_AIO_WRITE_ZEROES|QEMU_AIO_BLKDEV);
+    } else if (s->discard_zeroes) {
+        return paio_submit_co(bs, s->fd, sector_num, NULL, nb_sectors,
+                              QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
+    }
+    return -ENOTSUP;
+}
+
 static int hdev_create(const char *filename, QEMUOptionParameter *options,
                        Error **errp)
 {
@@ -1577,6 +1734,7 @@ static BlockDriver bdrv_host_device = {
     .bdrv_reopen_abort   = raw_reopen_abort,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
+    .bdrv_co_write_zeroes = hdev_co_write_zeroes,
 
     .bdrv_aio_readv	= raw_aio_readv,
     .bdrv_aio_writev	= raw_aio_writev,
@@ -1585,6 +1743,7 @@ static BlockDriver bdrv_host_device = {
 
     .bdrv_truncate      = raw_truncate,
     .bdrv_getlength	= raw_getlength,
+    .bdrv_get_info = raw_get_info,
     .bdrv_get_allocated_file_size
                         = raw_get_allocated_file_size,
 
diff --git a/block/snapshot.c b/block/snapshot.c
index a05c0c0be0..9047f8ddc9 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -25,6 +25,24 @@
 #include "block/snapshot.h"
 #include "block/block_int.h"
 
+QemuOptsList internal_snapshot_opts = {
+    .name = "snapshot",
+    .head = QTAILQ_HEAD_INITIALIZER(internal_snapshot_opts.head),
+    .desc = {
+        {
+            .name = SNAPSHOT_OPT_ID,
+            .type = QEMU_OPT_STRING,
+            .help = "snapshot id"
+        },{
+            .name = SNAPSHOT_OPT_NAME,
+            .type = QEMU_OPT_STRING,
+            .help = "snapshot name"
+        },{
+            /* end of list */
+        }
+    },
+};
+
 int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
                        const char *name)
 {
@@ -194,7 +212,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
  * If only @snapshot_id is specified, delete the first one with id
  * @snapshot_id.
  * If only @name is specified, delete the first one with name @name.
- * if none is specified, return -ENINVAL.
+ * if none is specified, return -EINVAL.
  *
  * Returns: 0 on success, -errno on failure. If @bs is not inserted, return
  * -ENOMEDIUM. If @snapshot_id and @name are both NULL, return -EINVAL. If @bs
@@ -265,18 +283,71 @@ int bdrv_snapshot_list(BlockDriverState *bs,
     return -ENOTSUP;
 }
 
+/**
+ * Temporarily load an internal snapshot by @snapshot_id and @name.
+ * @bs: block device used in the operation
+ * @snapshot_id: unique snapshot ID, or NULL
+ * @name: snapshot name, or NULL
+ * @errp: location to store error
+ *
+ * If both @snapshot_id and @name are specified, load the first one with
+ * id @snapshot_id and name @name.
+ * If only @snapshot_id is specified, load the first one with id
+ * @snapshot_id.
+ * If only @name is specified, load the first one with name @name.
+ * if none is specified, return -EINVAL.
+ *
+ * Returns: 0 on success, -errno on fail. If @bs is not inserted, return
+ * -ENOMEDIUM. If @bs is not readonly, return -EINVAL. If @bs did not support
+ * internal snapshot, return -ENOTSUP. If qemu can't find a matching @id and
+ * @name, return -ENOENT. If @errp != NULL, it will always be filled on
+ * failure.
+ */
 int bdrv_snapshot_load_tmp(BlockDriverState *bs,
-        const char *snapshot_name)
+                           const char *snapshot_id,
+                           const char *name,
+                           Error **errp)
 {
     BlockDriver *drv = bs->drv;
+
     if (!drv) {
+        error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
         return -ENOMEDIUM;
     }
+    if (!snapshot_id && !name) {
+        error_setg(errp, "snapshot_id and name are both NULL");
+        return -EINVAL;
+    }
     if (!bs->read_only) {
+        error_setg(errp, "Device is not readonly");
         return -EINVAL;
     }
     if (drv->bdrv_snapshot_load_tmp) {
-        return drv->bdrv_snapshot_load_tmp(bs, snapshot_name);
+        return drv->bdrv_snapshot_load_tmp(bs, snapshot_id, name, errp);
     }
+    error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+              drv->format_name, bdrv_get_device_name(bs),
+              "temporarily load internal snapshot");
     return -ENOTSUP;
 }
+
+int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
+                                         const char *id_or_name,
+                                         Error **errp)
+{
+    int ret;
+    Error *local_err = NULL;
+
+    ret = bdrv_snapshot_load_tmp(bs, id_or_name, NULL, &local_err);
+    if (ret == -ENOENT || ret == -EINVAL) {
+        error_free(local_err);
+        local_err = NULL;
+        ret = bdrv_snapshot_load_tmp(bs, NULL, id_or_name, &local_err);
+    }
+
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+    }
+
+    return ret;
+}
diff --git a/block/vdi.c b/block/vdi.c
index b6ec0020dc..2d7490f173 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -331,6 +331,7 @@ static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
     logout("\n");
     bdi->cluster_size = s->block_size;
     bdi->vm_state_offset = 0;
+    bdi->unallocated_blocks_are_zero = true;
     return 0;
 }
 
diff --git a/block/vhdx.c b/block/vhdx.c
index 7d1af9663b..67bbe103a1 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1043,6 +1043,18 @@ static void vhdx_block_translate(BDRVVHDXState *s, int64_t sector_num,
 }
 
 
+static int vhdx_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    BDRVVHDXState *s = bs->opaque;
+
+    bdi->cluster_size = s->block_size;
+
+    bdi->unallocated_blocks_are_zero =
+        (s->params.data_bits & VHDX_PARAMS_HAS_PARENT) == 0;
+
+    return 0;
+}
+
 
 static coroutine_fn int vhdx_co_readv(BlockDriverState *bs, int64_t sector_num,
                                       int nb_sectors, QEMUIOVector *qiov)
@@ -1885,6 +1897,7 @@ static BlockDriver bdrv_vhdx = {
     .bdrv_co_readv          = vhdx_co_readv,
     .bdrv_co_writev         = vhdx_co_writev,
     .bdrv_create            = vhdx_create,
+    .bdrv_get_info          = vhdx_get_info,
 
     .create_options         = vhdx_create_options,
 };
diff --git a/block/vmdk.c b/block/vmdk.c
index 88d09e3e16..0734bc200c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -428,6 +428,10 @@ static int vmdk_add_extent(BlockDriverState *bs,
     extent->l2_size = l2_size;
     extent->cluster_sectors = flat ? sectors : cluster_sectors;
 
+    if (!flat) {
+        bs->bl.write_zeroes_alignment =
+            MAX(bs->bl.write_zeroes_alignment, cluster_sectors);
+    }
     if (s->num_extents > 1) {
         extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
     } else {
@@ -1596,7 +1600,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
                        Error **errp)
 {
     int fd, idx = 0;
-    char desc[BUF_SIZE];
+    char *desc = NULL;
     int64_t total_size = 0, filesize;
     const char *adapter_type = NULL;
     const char *backing_file = NULL;
@@ -1604,7 +1608,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
     int flags = 0;
     int ret = 0;
     bool flat, split, compress;
-    char ext_desc_lines[BUF_SIZE] = "";
+    GString *ext_desc_lines;
     char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
     const int64_t split_size = 0x80000000;  /* VMDK has constant split size */
     const char *desc_extent_line;
@@ -1632,8 +1636,11 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
         "ddb.geometry.sectors = \"63\"\n"
         "ddb.adapterType = \"%s\"\n";
 
+    ext_desc_lines = g_string_new(NULL);
+
     if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) {
-        return -EINVAL;
+        ret = -EINVAL;
+        goto exit;
     }
     /* Read out options */
     while (options && options->name) {
@@ -1659,7 +1666,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
                strcmp(adapter_type, "lsilogic") &&
                strcmp(adapter_type, "legacyESX")) {
         error_setg(errp, "Unknown adapter type: '%s'", adapter_type);
-        return -EINVAL;
+        ret = -EINVAL;
+        goto exit;
     }
     if (strcmp(adapter_type, "ide") != 0) {
         /* that's the number of heads with which vmware operates when
@@ -1675,7 +1683,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
                strcmp(fmt, "twoGbMaxExtentFlat") &&
                strcmp(fmt, "streamOptimized")) {
         error_setg(errp, "Unknown subformat: '%s'", fmt);
-        return -EINVAL;
+        ret = -EINVAL;
+        goto exit;
     }
     split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
               strcmp(fmt, "twoGbMaxExtentSparse"));
@@ -1689,22 +1698,25 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
     }
     if (flat && backing_file) {
         error_setg(errp, "Flat image can't have backing file");
-        return -ENOTSUP;
+        ret = -ENOTSUP;
+        goto exit;
     }
     if (flat && zeroed_grain) {
         error_setg(errp, "Flat image can't enable zeroed grain");
-        return -ENOTSUP;
+        ret = -ENOTSUP;
+        goto exit;
     }
     if (backing_file) {
         BlockDriverState *bs = bdrv_new("");
         ret = bdrv_open(bs, backing_file, NULL, BDRV_O_NO_BACKING, NULL, errp);
         if (ret != 0) {
             bdrv_unref(bs);
-            return ret;
+            goto exit;
         }
         if (strcmp(bs->drv->format_name, "vmdk")) {
             bdrv_unref(bs);
-            return -EINVAL;
+            ret = -EINVAL;
+            goto exit;
         }
         parent_cid = vmdk_read_cid(bs, 0);
         bdrv_unref(bs);
@@ -1738,25 +1750,27 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 
         if (vmdk_create_extent(ext_filename, size,
                                flat, compress, zeroed_grain)) {
-            return -EINVAL;
+            ret = -EINVAL;
+            goto exit;
         }
         filesize -= size;
 
         /* Format description line */
         snprintf(desc_line, sizeof(desc_line),
                     desc_extent_line, size / 512, desc_filename);
-        pstrcat(ext_desc_lines, sizeof(ext_desc_lines), desc_line);
+        g_string_append(ext_desc_lines, desc_line);
     }
     /* generate descriptor file */
-    snprintf(desc, sizeof(desc), desc_template,
-            (unsigned int)time(NULL),
-            parent_cid,
-            fmt,
-            parent_desc_line,
-            ext_desc_lines,
-            (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
-            total_size / (int64_t)(63 * number_heads * 512), number_heads,
-                adapter_type);
+    desc = g_strdup_printf(desc_template,
+                           (unsigned int)time(NULL),
+                           parent_cid,
+                           fmt,
+                           parent_desc_line,
+                           ext_desc_lines->str,
+                           (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
+                           total_size / (int64_t)(63 * number_heads * 512),
+                           number_heads,
+                           adapter_type);
     if (split || flat) {
         fd = qemu_open(filename,
                        O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
@@ -1767,21 +1781,25 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
                        0644);
     }
     if (fd < 0) {
-        return -errno;
+        ret = -errno;
+        goto exit;
     }
     /* the descriptor offset = 0x200 */
     if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) {
         ret = -errno;
-        goto exit;
+        goto close_exit;
     }
     ret = qemu_write_full(fd, desc, strlen(desc));
     if (ret != strlen(desc)) {
         ret = -errno;
-        goto exit;
+        goto close_exit;
     }
     ret = 0;
-exit:
+close_exit:
     qemu_close(fd);
+exit:
+    g_free(desc);
+    g_string_free(ext_desc_lines, true);
     return ret;
 }
 
diff --git a/block/vpc.c b/block/vpc.c
index 577cc45992..1d326cbf44 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -455,6 +455,19 @@ fail:
     return -1;
 }
 
+static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+    BDRVVPCState *s = (BDRVVPCState *)bs->opaque;
+    VHDFooter *footer = (VHDFooter *) s->footer_buf;
+
+    if (cpu_to_be32(footer->type) != VHD_FIXED) {
+        bdi->cluster_size = s->block_size;
+    }
+
+    bdi->unallocated_blocks_are_zero = true;
+    return 0;
+}
+
 static int vpc_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
@@ -857,6 +870,8 @@ static BlockDriver bdrv_vpc = {
     .bdrv_read              = vpc_co_read,
     .bdrv_write             = vpc_co_write,
 
+    .bdrv_get_info          = vpc_get_info,
+
     .create_options         = vpc_create_options,
     .bdrv_has_zero_init     = vpc_has_zero_init,
 };
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 74e6a14c29..efadfc023f 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -41,6 +41,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 #include <scsi/sg.h>
 #endif
 
+#define SCSI_WRITE_SAME_MAX         524288
 #define SCSI_DMA_BUF_SIZE           131072
 #define SCSI_MAX_INQUIRY_LEN        256
 #define SCSI_MAX_MODE_LEN           256
@@ -634,6 +635,8 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             buflen = 0x40;
             memset(outbuf + 4, 0, buflen - 4);
 
+            outbuf[4] = 0x1; /* wsnz */
+
             /* optimal transfer length granularity */
             outbuf[6] = (min_io_size >> 8) & 0xff;
             outbuf[7] = min_io_size & 0xff;
@@ -1543,10 +1546,16 @@ done:
 
 static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
 {
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
     uint8_t *p = inbuf;
     int len = r->req.cmd.xfer;
     UnmapCBData *data;
 
+    /* Reject ANCHOR=1.  */
+    if (r->req.cmd.buf[1] & 0x1) {
+        goto invalid_field;
+    }
+
     if (len < 8) {
         goto invalid_param_len;
     }
@@ -1560,6 +1569,11 @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
         goto invalid_param_len;
     }
 
+    if (bdrv_is_read_only(s->qdev.conf.bs)) {
+        scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
+        return;
+    }
+
     data = g_new0(UnmapCBData, 1);
     data->r = r;
     data->inbuf = &p[8];
@@ -1572,6 +1586,115 @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
 
 invalid_param_len:
     scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
+    return;
+
+invalid_field:
+    scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
+}
+
+typedef struct WriteSameCBData {
+    SCSIDiskReq *r;
+    int64_t sector;
+    int nb_sectors;
+    QEMUIOVector qiov;
+    struct iovec iov;
+} WriteSameCBData;
+
+static void scsi_write_same_complete(void *opaque, int ret)
+{
+    WriteSameCBData *data = opaque;
+    SCSIDiskReq *r = data->r;
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
+    assert(r->req.aiocb != NULL);
+    r->req.aiocb = NULL;
+    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    if (r->req.io_canceled) {
+        goto done;
+    }
+
+    if (ret < 0) {
+        if (scsi_handle_rw_error(r, -ret)) {
+            goto done;
+        }
+    }
+
+    data->nb_sectors -= data->iov.iov_len / 512;
+    data->sector += data->iov.iov_len / 512;
+    data->iov.iov_len = MIN(data->nb_sectors * 512, data->iov.iov_len);
+    if (data->iov.iov_len) {
+        bdrv_acct_start(s->qdev.conf.bs, &r->acct, data->iov.iov_len, BDRV_ACCT_WRITE);
+        r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector,
+                                       &data->qiov, data->iov.iov_len / 512,
+                                       scsi_write_same_complete, r);
+        return;
+    }
+
+    scsi_req_complete(&r->req, GOOD);
+
+done:
+    if (!r->req.io_canceled) {
+        scsi_req_unref(&r->req);
+    }
+    qemu_vfree(data->iov.iov_base);
+    g_free(data);
+}
+
+static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
+{
+    SCSIRequest *req = &r->req;
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+    uint32_t nb_sectors = scsi_data_cdb_length(r->req.cmd.buf);
+    WriteSameCBData *data;
+    uint8_t *buf;
+    int i;
+
+    /* Fail if PBDATA=1 or LBDATA=1 or ANCHOR=1.  */
+    if (nb_sectors == 0 || (req->cmd.buf[1] & 0x16)) {
+        scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
+        return;
+    }
+
+    if (bdrv_is_read_only(s->qdev.conf.bs)) {
+        scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
+        return;
+    }
+    if (!check_lba_range(s, r->req.cmd.lba, nb_sectors)) {
+        scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
+        return;
+    }
+
+    if (buffer_is_zero(inbuf, s->qdev.blocksize)) {
+        int flags = (req->cmd.buf[1] & 0x8) ? BDRV_REQ_MAY_UNMAP : 0;
+
+        /* The request is used as the AIO opaque value, so add a ref.  */
+        scsi_req_ref(&r->req);
+        bdrv_acct_start(s->qdev.conf.bs, &r->acct, nb_sectors * s->qdev.blocksize,
+                        BDRV_ACCT_WRITE);
+        r->req.aiocb = bdrv_aio_write_zeroes(s->qdev.conf.bs,
+                                             r->req.cmd.lba * (s->qdev.blocksize / 512),
+                                             nb_sectors * (s->qdev.blocksize / 512),
+                                             flags, scsi_aio_complete, r);
+        return;
+    }
+
+    data = g_new0(WriteSameCBData, 1);
+    data->r = r;
+    data->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
+    data->nb_sectors = nb_sectors * (s->qdev.blocksize / 512);
+    data->iov.iov_len = MIN(data->nb_sectors * 512, SCSI_WRITE_SAME_MAX);
+    data->iov.iov_base = buf = qemu_blockalign(s->qdev.conf.bs, data->iov.iov_len);
+    qemu_iovec_init_external(&data->qiov, &data->iov, 1);
+
+    for (i = 0; i < data->iov.iov_len; i += s->qdev.blocksize) {
+        memcpy(&buf[i], inbuf, s->qdev.blocksize);
+    }
+
+    scsi_req_ref(&r->req);
+    bdrv_acct_start(s->qdev.conf.bs, &r->acct, data->iov.iov_len, BDRV_ACCT_WRITE);
+    r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector,
+                                   &data->qiov, data->iov.iov_len / 512,
+                                   scsi_write_same_complete, data);
 }
 
 static void scsi_disk_emulate_write_data(SCSIRequest *req)
@@ -1597,6 +1720,10 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req)
         scsi_disk_emulate_unmap(r, r->iov.iov_base);
         break;
 
+    case WRITE_SAME_10:
+    case WRITE_SAME_16:
+        scsi_disk_emulate_write_same(r, r->iov.iov_base);
+        break;
     default:
         abort();
     }
@@ -1839,29 +1966,10 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         break;
     case WRITE_SAME_10:
     case WRITE_SAME_16:
-        nb_sectors = scsi_data_cdb_length(r->req.cmd.buf);
-        if (bdrv_is_read_only(s->qdev.conf.bs)) {
-            scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
-            return 0;
-        }
-        if (!check_lba_range(s, r->req.cmd.lba, nb_sectors)) {
-            goto illegal_lba;
-        }
-
-        /*
-         * We only support WRITE SAME with the unmap bit set for now.
-         */
-        if (!(req->cmd.buf[1] & 0x8)) {
-            goto illegal_request;
-        }
-
-        /* The request is used as the AIO opaque value, so add a ref.  */
-        scsi_req_ref(&r->req);
-        r->req.aiocb = bdrv_aio_discard(s->qdev.conf.bs,
-                                        r->req.cmd.lba * (s->qdev.blocksize / 512),
-                                        nb_sectors * (s->qdev.blocksize / 512),
-                                        scsi_aio_complete, r);
-        return 0;
+        DPRINTF("WRITE SAME %d (len %lu)\n",
+                req->cmd.buf[0] == WRITE_SAME_10 ? 10 : 16,
+                (long)r->req.cmd.xfer);
+        break;
     default:
         DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
         scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
diff --git a/include/block/block.h b/include/block/block.h
index 5beccbf1cf..36efaeac2d 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -216,6 +216,9 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
                const uint8_t *buf, int nb_sectors);
 int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
                int nb_sectors, BdrvRequestFlags flags);
+BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num,
+                                        int nb_sectors, BdrvRequestFlags flags,
+                                        BlockDriverCompletionFunc *cb, void *opaque);
 int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags);
 int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov);
 int bdrv_pread(BlockDriverState *bs, int64_t offset,
@@ -311,6 +314,7 @@ typedef struct BlockRequest {
     /* Fields to be filled by multiwrite caller */
     int64_t sector;
     int nb_sectors;
+    int flags;
     QEMUIOVector *qiov;
     BlockDriverCompletionFunc *cb;
     void *opaque;
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 773899b500..8b132d7178 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -176,7 +176,9 @@ struct BlockDriver {
     int (*bdrv_snapshot_list)(BlockDriverState *bs,
                               QEMUSnapshotInfo **psn_info);
     int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,
-                                  const char *snapshot_name);
+                                  const char *snapshot_id,
+                                  const char *name,
+                                  Error **errp);
     int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
     ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs);
 
@@ -245,6 +247,9 @@ typedef struct BlockLimits {
 
     /* optimal alignment for write zeroes requests in sectors */
     int64_t write_zeroes_alignment;
+
+    /* optimal transfer length in sectors */
+    int opt_transfer_length;
 } BlockLimits;
 
 /*
diff --git a/include/block/coroutine.h b/include/block/coroutine.h
index 4d5c0cfdd7..a1797ae3d8 100644
--- a/include/block/coroutine.h
+++ b/include/block/coroutine.h
@@ -105,7 +105,6 @@ bool qemu_in_coroutine(void);
  */
 typedef struct CoQueue {
     QTAILQ_HEAD(, Coroutine) entries;
-    AioContext *ctx;
 } CoQueue;
 
 /**
@@ -121,12 +120,6 @@ void qemu_co_queue_init(CoQueue *queue);
 void coroutine_fn qemu_co_queue_wait(CoQueue *queue);
 
 /**
- * Adds the current coroutine to the head of the CoQueue and transfers control to the
- * caller of the coroutine.
- */
-void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue);
-
-/**
  * Restarts the next coroutine in the CoQueue and removes it from the queue.
  *
  * Returns true if a coroutine was restarted, false if the queue is empty.
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
index 012bf226d3..770d9bbc8c 100644
--- a/include/block/snapshot.h
+++ b/include/block/snapshot.h
@@ -27,6 +27,14 @@
 
 #include "qemu-common.h"
 #include "qapi/error.h"
+#include "qemu/option.h"
+
+
+#define SNAPSHOT_OPT_BASE       "snapshot."
+#define SNAPSHOT_OPT_ID         "snapshot.id"
+#define SNAPSHOT_OPT_NAME       "snapshot.name"
+
+extern QemuOptsList internal_snapshot_opts;
 
 typedef struct QEMUSnapshotInfo {
     char id_str[128]; /* unique snapshot id */
@@ -61,5 +69,10 @@ void bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
 int bdrv_snapshot_list(BlockDriverState *bs,
                        QEMUSnapshotInfo **psn_info);
 int bdrv_snapshot_load_tmp(BlockDriverState *bs,
-                           const char *snapshot_name);
+                           const char *snapshot_id,
+                           const char *name,
+                           Error **errp);
+int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
+                                         const char *id_or_name,
+                                         Error **errp);
 #endif
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index aeb33b9118..e4860ae42f 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -41,14 +41,6 @@ void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
     assert(qemu_in_coroutine());
 }
 
-void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue)
-{
-    Coroutine *self = qemu_coroutine_self();
-    QTAILQ_INSERT_HEAD(&queue->entries, self, co_queue_next);
-    qemu_coroutine_yield();
-    assert(qemu_in_coroutine());
-}
-
 /**
  * qemu_co_queue_run_restart:
  *
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index da1d965f3e..d02960921a 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -34,9 +34,9 @@ STEXI
 ETEXI
 
 DEF("convert", img_convert,
-    "convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename")
+    "convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename")
 STEXI
-@item convert [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
+@item convert [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
 ETEXI
 
 DEF("info", img_info,
diff --git a/qemu-img.c b/qemu-img.c
index dc0c2f0ed3..7dfe982b0c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -93,6 +93,11 @@ static void help(void)
            "  'options' is a comma separated list of format specific options in a\n"
            "    name=value format. Use -o ? for an overview of the options supported by the\n"
            "    used format\n"
+           "  'snapshot_param' is param used for internal snapshot, format\n"
+           "    is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
+           "    '[ID_OR_NAME]'\n"
+           "  'snapshot_id_or_name' is deprecated, use 'snapshot_param'\n"
+           "    instead\n"
            "  '-c' indicates that target image must be compressed (qcow format only)\n"
            "  '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
            "       match exactly. The image doesn't need a working backing file before\n"
@@ -105,7 +110,6 @@ static void help(void)
            "       conversion. If the number of bytes is 0, the source will not be scanned for\n"
            "       unallocated or zero sectors, and the destination image will always be\n"
            "       fully allocated\n"
-           "       images will always be fully allocated\n"
            "  '--output' takes the format in which the output must be done (human or json)\n"
            "  '-n' skips the target volume creation (useful if the volume is created\n"
            "       prior to running qemu-img)\n"
@@ -1125,25 +1129,27 @@ out3:
 
 static int img_convert(int argc, char **argv)
 {
-    int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size,
-        cluster_sectors, skip_create;
+    int c, n, n1, bs_n, bs_i, compress, cluster_sectors, skip_create;
+    int64_t ret = 0;
     int progress = 0, flags;
     const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
     BlockDriver *drv, *proto_drv;
     BlockDriverState **bs = NULL, *out_bs = NULL;
-    int64_t total_sectors, nb_sectors, sector_num, bs_offset;
+    int64_t total_sectors, nb_sectors, sector_num, bs_offset,
+            sector_num_next_status = 0;
     uint64_t bs_sectors;
     uint8_t * buf = NULL;
+    size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE;
     const uint8_t *buf1;
     BlockDriverInfo bdi;
     QEMUOptionParameter *param = NULL, *create_options = NULL;
     QEMUOptionParameter *out_baseimg_param;
     char *options = NULL;
     const char *snapshot_name = NULL;
-    float local_progress = 0;
     int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
     bool quiet = false;
     Error *local_err = NULL;
+    QemuOpts *sn_opts = NULL;
 
     fmt = NULL;
     out_fmt = "raw";
@@ -1152,7 +1158,7 @@ static int img_convert(int argc, char **argv)
     compress = 0;
     skip_create = 0;
     for(;;) {
-        c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:qn");
+        c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:qnl:");
         if (c == -1) {
             break;
         }
@@ -1187,6 +1193,18 @@ static int img_convert(int argc, char **argv)
         case 's':
             snapshot_name = optarg;
             break;
+        case 'l':
+            if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
+                sn_opts = qemu_opts_parse(&internal_snapshot_opts, optarg, 0);
+                if (!sn_opts) {
+                    error_report("Failed in parsing snapshot param '%s'",
+                                 optarg);
+                    return 1;
+                }
+            } else {
+                snapshot_name = optarg;
+            }
+            break;
         case 'S':
         {
             int64_t sval;
@@ -1227,7 +1245,7 @@ static int img_convert(int argc, char **argv)
     out_filename = argv[argc - 1];
 
     /* Initialize before goto out */
-    qemu_progress_init(progress, 2.0);
+    qemu_progress_init(progress, 1.0);
 
     if (options && is_help_option(options)) {
         ret = print_block_option_help(out_filename, out_fmt);
@@ -1258,17 +1276,26 @@ static int img_convert(int argc, char **argv)
         total_sectors += bs_sectors;
     }
 
-    if (snapshot_name != NULL) {
+    if (sn_opts) {
+        ret = bdrv_snapshot_load_tmp(bs[0],
+                                     qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
+                                     qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
+                                     &local_err);
+    } else if (snapshot_name != NULL) {
         if (bs_n > 1) {
             error_report("No support for concatenating multiple snapshot");
             ret = -1;
             goto out;
         }
-        if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
-            error_report("Failed to load snapshot");
-            ret = -1;
-            goto out;
-        }
+
+        bdrv_snapshot_load_tmp_by_id_or_name(bs[0], snapshot_name, &local_err);
+    }
+    if (error_is_set(&local_err)) {
+        error_report("Failed to load snapshot: %s",
+                     error_get_pretty(local_err));
+        error_free(local_err);
+        ret = -1;
+        goto out;
     }
 
     /* Find driver and parse its options */
@@ -1371,7 +1398,16 @@ static int img_convert(int argc, char **argv)
     bs_i = 0;
     bs_offset = 0;
     bdrv_get_geometry(bs[0], &bs_sectors);
-    buf = qemu_blockalign(out_bs, IO_BUF_SIZE);
+
+    /* increase bufsectors from the default 4096 (2M) if opt_transfer_length
+     * or discard_alignment of the out_bs is greater. Limit to 32768 (16MB)
+     * as maximum. */
+    bufsectors = MIN(32768,
+                     MAX(bufsectors, MAX(out_bs->bl.opt_transfer_length,
+                                         out_bs->bl.discard_alignment))
+                    );
+
+    buf = qemu_blockalign(out_bs, bufsectors * BDRV_SECTOR_SIZE);
 
     if (skip_create) {
         int64_t output_length = bdrv_getlength(out_bs);
@@ -1387,26 +1423,26 @@ static int img_convert(int argc, char **argv)
         }
     }
 
-    if (compress) {
-        ret = bdrv_get_info(out_bs, &bdi);
-        if (ret < 0) {
+    cluster_sectors = 0;
+    ret = bdrv_get_info(out_bs, &bdi);
+    if (ret < 0) {
+        if (compress) {
             error_report("could not get block driver info");
             goto out;
         }
-        cluster_size = bdi.cluster_size;
-        if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
+    } else {
+        cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
+    }
+
+    if (compress) {
+        if (cluster_sectors <= 0 || cluster_sectors > bufsectors) {
             error_report("invalid cluster size");
             ret = -1;
             goto out;
         }
-        cluster_sectors = cluster_size >> 9;
         sector_num = 0;
 
         nb_sectors = total_sectors;
-        if (nb_sectors != 0) {
-            local_progress = (float)100 /
-                (nb_sectors / MIN(nb_sectors, cluster_sectors));
-        }
 
         for(;;) {
             int64_t bs_num;
@@ -1464,7 +1500,7 @@ static int img_convert(int argc, char **argv)
                 }
             }
             sector_num += n;
-            qemu_progress_print(local_progress, 100);
+            qemu_progress_print(100.0 * sector_num / total_sectors, 0);
         }
         /* signal EOF to align */
         bdrv_write_compressed(out_bs, 0, NULL, 0);
@@ -1481,21 +1517,13 @@ static int img_convert(int argc, char **argv)
 
         sector_num = 0; // total number of sectors converted so far
         nb_sectors = total_sectors - sector_num;
-        if (nb_sectors != 0) {
-            local_progress = (float)100 /
-                (nb_sectors / MIN(nb_sectors, IO_BUF_SIZE / 512));
-        }
 
         for(;;) {
             nb_sectors = total_sectors - sector_num;
             if (nb_sectors <= 0) {
+                ret = 0;
                 break;
             }
-            if (nb_sectors >= (IO_BUF_SIZE / 512)) {
-                n = (IO_BUF_SIZE / 512);
-            } else {
-                n = nb_sectors;
-            }
 
             while (sector_num - bs_offset >= bs_sectors) {
                 bs_i ++;
@@ -1507,34 +1535,59 @@ static int img_convert(int argc, char **argv)
                    sector_num, bs_i, bs_offset, bs_sectors); */
             }
 
-            if (n > bs_offset + bs_sectors - sector_num) {
-                n = bs_offset + bs_sectors - sector_num;
-            }
-
-            /* If the output image is being created as a copy on write image,
-               assume that sectors which are unallocated in the input image
-               are present in both the output's and input's base images (no
-               need to copy them). */
-            if (out_baseimg) {
-                ret = bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
-                                        n, &n1);
+            if ((out_baseimg || has_zero_init) &&
+                sector_num >= sector_num_next_status) {
+                n = nb_sectors > INT_MAX ? INT_MAX : nb_sectors;
+                ret = bdrv_get_block_status(bs[bs_i], sector_num - bs_offset,
+                                            n, &n1);
                 if (ret < 0) {
-                    error_report("error while reading metadata for sector "
-                                 "%" PRId64 ": %s",
-                                 sector_num - bs_offset, strerror(-ret));
+                    error_report("error while reading block status of sector %"
+                                 PRId64 ": %s", sector_num - bs_offset,
+                                 strerror(-ret));
                     goto out;
                 }
-                if (!ret) {
+                /* If the output image is zero initialized, we are not working
+                 * on a shared base and the input is zero we can skip the next
+                 * n1 sectors */
+                if (has_zero_init && !out_baseimg && (ret & BDRV_BLOCK_ZERO)) {
                     sector_num += n1;
                     continue;
                 }
-                /* The next 'n1' sectors are allocated in the input image. Copy
-                   only those as they may be followed by unallocated sectors. */
-                n = n1;
-            } else {
-                n1 = n;
+                /* If the output image is being created as a copy on write
+                 * image, assume that sectors which are unallocated in the
+                 * input image are present in both the output's and input's
+                 * base images (no need to copy them). */
+                if (out_baseimg) {
+                    if (!(ret & BDRV_BLOCK_DATA)) {
+                        sector_num += n1;
+                        continue;
+                    }
+                    /* The next 'n1' sectors are allocated in the input image.
+                     * Copy only those as they may be followed by unallocated
+                     * sectors. */
+                    nb_sectors = n1;
+                }
+                /* avoid redundant callouts to get_block_status */
+                sector_num_next_status = sector_num + n1;
+            }
+
+            n = MIN(nb_sectors, bufsectors);
+
+            /* round down request length to an aligned sector, but
+             * do not bother doing this on short requests. They happen
+             * when we found an all-zero area, and the next sector to
+             * write will not be sector_num + n. */
+            if (cluster_sectors > 0 && n >= cluster_sectors) {
+                int64_t next_aligned_sector = (sector_num + n);
+                next_aligned_sector -= next_aligned_sector % cluster_sectors;
+                if (sector_num + n > next_aligned_sector) {
+                    n = next_aligned_sector - sector_num;
+                }
             }
 
+            n = MIN(n, bs_sectors - (sector_num - bs_offset));
+            n1 = n;
+
             ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
             if (ret < 0) {
                 error_report("error while reading sector %" PRId64 ": %s",
@@ -1559,14 +1612,20 @@ static int img_convert(int argc, char **argv)
                 n -= n1;
                 buf1 += n1 * 512;
             }
-            qemu_progress_print(local_progress, 100);
+            qemu_progress_print(100.0 * sector_num / total_sectors, 0);
         }
     }
 out:
+    if (!ret) {
+        qemu_progress_print(100, 0);
+    }
     qemu_progress_end();
     free_option_parameters(create_options);
     free_option_parameters(param);
     qemu_vfree(buf);
+    if (sn_opts) {
+        qemu_opts_del(sn_opts);
+    }
     if (out_bs) {
         bdrv_unref(out_bs);
     }
diff --git a/qemu-img.texi b/qemu-img.texi
index da36975d70..be31191e43 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -46,7 +46,11 @@ is the destination disk image filename
 is a comma separated list of format specific options in a
 name=value format. Use @code{-o ?} for an overview of the options supported
 by the used format or see the format descriptions below for details.
-
+@item snapshot_param
+is param used for internal snapshot, format is
+'snapshot.id=[ID],snapshot.name=[NAME]' or '[ID_OR_NAME]'
+@item snapshot_id_or_name
+is deprecated, use snapshot_param instead
 
 @item -c
 indicates that target image must be compressed (qcow format only)
@@ -179,10 +183,10 @@ Error on reading data
 
 @end table
 
-@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
+@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
 
-Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename}
-using format @var{output_fmt}. It can be optionally compressed (@code{-c}
+Convert the disk image @var{filename} or a snapshot @var{snapshot_param}(@var{snapshot_id_or_name} is deprecated)
+to disk image @var{output_filename} using format @var{output_fmt}. It can be optionally compressed (@code{-c}
 option) or use any format specific options like encryption (@code{-o} option).
 
 Only the formats @code{qcow} and @code{qcow2} support compression. The
diff --git a/qemu-nbd.c b/qemu-nbd.c
index c26c98ef1d..136e8c9c05 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -20,6 +20,7 @@
 #include "block/block.h"
 #include "block/nbd.h"
 #include "qemu/main-loop.h"
+#include "block/snapshot.h"
 
 #include <stdarg.h>
 #include <stdio.h>
@@ -78,8 +79,16 @@ static void usage(const char *name)
 #endif
 "\n"
 "Block device options:\n"
+"  -f, --format=FORMAT  set image format (raw, qcow2, ...)\n"
 "  -r, --read-only      export read-only\n"
-"  -s, --snapshot       use snapshot file\n"
+"  -s, --snapshot       use FILE as an external snapshot, create a temporary\n"
+"                       file with backing_file=FILE, redirect the write to\n"
+"                       the temporary one\n"
+"  -l, --load-snapshot=SNAPSHOT_PARAM\n"
+"                       load an internal snapshot inside FILE and export it\n"
+"                       as an read-only device, SNAPSHOT_PARAM format is\n"
+"                       'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
+"                       '[ID_OR_NAME]'\n"
 "  -n, --nocache        disable host cache\n"
 "      --cache=MODE     set cache mode (none, writeback, ...)\n"
 #ifdef CONFIG_LINUX_AIO
@@ -315,7 +324,9 @@ int main(int argc, char **argv)
     char *device = NULL;
     int port = NBD_DEFAULT_PORT;
     off_t fd_size;
-    const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:t";
+    QemuOpts *sn_opts = NULL;
+    const char *sn_id_or_name = NULL;
+    const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:";
     struct option lopt[] = {
         { "help", 0, NULL, 'h' },
         { "version", 0, NULL, 'V' },
@@ -328,6 +339,7 @@ int main(int argc, char **argv)
         { "connect", 1, NULL, 'c' },
         { "disconnect", 0, NULL, 'd' },
         { "snapshot", 0, NULL, 's' },
+        { "load-snapshot", 1, NULL, 'l' },
         { "nocache", 0, NULL, 'n' },
         { "cache", 1, NULL, QEMU_NBD_OPT_CACHE },
 #ifdef CONFIG_LINUX_AIO
@@ -428,6 +440,17 @@ int main(int argc, char **argv)
                 errx(EXIT_FAILURE, "Offset must be positive `%s'", optarg);
             }
             break;
+        case 'l':
+            if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
+                sn_opts = qemu_opts_parse(&internal_snapshot_opts, optarg, 0);
+                if (!sn_opts) {
+                    errx(EXIT_FAILURE, "Failed in parsing snapshot param `%s'",
+                         optarg);
+                }
+            } else {
+                sn_id_or_name = optarg;
+            }
+            /* fall through */
         case 'r':
             nbdflags |= NBD_FLAG_READ_ONLY;
             flags &= ~BDRV_O_RDWR;
@@ -581,6 +604,22 @@ int main(int argc, char **argv)
             error_get_pretty(local_err));
     }
 
+    if (sn_opts) {
+        ret = bdrv_snapshot_load_tmp(bs,
+                                     qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
+                                     qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
+                                     &local_err);
+    } else if (sn_id_or_name) {
+        ret = bdrv_snapshot_load_tmp_by_id_or_name(bs, sn_id_or_name,
+                                                   &local_err);
+    }
+    if (ret < 0) {
+        errno = -ret;
+        err(EXIT_FAILURE,
+            "Failed to load snapshot: %s",
+            error_get_pretty(local_err));
+    }
+
     fd_size = bdrv_getlength(bs);
 
     if (partition != -1) {
@@ -641,6 +680,10 @@ int main(int argc, char **argv)
         unlink(sockpath);
     }
 
+    if (sn_opts) {
+        qemu_opts_del(sn_opts);
+    }
+
     if (device) {
         void *ret;
         pthread_join(client_thread, &ret);
diff --git a/qemu-nbd.texi b/qemu-nbd.texi
index 6055ec693b..0a7e01385c 100644
--- a/qemu-nbd.texi
+++ b/qemu-nbd.texi
@@ -22,12 +22,20 @@ Export QEMU disk image using NBD protocol.
   interface to bind to (default @samp{0.0.0.0})
 @item -k, --socket=@var{path}
   Use a unix socket with path @var{path}
+@item -f, --format=@var{format}
+  Set image format as @var{format}
 @item -r, --read-only
   export read-only
 @item -P, --partition=@var{num}
   only expose partition @var{num}
 @item -s, --snapshot
-  use snapshot file
+  use @var{filename} as an external snapshot, create a temporary
+  file with backing_file=@var{filename}, redirect the write to
+  the temporary one
+@item -l, --load-snapshot=@var{snapshot_param}
+  load an internal snapshot inside @var{filename} and export it
+  as an read-only device, @var{snapshot_param} format is
+  'snapshot.id=[ID],snapshot.name=[NAME]' or '[ID_OR_NAME]'
 @item -n, --nocache
 @itemx --cache=@var{cache}
   set cache mode to be used with the file.  See the documentation of
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
index ebe29d0168..c9c5f83936 100755
--- a/tests/qemu-iotests/026
+++ b/tests/qemu-iotests/026
@@ -44,7 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow2
 _supported_proto generic
 _supported_os Linux
-
+_default_cache_mode "writethrough"
+_supported_cache_modes "writethrough" "none"
 
 echo "Errors while writing 128 kB"
 echo
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
index 8bade92a80..6abf47267f 100755
--- a/tests/qemu-iotests/039
+++ b/tests/qemu-iotests/039
@@ -44,7 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow2
 _supported_proto generic
 _supported_os Linux
-_unsupported_qemu_io_options --nocache
+_default_cache_mode "writethrough"
+_supported_cache_modes "writethrough"
 
 size=128M
 
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
index 9def7fcc8c..65da46d6f5 100755
--- a/tests/qemu-iotests/048
+++ b/tests/qemu-iotests/048
@@ -81,32 +81,5 @@ cp "$TEST_IMG" "$TEST_IMG2"
 io_pattern write 512 512 0 1 101
 _compare
 
-# Test cluster allocated in one, with IO error
-cat > "$TEST_DIR/blkdebug.conf"<<EOF
-[inject-error]
-event = "read_aio"
-errno = "5"
-once ="off"
-EOF
-_make_test_img $size
-cp "$TEST_IMG" "$TEST_IMG2"
-io_pattern write 512 512 0 1 102
-TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" _compare 2>&1 |\
-    _filter_testdir | _filter_imgfmt
-
-# Test cluster allocated in one, with different sizes and IO error in the part
-# that exists only in one image
-cat > "$TEST_DIR/blkdebug.conf"<<EOF
-[inject-error]
-event = "read_aio"
-errno = "5"
-once ="off"
-EOF
-_make_test_img $size
-TEST_IMG="$TEST_IMG2" _make_test_img 0
-io_pattern write 512 512 0 1 102
-TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" _compare 2>&1 |\
-    _filter_testdir | _filter_imgfmt
-
 # Cleanup
 status=0
diff --git a/tests/qemu-iotests/048.out b/tests/qemu-iotests/048.out
index 58d03d3d79..c0f380d3a3 100644
--- a/tests/qemu-iotests/048.out
+++ b/tests/qemu-iotests/048.out
@@ -37,20 +37,4 @@ wrote 512/512 bytes at offset 512
 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 Content mismatch at offset 512!
 1
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
-=== IO: pattern 102
-wrote 512/512 bytes at offset 512
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
-qemu-img: Error while reading offset 0: Input/output error
-4
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
-Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0 
-=== IO: pattern 102
-wrote 512/512 bytes at offset 512
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
-qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
-Warning: Image size mismatch!
-4
 Cleanup
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index ddef87cb18..49e95a20cf 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -39,12 +39,12 @@ ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
 === Enable and disable lazy refcounting on the command line, plus some invalid values ===
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: could not open disk image TEST_DIR/t.qcow2: Parameter 'lazy-refcounts' expects 'on' or 'off'
@@ -63,71 +63,71 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: could not open disk image TEST_DIR/t.qcow2: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 
 === No medium ===
 
 Testing: -drive if=floppy
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive if=ide,media=cdrom
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive if=scsi,media=cdrom
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive if=ide
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: Device needs media, but drive is empty
 QEMU_PROG: Device initialization failed.
 QEMU_PROG: Initialization of device ide-hd failed
 
 Testing: -drive if=virtio
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
 QEMU_PROG: -drive if=virtio: Device initialization failed.
 QEMU_PROG: -drive if=virtio: Device initialization failed.
 QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized
 
 Testing: -drive if=scsi
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty
 QEMU_PROG: Device initialization failed.
 QEMU_PROG: Initialization of device lsi53c895a failed
 
 Testing: -drive if=none,id=disk -device ide-cd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive if=none,id=disk -device ide-drive,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
 QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
 QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized
 
 Testing: -drive if=none,id=disk -device ide-hd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
 QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
 QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized
 
 Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty
 QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed.
 QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized
 
 Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
 QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed.
 QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized
@@ -136,81 +136,81 @@ QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized
 === Read-only ===
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: Can't use a read-only drive
 QEMU_PROG: Device initialization failed.
 QEMU_PROG: Initialization of device ide-hd failed
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive
 QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
 QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

+QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive
 QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
 QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 
 === Cache modes ===
 
 Testing: -drive media=cdrom,cache=none
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive media=cdrom,cache=directsync
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive media=cdrom,cache=writeback
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive media=cdrom,cache=writethrough
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive media=cdrom,cache=unsafe
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive media=cdrom,cache=invalid_value
 QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option
@@ -219,8 +219,8 @@ QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option
 === Specifying the protocol layer ===
 
 Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file
-QEMU X.Y.Z monitor - type 'help' for more information

-(qemu) qququiquit

+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
 
 Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Can't use 'qcow2' as a block driver for the protocol level
diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
index f5f9683e68..4d4e411339 100755
--- a/tests/qemu-iotests/052
+++ b/tests/qemu-iotests/052
@@ -41,8 +41,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt generic
 _supported_proto generic
 _supported_os Linux
-_unsupported_qemu_io_options --nocache
-
+_default_cache_mode "writethrough"
+_supported_cache_modes "writethrough"
 
 size=128M
 _make_test_img $size
diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058
new file mode 100755
index 0000000000..14584cdea2
--- /dev/null
+++ b/tests/qemu-iotests/058
@@ -0,0 +1,138 @@
+#!/bin/bash
+#
+# Test export internal snapshot by qemu-nbd, convert it by qemu-img.
+#
+# Copyright (C) 2013 IBM, Inc.
+#
+# Based on 029.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=xiawenc@linux.vnet.ibm.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+nbd_unix_socket=$TEST_DIR/test_qemu_nbd_socket
+nbd_snapshot_img="nbd:unix:$nbd_unix_socket"
+
+_cleanup_nbd()
+{
+    if [ -n "$NBD_SNAPSHOT_PID" ]; then
+        kill "$NBD_SNAPSHOT_PID"
+    fi
+    rm -f "$nbd_unix_socket"
+}
+
+_wait_for_nbd()
+{
+    for ((i = 0; i < 300; i++))
+    do
+        if [ -r "$nbd_unix_socket" ]; then
+            return
+        fi
+        sleep 0.1
+    done
+    echo "Failed in check of unix socket created by qemu-nbd"
+    exit 1
+}
+
+converted_image=$TEST_IMG.converted
+
+_export_nbd_snapshot()
+{
+    _cleanup_nbd
+    $QEMU_NBD -v -t -k "$nbd_unix_socket" "$TEST_IMG" -l $1 &
+    NBD_SNAPSHOT_PID=$!
+    _wait_for_nbd
+}
+
+_export_nbd_snapshot1()
+{
+    _cleanup_nbd
+    $QEMU_NBD -v -t -k "$nbd_unix_socket" "$TEST_IMG" -l snapshot.name=$1 &
+    NBD_SNAPSHOT_PID=$!
+    _wait_for_nbd
+}
+
+_cleanup()
+{
+    _cleanup_nbd
+    _cleanup_test_img
+    rm -f "$converted_image"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.pattern
+
+_supported_fmt qcow2
+_supported_proto file
+_require_command QEMU_NBD
+
+echo
+echo "== preparing image =="
+_make_test_img 64M
+$QEMU_IO -c 'write -P 0xa 0x1000 0x1000' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write -P 0xb 0x2000 0x1000' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG snapshot -c sn1 "$TEST_IMG"
+$QEMU_IO -c 'write -P 0xc 0x1000 0x1000' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write -P 0xd 0x2000 0x1000' "$TEST_IMG" | _filter_qemu_io
+_check_test_img
+
+echo
+echo "== verifying the image file with patterns =="
+$QEMU_IO -c 'read -P 0xc 0x1000 0x1000' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'read -P 0xd 0x2000 0x1000' "$TEST_IMG" | _filter_qemu_io
+
+_export_nbd_snapshot sn1
+
+echo
+echo "== verifying the exported snapshot with patterns, method 1 =="
+$QEMU_IO -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
+$QEMU_IO -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
+
+_export_nbd_snapshot1 sn1
+
+echo
+echo "== verifying the exported snapshot with patterns, method 2 =="
+$QEMU_IO -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
+$QEMU_IO -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
+
+$QEMU_IMG convert "$TEST_IMG" -l sn1 -O qcow2 "$converted_image"
+
+echo
+echo "== verifying the converted snapshot with patterns, method 1 =="
+$QEMU_IO -c 'read -P 0xa 0x1000 0x1000' "$converted_image" | _filter_qemu_io
+$QEMU_IO -c 'read -P 0xb 0x2000 0x1000' "$converted_image" | _filter_qemu_io
+
+$QEMU_IMG convert "$TEST_IMG" -l snapshot.name=sn1 -O qcow2 "$converted_image"
+
+echo
+echo "== verifying the converted snapshot with patterns, method 2 =="
+$QEMU_IO -c 'read -P 0xa 0x1000 0x1000' "$converted_image" | _filter_qemu_io
+$QEMU_IO -c 'read -P 0xb 0x2000 0x1000' "$converted_image" | _filter_qemu_io
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/058.out b/tests/qemu-iotests/058.out
new file mode 100644
index 0000000000..9a69379589
--- /dev/null
+++ b/tests/qemu-iotests/058.out
@@ -0,0 +1,44 @@
+QA output created by 058
+
+== preparing image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+wrote 4096/4096 bytes at offset 4096
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 4096/4096 bytes at offset 8192
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 4096/4096 bytes at offset 4096
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 4096/4096 bytes at offset 8192
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
+
+== verifying the image file with patterns ==
+read 4096/4096 bytes at offset 4096
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 8192
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying the exported snapshot with patterns, method 1 ==
+read 4096/4096 bytes at offset 4096
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 8192
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying the exported snapshot with patterns, method 2 ==
+read 4096/4096 bytes at offset 4096
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 8192
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying the converted snapshot with patterns, method 1 ==
+read 4096/4096 bytes at offset 4096
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 8192
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying the converted snapshot with patterns, method 2 ==
+read 4096/4096 bytes at offset 4096
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 4096/4096 bytes at offset 8192
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index 4926645e5e..73941c3e61 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -76,6 +76,11 @@ echo "=== Testing monolithicFlat with zeroed_grain ==="
 IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G
 
 echo
+echo "=== Testing big twoGbMaxExtentFlat ==="
+IMGOPTS="subformat=twoGbMaxExtentFlat" _make_test_img 1000G
+$QEMU_IMG info $TEST_IMG | _filter_testdir | sed -e 's/cid: [0-9]*/cid: XXXXXXXX/'
+
+echo
 echo "=== Testing version 3 ==="
 _use_sample_img iotest-version3.vmdk.bz2
 _img_info
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 0aadd569d0..4ff935c6f4 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -26,6 +26,2018 @@ virtual size: 2.0G (2147483648 bytes)
 qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
 
+=== Testing big twoGbMaxExtentFlat ===
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000
+image: TEST_DIR/t.vmdk
+file format: vmdk
+virtual size: 1.0T (1073741824000 bytes)
+disk size: 16K
+Format specific information:
+    cid: XXXXXXXX
+    parent cid: XXXXXXXX
+    create type: twoGbMaxExtentFlat
+    extents:
+        [0]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f001.vmdk
+            format: FLAT
+        [1]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f002.vmdk
+            format: FLAT
+        [2]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f003.vmdk
+            format: FLAT
+        [3]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f004.vmdk
+            format: FLAT
+        [4]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f005.vmdk
+            format: FLAT
+        [5]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f006.vmdk
+            format: FLAT
+        [6]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f007.vmdk
+            format: FLAT
+        [7]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f008.vmdk
+            format: FLAT
+        [8]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f009.vmdk
+            format: FLAT
+        [9]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f010.vmdk
+            format: FLAT
+        [10]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f011.vmdk
+            format: FLAT
+        [11]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f012.vmdk
+            format: FLAT
+        [12]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f013.vmdk
+            format: FLAT
+        [13]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f014.vmdk
+            format: FLAT
+        [14]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f015.vmdk
+            format: FLAT
+        [15]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f016.vmdk
+            format: FLAT
+        [16]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f017.vmdk
+            format: FLAT
+        [17]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f018.vmdk
+            format: FLAT
+        [18]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f019.vmdk
+            format: FLAT
+        [19]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f020.vmdk
+            format: FLAT
+        [20]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f021.vmdk
+            format: FLAT
+        [21]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f022.vmdk
+            format: FLAT
+        [22]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f023.vmdk
+            format: FLAT
+        [23]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f024.vmdk
+            format: FLAT
+        [24]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f025.vmdk
+            format: FLAT
+        [25]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f026.vmdk
+            format: FLAT
+        [26]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f027.vmdk
+            format: FLAT
+        [27]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f028.vmdk
+            format: FLAT
+        [28]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f029.vmdk
+            format: FLAT
+        [29]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f030.vmdk
+            format: FLAT
+        [30]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f031.vmdk
+            format: FLAT
+        [31]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f032.vmdk
+            format: FLAT
+        [32]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f033.vmdk
+            format: FLAT
+        [33]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f034.vmdk
+            format: FLAT
+        [34]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f035.vmdk
+            format: FLAT
+        [35]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f036.vmdk
+            format: FLAT
+        [36]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f037.vmdk
+            format: FLAT
+        [37]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f038.vmdk
+            format: FLAT
+        [38]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f039.vmdk
+            format: FLAT
+        [39]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f040.vmdk
+            format: FLAT
+        [40]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f041.vmdk
+            format: FLAT
+        [41]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f042.vmdk
+            format: FLAT
+        [42]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f043.vmdk
+            format: FLAT
+        [43]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f044.vmdk
+            format: FLAT
+        [44]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f045.vmdk
+            format: FLAT
+        [45]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f046.vmdk
+            format: FLAT
+        [46]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f047.vmdk
+            format: FLAT
+        [47]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f048.vmdk
+            format: FLAT
+        [48]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f049.vmdk
+            format: FLAT
+        [49]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f050.vmdk
+            format: FLAT
+        [50]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f051.vmdk
+            format: FLAT
+        [51]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f052.vmdk
+            format: FLAT
+        [52]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f053.vmdk
+            format: FLAT
+        [53]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f054.vmdk
+            format: FLAT
+        [54]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f055.vmdk
+            format: FLAT
+        [55]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f056.vmdk
+            format: FLAT
+        [56]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f057.vmdk
+            format: FLAT
+        [57]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f058.vmdk
+            format: FLAT
+        [58]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f059.vmdk
+            format: FLAT
+        [59]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f060.vmdk
+            format: FLAT
+        [60]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f061.vmdk
+            format: FLAT
+        [61]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f062.vmdk
+            format: FLAT
+        [62]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f063.vmdk
+            format: FLAT
+        [63]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f064.vmdk
+            format: FLAT
+        [64]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f065.vmdk
+            format: FLAT
+        [65]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f066.vmdk
+            format: FLAT
+        [66]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f067.vmdk
+            format: FLAT
+        [67]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f068.vmdk
+            format: FLAT
+        [68]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f069.vmdk
+            format: FLAT
+        [69]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f070.vmdk
+            format: FLAT
+        [70]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f071.vmdk
+            format: FLAT
+        [71]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f072.vmdk
+            format: FLAT
+        [72]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f073.vmdk
+            format: FLAT
+        [73]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f074.vmdk
+            format: FLAT
+        [74]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f075.vmdk
+            format: FLAT
+        [75]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f076.vmdk
+            format: FLAT
+        [76]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f077.vmdk
+            format: FLAT
+        [77]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f078.vmdk
+            format: FLAT
+        [78]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f079.vmdk
+            format: FLAT
+        [79]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f080.vmdk
+            format: FLAT
+        [80]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f081.vmdk
+            format: FLAT
+        [81]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f082.vmdk
+            format: FLAT
+        [82]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f083.vmdk
+            format: FLAT
+        [83]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f084.vmdk
+            format: FLAT
+        [84]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f085.vmdk
+            format: FLAT
+        [85]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f086.vmdk
+            format: FLAT
+        [86]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f087.vmdk
+            format: FLAT
+        [87]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f088.vmdk
+            format: FLAT
+        [88]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f089.vmdk
+            format: FLAT
+        [89]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f090.vmdk
+            format: FLAT
+        [90]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f091.vmdk
+            format: FLAT
+        [91]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f092.vmdk
+            format: FLAT
+        [92]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f093.vmdk
+            format: FLAT
+        [93]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f094.vmdk
+            format: FLAT
+        [94]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f095.vmdk
+            format: FLAT
+        [95]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f096.vmdk
+            format: FLAT
+        [96]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f097.vmdk
+            format: FLAT
+        [97]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f098.vmdk
+            format: FLAT
+        [98]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f099.vmdk
+            format: FLAT
+        [99]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f100.vmdk
+            format: FLAT
+        [100]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f101.vmdk
+            format: FLAT
+        [101]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f102.vmdk
+            format: FLAT
+        [102]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f103.vmdk
+            format: FLAT
+        [103]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f104.vmdk
+            format: FLAT
+        [104]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f105.vmdk
+            format: FLAT
+        [105]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f106.vmdk
+            format: FLAT
+        [106]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f107.vmdk
+            format: FLAT
+        [107]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f108.vmdk
+            format: FLAT
+        [108]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f109.vmdk
+            format: FLAT
+        [109]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f110.vmdk
+            format: FLAT
+        [110]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f111.vmdk
+            format: FLAT
+        [111]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f112.vmdk
+            format: FLAT
+        [112]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f113.vmdk
+            format: FLAT
+        [113]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f114.vmdk
+            format: FLAT
+        [114]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f115.vmdk
+            format: FLAT
+        [115]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f116.vmdk
+            format: FLAT
+        [116]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f117.vmdk
+            format: FLAT
+        [117]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f118.vmdk
+            format: FLAT
+        [118]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f119.vmdk
+            format: FLAT
+        [119]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f120.vmdk
+            format: FLAT
+        [120]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f121.vmdk
+            format: FLAT
+        [121]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f122.vmdk
+            format: FLAT
+        [122]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f123.vmdk
+            format: FLAT
+        [123]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f124.vmdk
+            format: FLAT
+        [124]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f125.vmdk
+            format: FLAT
+        [125]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f126.vmdk
+            format: FLAT
+        [126]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f127.vmdk
+            format: FLAT
+        [127]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f128.vmdk
+            format: FLAT
+        [128]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f129.vmdk
+            format: FLAT
+        [129]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f130.vmdk
+            format: FLAT
+        [130]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f131.vmdk
+            format: FLAT
+        [131]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f132.vmdk
+            format: FLAT
+        [132]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f133.vmdk
+            format: FLAT
+        [133]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f134.vmdk
+            format: FLAT
+        [134]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f135.vmdk
+            format: FLAT
+        [135]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f136.vmdk
+            format: FLAT
+        [136]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f137.vmdk
+            format: FLAT
+        [137]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f138.vmdk
+            format: FLAT
+        [138]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f139.vmdk
+            format: FLAT
+        [139]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f140.vmdk
+            format: FLAT
+        [140]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f141.vmdk
+            format: FLAT
+        [141]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f142.vmdk
+            format: FLAT
+        [142]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f143.vmdk
+            format: FLAT
+        [143]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f144.vmdk
+            format: FLAT
+        [144]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f145.vmdk
+            format: FLAT
+        [145]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f146.vmdk
+            format: FLAT
+        [146]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f147.vmdk
+            format: FLAT
+        [147]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f148.vmdk
+            format: FLAT
+        [148]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f149.vmdk
+            format: FLAT
+        [149]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f150.vmdk
+            format: FLAT
+        [150]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f151.vmdk
+            format: FLAT
+        [151]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f152.vmdk
+            format: FLAT
+        [152]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f153.vmdk
+            format: FLAT
+        [153]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f154.vmdk
+            format: FLAT
+        [154]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f155.vmdk
+            format: FLAT
+        [155]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f156.vmdk
+            format: FLAT
+        [156]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f157.vmdk
+            format: FLAT
+        [157]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f158.vmdk
+            format: FLAT
+        [158]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f159.vmdk
+            format: FLAT
+        [159]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f160.vmdk
+            format: FLAT
+        [160]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f161.vmdk
+            format: FLAT
+        [161]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f162.vmdk
+            format: FLAT
+        [162]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f163.vmdk
+            format: FLAT
+        [163]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f164.vmdk
+            format: FLAT
+        [164]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f165.vmdk
+            format: FLAT
+        [165]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f166.vmdk
+            format: FLAT
+        [166]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f167.vmdk
+            format: FLAT
+        [167]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f168.vmdk
+            format: FLAT
+        [168]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f169.vmdk
+            format: FLAT
+        [169]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f170.vmdk
+            format: FLAT
+        [170]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f171.vmdk
+            format: FLAT
+        [171]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f172.vmdk
+            format: FLAT
+        [172]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f173.vmdk
+            format: FLAT
+        [173]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f174.vmdk
+            format: FLAT
+        [174]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f175.vmdk
+            format: FLAT
+        [175]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f176.vmdk
+            format: FLAT
+        [176]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f177.vmdk
+            format: FLAT
+        [177]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f178.vmdk
+            format: FLAT
+        [178]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f179.vmdk
+            format: FLAT
+        [179]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f180.vmdk
+            format: FLAT
+        [180]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f181.vmdk
+            format: FLAT
+        [181]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f182.vmdk
+            format: FLAT
+        [182]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f183.vmdk
+            format: FLAT
+        [183]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f184.vmdk
+            format: FLAT
+        [184]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f185.vmdk
+            format: FLAT
+        [185]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f186.vmdk
+            format: FLAT
+        [186]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f187.vmdk
+            format: FLAT
+        [187]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f188.vmdk
+            format: FLAT
+        [188]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f189.vmdk
+            format: FLAT
+        [189]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f190.vmdk
+            format: FLAT
+        [190]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f191.vmdk
+            format: FLAT
+        [191]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f192.vmdk
+            format: FLAT
+        [192]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f193.vmdk
+            format: FLAT
+        [193]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f194.vmdk
+            format: FLAT
+        [194]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f195.vmdk
+            format: FLAT
+        [195]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f196.vmdk
+            format: FLAT
+        [196]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f197.vmdk
+            format: FLAT
+        [197]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f198.vmdk
+            format: FLAT
+        [198]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f199.vmdk
+            format: FLAT
+        [199]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f200.vmdk
+            format: FLAT
+        [200]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f201.vmdk
+            format: FLAT
+        [201]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f202.vmdk
+            format: FLAT
+        [202]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f203.vmdk
+            format: FLAT
+        [203]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f204.vmdk
+            format: FLAT
+        [204]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f205.vmdk
+            format: FLAT
+        [205]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f206.vmdk
+            format: FLAT
+        [206]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f207.vmdk
+            format: FLAT
+        [207]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f208.vmdk
+            format: FLAT
+        [208]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f209.vmdk
+            format: FLAT
+        [209]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f210.vmdk
+            format: FLAT
+        [210]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f211.vmdk
+            format: FLAT
+        [211]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f212.vmdk
+            format: FLAT
+        [212]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f213.vmdk
+            format: FLAT
+        [213]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f214.vmdk
+            format: FLAT
+        [214]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f215.vmdk
+            format: FLAT
+        [215]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f216.vmdk
+            format: FLAT
+        [216]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f217.vmdk
+            format: FLAT
+        [217]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f218.vmdk
+            format: FLAT
+        [218]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f219.vmdk
+            format: FLAT
+        [219]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f220.vmdk
+            format: FLAT
+        [220]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f221.vmdk
+            format: FLAT
+        [221]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f222.vmdk
+            format: FLAT
+        [222]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f223.vmdk
+            format: FLAT
+        [223]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f224.vmdk
+            format: FLAT
+        [224]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f225.vmdk
+            format: FLAT
+        [225]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f226.vmdk
+            format: FLAT
+        [226]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f227.vmdk
+            format: FLAT
+        [227]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f228.vmdk
+            format: FLAT
+        [228]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f229.vmdk
+            format: FLAT
+        [229]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f230.vmdk
+            format: FLAT
+        [230]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f231.vmdk
+            format: FLAT
+        [231]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f232.vmdk
+            format: FLAT
+        [232]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f233.vmdk
+            format: FLAT
+        [233]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f234.vmdk
+            format: FLAT
+        [234]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f235.vmdk
+            format: FLAT
+        [235]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f236.vmdk
+            format: FLAT
+        [236]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f237.vmdk
+            format: FLAT
+        [237]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f238.vmdk
+            format: FLAT
+        [238]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f239.vmdk
+            format: FLAT
+        [239]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f240.vmdk
+            format: FLAT
+        [240]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f241.vmdk
+            format: FLAT
+        [241]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f242.vmdk
+            format: FLAT
+        [242]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f243.vmdk
+            format: FLAT
+        [243]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f244.vmdk
+            format: FLAT
+        [244]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f245.vmdk
+            format: FLAT
+        [245]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f246.vmdk
+            format: FLAT
+        [246]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f247.vmdk
+            format: FLAT
+        [247]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f248.vmdk
+            format: FLAT
+        [248]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f249.vmdk
+            format: FLAT
+        [249]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f250.vmdk
+            format: FLAT
+        [250]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f251.vmdk
+            format: FLAT
+        [251]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f252.vmdk
+            format: FLAT
+        [252]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f253.vmdk
+            format: FLAT
+        [253]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f254.vmdk
+            format: FLAT
+        [254]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f255.vmdk
+            format: FLAT
+        [255]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f256.vmdk
+            format: FLAT
+        [256]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f257.vmdk
+            format: FLAT
+        [257]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f258.vmdk
+            format: FLAT
+        [258]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f259.vmdk
+            format: FLAT
+        [259]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f260.vmdk
+            format: FLAT
+        [260]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f261.vmdk
+            format: FLAT
+        [261]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f262.vmdk
+            format: FLAT
+        [262]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f263.vmdk
+            format: FLAT
+        [263]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f264.vmdk
+            format: FLAT
+        [264]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f265.vmdk
+            format: FLAT
+        [265]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f266.vmdk
+            format: FLAT
+        [266]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f267.vmdk
+            format: FLAT
+        [267]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f268.vmdk
+            format: FLAT
+        [268]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f269.vmdk
+            format: FLAT
+        [269]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f270.vmdk
+            format: FLAT
+        [270]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f271.vmdk
+            format: FLAT
+        [271]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f272.vmdk
+            format: FLAT
+        [272]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f273.vmdk
+            format: FLAT
+        [273]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f274.vmdk
+            format: FLAT
+        [274]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f275.vmdk
+            format: FLAT
+        [275]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f276.vmdk
+            format: FLAT
+        [276]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f277.vmdk
+            format: FLAT
+        [277]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f278.vmdk
+            format: FLAT
+        [278]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f279.vmdk
+            format: FLAT
+        [279]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f280.vmdk
+            format: FLAT
+        [280]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f281.vmdk
+            format: FLAT
+        [281]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f282.vmdk
+            format: FLAT
+        [282]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f283.vmdk
+            format: FLAT
+        [283]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f284.vmdk
+            format: FLAT
+        [284]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f285.vmdk
+            format: FLAT
+        [285]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f286.vmdk
+            format: FLAT
+        [286]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f287.vmdk
+            format: FLAT
+        [287]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f288.vmdk
+            format: FLAT
+        [288]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f289.vmdk
+            format: FLAT
+        [289]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f290.vmdk
+            format: FLAT
+        [290]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f291.vmdk
+            format: FLAT
+        [291]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f292.vmdk
+            format: FLAT
+        [292]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f293.vmdk
+            format: FLAT
+        [293]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f294.vmdk
+            format: FLAT
+        [294]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f295.vmdk
+            format: FLAT
+        [295]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f296.vmdk
+            format: FLAT
+        [296]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f297.vmdk
+            format: FLAT
+        [297]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f298.vmdk
+            format: FLAT
+        [298]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f299.vmdk
+            format: FLAT
+        [299]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f300.vmdk
+            format: FLAT
+        [300]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f301.vmdk
+            format: FLAT
+        [301]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f302.vmdk
+            format: FLAT
+        [302]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f303.vmdk
+            format: FLAT
+        [303]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f304.vmdk
+            format: FLAT
+        [304]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f305.vmdk
+            format: FLAT
+        [305]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f306.vmdk
+            format: FLAT
+        [306]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f307.vmdk
+            format: FLAT
+        [307]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f308.vmdk
+            format: FLAT
+        [308]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f309.vmdk
+            format: FLAT
+        [309]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f310.vmdk
+            format: FLAT
+        [310]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f311.vmdk
+            format: FLAT
+        [311]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f312.vmdk
+            format: FLAT
+        [312]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f313.vmdk
+            format: FLAT
+        [313]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f314.vmdk
+            format: FLAT
+        [314]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f315.vmdk
+            format: FLAT
+        [315]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f316.vmdk
+            format: FLAT
+        [316]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f317.vmdk
+            format: FLAT
+        [317]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f318.vmdk
+            format: FLAT
+        [318]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f319.vmdk
+            format: FLAT
+        [319]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f320.vmdk
+            format: FLAT
+        [320]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f321.vmdk
+            format: FLAT
+        [321]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f322.vmdk
+            format: FLAT
+        [322]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f323.vmdk
+            format: FLAT
+        [323]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f324.vmdk
+            format: FLAT
+        [324]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f325.vmdk
+            format: FLAT
+        [325]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f326.vmdk
+            format: FLAT
+        [326]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f327.vmdk
+            format: FLAT
+        [327]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f328.vmdk
+            format: FLAT
+        [328]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f329.vmdk
+            format: FLAT
+        [329]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f330.vmdk
+            format: FLAT
+        [330]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f331.vmdk
+            format: FLAT
+        [331]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f332.vmdk
+            format: FLAT
+        [332]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f333.vmdk
+            format: FLAT
+        [333]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f334.vmdk
+            format: FLAT
+        [334]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f335.vmdk
+            format: FLAT
+        [335]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f336.vmdk
+            format: FLAT
+        [336]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f337.vmdk
+            format: FLAT
+        [337]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f338.vmdk
+            format: FLAT
+        [338]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f339.vmdk
+            format: FLAT
+        [339]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f340.vmdk
+            format: FLAT
+        [340]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f341.vmdk
+            format: FLAT
+        [341]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f342.vmdk
+            format: FLAT
+        [342]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f343.vmdk
+            format: FLAT
+        [343]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f344.vmdk
+            format: FLAT
+        [344]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f345.vmdk
+            format: FLAT
+        [345]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f346.vmdk
+            format: FLAT
+        [346]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f347.vmdk
+            format: FLAT
+        [347]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f348.vmdk
+            format: FLAT
+        [348]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f349.vmdk
+            format: FLAT
+        [349]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f350.vmdk
+            format: FLAT
+        [350]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f351.vmdk
+            format: FLAT
+        [351]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f352.vmdk
+            format: FLAT
+        [352]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f353.vmdk
+            format: FLAT
+        [353]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f354.vmdk
+            format: FLAT
+        [354]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f355.vmdk
+            format: FLAT
+        [355]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f356.vmdk
+            format: FLAT
+        [356]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f357.vmdk
+            format: FLAT
+        [357]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f358.vmdk
+            format: FLAT
+        [358]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f359.vmdk
+            format: FLAT
+        [359]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f360.vmdk
+            format: FLAT
+        [360]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f361.vmdk
+            format: FLAT
+        [361]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f362.vmdk
+            format: FLAT
+        [362]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f363.vmdk
+            format: FLAT
+        [363]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f364.vmdk
+            format: FLAT
+        [364]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f365.vmdk
+            format: FLAT
+        [365]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f366.vmdk
+            format: FLAT
+        [366]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f367.vmdk
+            format: FLAT
+        [367]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f368.vmdk
+            format: FLAT
+        [368]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f369.vmdk
+            format: FLAT
+        [369]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f370.vmdk
+            format: FLAT
+        [370]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f371.vmdk
+            format: FLAT
+        [371]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f372.vmdk
+            format: FLAT
+        [372]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f373.vmdk
+            format: FLAT
+        [373]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f374.vmdk
+            format: FLAT
+        [374]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f375.vmdk
+            format: FLAT
+        [375]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f376.vmdk
+            format: FLAT
+        [376]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f377.vmdk
+            format: FLAT
+        [377]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f378.vmdk
+            format: FLAT
+        [378]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f379.vmdk
+            format: FLAT
+        [379]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f380.vmdk
+            format: FLAT
+        [380]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f381.vmdk
+            format: FLAT
+        [381]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f382.vmdk
+            format: FLAT
+        [382]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f383.vmdk
+            format: FLAT
+        [383]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f384.vmdk
+            format: FLAT
+        [384]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f385.vmdk
+            format: FLAT
+        [385]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f386.vmdk
+            format: FLAT
+        [386]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f387.vmdk
+            format: FLAT
+        [387]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f388.vmdk
+            format: FLAT
+        [388]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f389.vmdk
+            format: FLAT
+        [389]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f390.vmdk
+            format: FLAT
+        [390]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f391.vmdk
+            format: FLAT
+        [391]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f392.vmdk
+            format: FLAT
+        [392]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f393.vmdk
+            format: FLAT
+        [393]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f394.vmdk
+            format: FLAT
+        [394]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f395.vmdk
+            format: FLAT
+        [395]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f396.vmdk
+            format: FLAT
+        [396]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f397.vmdk
+            format: FLAT
+        [397]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f398.vmdk
+            format: FLAT
+        [398]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f399.vmdk
+            format: FLAT
+        [399]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f400.vmdk
+            format: FLAT
+        [400]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f401.vmdk
+            format: FLAT
+        [401]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f402.vmdk
+            format: FLAT
+        [402]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f403.vmdk
+            format: FLAT
+        [403]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f404.vmdk
+            format: FLAT
+        [404]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f405.vmdk
+            format: FLAT
+        [405]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f406.vmdk
+            format: FLAT
+        [406]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f407.vmdk
+            format: FLAT
+        [407]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f408.vmdk
+            format: FLAT
+        [408]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f409.vmdk
+            format: FLAT
+        [409]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f410.vmdk
+            format: FLAT
+        [410]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f411.vmdk
+            format: FLAT
+        [411]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f412.vmdk
+            format: FLAT
+        [412]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f413.vmdk
+            format: FLAT
+        [413]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f414.vmdk
+            format: FLAT
+        [414]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f415.vmdk
+            format: FLAT
+        [415]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f416.vmdk
+            format: FLAT
+        [416]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f417.vmdk
+            format: FLAT
+        [417]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f418.vmdk
+            format: FLAT
+        [418]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f419.vmdk
+            format: FLAT
+        [419]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f420.vmdk
+            format: FLAT
+        [420]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f421.vmdk
+            format: FLAT
+        [421]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f422.vmdk
+            format: FLAT
+        [422]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f423.vmdk
+            format: FLAT
+        [423]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f424.vmdk
+            format: FLAT
+        [424]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f425.vmdk
+            format: FLAT
+        [425]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f426.vmdk
+            format: FLAT
+        [426]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f427.vmdk
+            format: FLAT
+        [427]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f428.vmdk
+            format: FLAT
+        [428]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f429.vmdk
+            format: FLAT
+        [429]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f430.vmdk
+            format: FLAT
+        [430]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f431.vmdk
+            format: FLAT
+        [431]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f432.vmdk
+            format: FLAT
+        [432]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f433.vmdk
+            format: FLAT
+        [433]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f434.vmdk
+            format: FLAT
+        [434]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f435.vmdk
+            format: FLAT
+        [435]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f436.vmdk
+            format: FLAT
+        [436]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f437.vmdk
+            format: FLAT
+        [437]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f438.vmdk
+            format: FLAT
+        [438]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f439.vmdk
+            format: FLAT
+        [439]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f440.vmdk
+            format: FLAT
+        [440]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f441.vmdk
+            format: FLAT
+        [441]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f442.vmdk
+            format: FLAT
+        [442]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f443.vmdk
+            format: FLAT
+        [443]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f444.vmdk
+            format: FLAT
+        [444]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f445.vmdk
+            format: FLAT
+        [445]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f446.vmdk
+            format: FLAT
+        [446]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f447.vmdk
+            format: FLAT
+        [447]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f448.vmdk
+            format: FLAT
+        [448]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f449.vmdk
+            format: FLAT
+        [449]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f450.vmdk
+            format: FLAT
+        [450]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f451.vmdk
+            format: FLAT
+        [451]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f452.vmdk
+            format: FLAT
+        [452]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f453.vmdk
+            format: FLAT
+        [453]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f454.vmdk
+            format: FLAT
+        [454]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f455.vmdk
+            format: FLAT
+        [455]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f456.vmdk
+            format: FLAT
+        [456]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f457.vmdk
+            format: FLAT
+        [457]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f458.vmdk
+            format: FLAT
+        [458]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f459.vmdk
+            format: FLAT
+        [459]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f460.vmdk
+            format: FLAT
+        [460]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f461.vmdk
+            format: FLAT
+        [461]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f462.vmdk
+            format: FLAT
+        [462]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f463.vmdk
+            format: FLAT
+        [463]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f464.vmdk
+            format: FLAT
+        [464]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f465.vmdk
+            format: FLAT
+        [465]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f466.vmdk
+            format: FLAT
+        [466]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f467.vmdk
+            format: FLAT
+        [467]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f468.vmdk
+            format: FLAT
+        [468]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f469.vmdk
+            format: FLAT
+        [469]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f470.vmdk
+            format: FLAT
+        [470]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f471.vmdk
+            format: FLAT
+        [471]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f472.vmdk
+            format: FLAT
+        [472]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f473.vmdk
+            format: FLAT
+        [473]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f474.vmdk
+            format: FLAT
+        [474]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f475.vmdk
+            format: FLAT
+        [475]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f476.vmdk
+            format: FLAT
+        [476]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f477.vmdk
+            format: FLAT
+        [477]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f478.vmdk
+            format: FLAT
+        [478]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f479.vmdk
+            format: FLAT
+        [479]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f480.vmdk
+            format: FLAT
+        [480]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f481.vmdk
+            format: FLAT
+        [481]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f482.vmdk
+            format: FLAT
+        [482]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f483.vmdk
+            format: FLAT
+        [483]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f484.vmdk
+            format: FLAT
+        [484]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f485.vmdk
+            format: FLAT
+        [485]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f486.vmdk
+            format: FLAT
+        [486]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f487.vmdk
+            format: FLAT
+        [487]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f488.vmdk
+            format: FLAT
+        [488]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f489.vmdk
+            format: FLAT
+        [489]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f490.vmdk
+            format: FLAT
+        [490]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f491.vmdk
+            format: FLAT
+        [491]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f492.vmdk
+            format: FLAT
+        [492]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f493.vmdk
+            format: FLAT
+        [493]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f494.vmdk
+            format: FLAT
+        [494]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f495.vmdk
+            format: FLAT
+        [495]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f496.vmdk
+            format: FLAT
+        [496]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f497.vmdk
+            format: FLAT
+        [497]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f498.vmdk
+            format: FLAT
+        [498]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f499.vmdk
+            format: FLAT
+        [499]:
+            virtual size: 2147483648
+            filename: TEST_DIR/t-f500.vmdk
+            format: FLAT
+
 === Testing version 3 ===
 image: TEST_DIR/iotest-version3.IMGFMT
 file format: IMGFMT
diff --git a/tests/qemu-iotests/074 b/tests/qemu-iotests/074
new file mode 100755
index 0000000000..aba126cb69
--- /dev/null
+++ b/tests/qemu-iotests/074
@@ -0,0 +1,86 @@
+#!/bin/bash
+##
+## qemu-img compare test (qcow2 only ones)
+##
+##
+## Copyright (C) 2013 Red Hat, Inc.
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+#
+# creator
+owner=famz@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+status=1        # failure is the default!
+
+_cleanup()
+{
+    echo "Cleanup"
+    _cleanup_test_img
+    rm "${TEST_IMG2}"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_compare()
+{
+    $QEMU_IMG compare "$@" "$TEST_IMG" "${TEST_IMG2}"
+    echo $?
+}
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.pattern
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+# Setup test basic parameters
+TEST_IMG2=$TEST_IMG.2
+CLUSTER_SIZE=4096
+size=1024M
+
+# Test cluster allocated in one, with IO error
+cat > "$TEST_DIR/blkdebug.conf"<<EOF
+[inject-error]
+event = "read_aio"
+errno = "5"
+once ="off"
+EOF
+_make_test_img $size
+cp "$TEST_IMG" "$TEST_IMG2"
+io_pattern write 512 512 0 1 102
+TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" _compare 2>&1 |\
+    _filter_testdir | _filter_imgfmt
+
+# Test cluster allocated in one, with different sizes and IO error in the part
+# that exists only in one image
+cat > "$TEST_DIR/blkdebug.conf"<<EOF
+[inject-error]
+event = "read_aio"
+errno = "5"
+once ="off"
+EOF
+_make_test_img $size
+TEST_IMG="$TEST_IMG2" _make_test_img 0
+io_pattern write 512 512 0 1 102
+TEST_IMG="blkdebug:$TEST_DIR/blkdebug.conf:$TEST_IMG" _compare 2>&1 |\
+    _filter_testdir | _filter_imgfmt
+
+# Cleanup
+status=0
diff --git a/tests/qemu-iotests/074.out b/tests/qemu-iotests/074.out
new file mode 100644
index 0000000000..8fba5aea9c
--- /dev/null
+++ b/tests/qemu-iotests/074.out
@@ -0,0 +1,18 @@
+QA output created by 074
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+=== IO: pattern 102
+wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Error while reading offset 0: Input/output error
+4
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0
+=== IO: pattern 102
+wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+Warning: Image size mismatch!
+4
+Cleanup
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index f5f328f5f5..e2ed5a95f8 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -161,6 +161,7 @@ cat <<EOF
 QEMU          -- $QEMU
 QEMU_IMG      -- $QEMU_IMG
 QEMU_IO       -- $QEMU_IO
+QEMU_NBD      -- $QEMU_NBD
 IMGFMT        -- $FULL_IMGFMT_DETAILS
 IMGPROTO      -- $FULL_IMGPROTO_DETAILS
 PLATFORM      -- $FULL_HOST_DETAILS
@@ -242,7 +243,7 @@ do
             fi
 
             reference=$seq.out
-            if (echo $QEMU_IO_OPTIONS | grep -s -- '--nocache' > /dev/null); then
+            if [ "$CACHEMODE" = "none" ]; then
                 [ -f $seq.out.nocache ] && reference=$seq.out.nocache
             fi
 
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index 8cde7f11fa..8b4e22c856 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -42,13 +42,16 @@ expunge=true
 have_test_arg=false
 randomize=false
 valgrind=false
+cachemode=false
 rm -f $tmp.list $tmp.tmp $tmp.sed
 
 export IMGFMT=raw
 export IMGFMT_GENERIC=true
 export IMGPROTO=file
 export IMGOPTS=""
+export CACHEMODE="writeback"
 export QEMU_IO_OPTIONS=""
+export CACHEMODE_IS_DEFAULT=true
 
 for r
 do
@@ -113,7 +116,12 @@ s/ .*//p
         IMGOPTS="$r"
         imgopts=false
         continue
-
+    elif $cachemode
+    then
+        CACHEMODE="$r"
+        CACHEMODE_IS_DEFAULT=false
+        cachemode=false
+        continue
     fi
 
     xpand=true
@@ -124,7 +132,7 @@ s/ .*//p
             echo "Usage: $0 [options] [testlist]"'
 
 common options
-    -v                        verbose
+    -v                  verbose
 
 check options
     -raw                test raw (default)
@@ -140,19 +148,20 @@ check options
     -sheepdog           test sheepdog
     -nbd                test nbd
     -ssh                test ssh
-    -xdiff                graphical mode diff
-    -nocache                use O_DIRECT on backing file
-    -misalign                misalign memory allocations
-    -n                        show me, do not run tests
+    -xdiff              graphical mode diff
+    -nocache            use O_DIRECT on backing file
+    -misalign           misalign memory allocations
+    -n                  show me, do not run tests
     -o options          -o options to pass to qemu-img create/convert
-    -T                        output timestamps
-    -r                         randomize test order
+    -T                  output timestamps
+    -r                  randomize test order
+    -c mode             cache mode
 
 testlist options
     -g group[,group...]        include tests from these groups
     -x group[,group...]        exclude tests from these groups
     NNN                        include test NNN
-    NNN-NNN                include test range (eg. 012-021)
+    NNN-NNN                    include test range (eg. 012-021)
 '
             exit 0
             ;;
@@ -219,7 +228,8 @@ testlist options
             xpand=false
             ;;
         -nocache)
-            QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache"
+            CACHEMODE="none"
+            CACHEMODE_IS_DEFAULT=false
             xpand=false
             ;;
 
@@ -258,6 +268,10 @@ testlist options
             imgopts=true
             xpand=false
             ;;
+        -c)
+            cachemode=true
+            xpand=false
+            ;;
         -r)        # randomize test order
             randomize=true
             xpand=false
@@ -334,6 +348,9 @@ BEGIN        { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
 
 done
 
+# Set qemu-io cache mode with $CACHEMODE we have
+QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE"
+
 # Set default options for qemu-img create -o if they were not specified
 _set_default_imgopts
 
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 9c82c77a81..776985d15e 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -157,7 +157,8 @@ _filter_qemu_io()
 _filter_qemu()
 {
     sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" \
-        -e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#'
+        -e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#' \
+        -e $'s#\r##' # QEMU monitor uses \r\n line endings
 }
 
 # replace problematic QMP output like timestamps
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 7f6245770a..28ba0d9ad5 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -387,25 +387,31 @@ _supported_os()
     _notrun "not suitable for this OS: $HOSTOS"
 }
 
-_unsupported_qemu_io_options()
+_supported_cache_modes()
 {
-    for bad_opt
-    do
-        for opt in $QEMU_IO_OPTIONS
-        do
-            if [ "$bad_opt" = "$opt" ]
-            then
-                _notrun "not suitable for qemu-io option: $bad_opt"
-            fi
-        done
+    for mode; do
+        if [ "$mode" = "$CACHEMODE" ]; then
+            return
+        fi
     done
+    _notrun "not suitable for cache mode: $CACHEMODE"
+}
+
+_default_cache_mode()
+{
+    if $CACHEMODE_IS_DEFAULT; then
+        CACHEMODE="$1"
+        QEMU_IO="$QEMU_IO --cache $1"
+        return
+    fi
 }
 
 # this test requires that a specified command (executable) exists
 #
 _require_command()
 {
-    [ -x "$1" ] || _notrun "$1 utility required, skipped this test"
+    eval c=\$$1
+    [ -x "$c" ] || _notrun "$1 utility required, skipped this test"
 }
 
 _full_imgfmt_details()
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index b63b18c7aa..cc750c986e 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -39,7 +39,7 @@
 030 rw auto backing
 031 rw auto quick
 032 rw auto
-033 rw auto
+033 rw auto quick
 034 rw auto backing
 035 rw auto quick
 036 rw auto quick
@@ -64,6 +64,7 @@
 055 rw auto
 056 rw auto backing
 057 rw auto
+058 rw auto
 059 rw auto
 060 rw auto
 061 rw auto
@@ -77,3 +78,4 @@
 069 rw auto
 070 rw auto
 073 rw auto
+074 rw auto
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 10c9a99e3a..e4fa9af714 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -37,6 +37,7 @@ qemu_args = os.environ.get('QEMU', 'qemu').strip().split(' ')
 imgfmt = os.environ.get('IMGFMT', 'raw')
 imgproto = os.environ.get('IMGPROTO', 'file')
 test_dir = os.environ.get('TEST_DIR', '/var/tmp')
+cachemode = os.environ.get('CACHEMODE')
 
 socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
 
@@ -96,7 +97,7 @@ class VM(object):
         '''Add a virtio-blk drive to the VM'''
         options = ['if=virtio',
                    'format=%s' % imgfmt,
-                   'cache=none',
+                   'cache=%s' % cachemode,
                    'file=%s' % path,
                    'id=drive%d' % self._num_drives]
         if opts:
diff --git a/tests/test-aio.c b/tests/test-aio.c
index c4fe0fc3b7..592721ed3f 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -195,7 +195,6 @@ static void test_bh_delete_from_cb(void)
     g_assert(data1.bh == NULL);
 
     g_assert(!aio_poll(ctx, false));
-    g_assert(!aio_poll(ctx, true));
 }
 
 static void test_bh_delete_from_cb_many(void)
diff --git a/trace-events b/trace-events
index e78a8d3017..9f4456a82e 100644
--- a/trace-events
+++ b/trace-events
@@ -60,11 +60,12 @@ bdrv_aio_discard(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs
 bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p"
 bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
 bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
+bdrv_aio_write_zeroes(void *bs, int64_t sector_num, int nb_sectors, int flags, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d flags %#x opaque %p"
 bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d"
 bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
 bdrv_co_copy_on_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
 bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
-bdrv_co_write_zeroes(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
+bdrv_co_write_zeroes(void *bs, int64_t sector_num, int nb_sector, int flags) "bs %p sector_num %"PRId64" nb_sectors %d flags %#x"
 bdrv_co_io_em(void *bs, int64_t sector_num, int nb_sectors, int is_write, void *acb) "bs %p sector_num %"PRId64" nb_sectors %d is_write %d acb %p"
 bdrv_co_do_copy_on_readv(void *bs, int64_t sector_num, int nb_sectors, int64_t cluster_sector_num, int cluster_nb_sectors) "bs %p sector_num %"PRId64" nb_sectors %d cluster_sector_num %"PRId64" cluster_nb_sectors %d"
 
@@ -127,6 +128,7 @@ thread_pool_cancel(void *req, void *opaque) "req %p opaque %p"
 
 # block/raw-win32.c
 # block/raw-posix.c
+paio_submit_co(int64_t sector_num, int nb_sectors, int type) "sector_num %"PRId64" nb_sectors %d type %d"
 paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d"
 
 # ioport.c