diff options
-rw-r--r-- | block.c | 161 | ||||
-rw-r--r-- | block/iscsi.c | 6 | ||||
-rw-r--r-- | block/qcow2-cluster.c | 1 | ||||
-rw-r--r-- | block/qcow2.c | 25 | ||||
-rw-r--r-- | dma-helpers.c | 1 | ||||
-rw-r--r-- | hw/block/dataplane/virtio-blk.c | 31 | ||||
-rw-r--r-- | include/block/block.h | 1 | ||||
-rw-r--r-- | include/sysemu/iothread.h | 12 | ||||
-rw-r--r-- | iothread.c | 11 | ||||
-rwxr-xr-x | tests/qemu-iotests/039 | 20 | ||||
-rw-r--r-- | tests/qemu-iotests/039.out | 11 | ||||
-rwxr-xr-x | tests/qemu-iotests/051 | 12 | ||||
-rw-r--r-- | tests/qemu-iotests/051.out | 49 |
13 files changed, 225 insertions, 116 deletions
@@ -767,6 +767,11 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags) { int open_flags = flags | BDRV_O_CACHE_WB; + /* The backing file of a temporary snapshot is read-only */ + if (flags & BDRV_O_SNAPSHOT) { + open_flags &= ~BDRV_O_RDWR; + } + /* * Clear flags that are internal to the block layer before opening the * image. @@ -968,7 +973,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename, { BlockDriver *drv; const char *drvname; - bool allow_protocol_prefix = false; + bool parse_filename = false; Error *local_err = NULL; int ret; @@ -977,7 +982,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename, filename = qdict_get_try_str(*options, "filename"); } else if (filename && !qdict_haskey(*options, "filename")) { qdict_put(*options, "filename", qstring_from_str(filename)); - allow_protocol_prefix = true; + parse_filename = true; } else { error_setg(errp, "Can't specify 'file' and 'filename' options at the " "same time"); @@ -994,7 +999,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename, } qdict_del(*options, "driver"); } else if (filename) { - drv = bdrv_find_protocol(filename, allow_protocol_prefix); + drv = bdrv_find_protocol(filename, parse_filename); if (!drv) { error_setg(errp, "Unknown protocol"); } @@ -1010,7 +1015,7 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename, } /* Parse the filename and open it */ - if (drv->bdrv_parse_filename && filename) { + if (drv->bdrv_parse_filename && parse_filename) { drv->bdrv_parse_filename(filename, *options, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -1162,6 +1167,73 @@ done: return ret; } +void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp) +{ + /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ + char tmp_filename[PATH_MAX + 1]; + + int64_t total_size; + BlockDriver *bdrv_qcow2; + QEMUOptionParameter *create_options; + QDict *snapshot_options; + BlockDriverState *bs_snapshot; + Error *local_err; + int ret; + + /* if snapshot, we create a temporary backing file and open it + instead of opening 'filename' directly */ + + /* Get the required size from the image */ + total_size = bdrv_getlength(bs); + if (total_size < 0) { + error_setg_errno(errp, -total_size, "Could not get image size"); + return; + } + total_size &= BDRV_SECTOR_MASK; + + /* Create the temporary image */ + ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not get temporary filename"); + return; + } + + bdrv_qcow2 = bdrv_find_format("qcow2"); + create_options = parse_option_parameters("", bdrv_qcow2->create_options, + NULL); + + set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size); + + ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err); + free_option_parameters(create_options); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not create temporary overlay " + "'%s': %s", tmp_filename, + error_get_pretty(local_err)); + error_free(local_err); + return; + } + + /* Prepare a new options QDict for the temporary file */ + snapshot_options = qdict_new(); + qdict_put(snapshot_options, "file.driver", + qstring_from_str("file")); + qdict_put(snapshot_options, "file.filename", + qstring_from_str(tmp_filename)); + + bs_snapshot = bdrv_new(""); + bs_snapshot->is_temporary = 1; + + ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options, + bs->open_flags & ~BDRV_O_SNAPSHOT, bdrv_qcow2, &local_err); + if (ret < 0) { + error_propagate(errp, local_err); + return; + } + + bdrv_append(bs_snapshot, bs); +} + /* * Opens a disk image (raw, qcow2, vmdk, ...) * @@ -1182,8 +1254,6 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, BlockDriver *drv, Error **errp) { int ret; - /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ - char tmp_filename[PATH_MAX + 1]; BlockDriverState *file = NULL, *bs; const char *drvname; Error *local_err = NULL; @@ -1243,74 +1313,6 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, } } - /* For snapshot=on, create a temporary qcow2 overlay */ - if (flags & BDRV_O_SNAPSHOT) { - BlockDriverState *bs1; - int64_t total_size; - BlockDriver *bdrv_qcow2; - QEMUOptionParameter *create_options; - QDict *snapshot_options; - - /* if snapshot, we create a temporary backing file and open it - instead of opening 'filename' directly */ - - /* Get the required size from the image */ - QINCREF(options); - bs1 = NULL; - ret = bdrv_open(&bs1, filename, NULL, options, BDRV_O_NO_BACKING, - drv, &local_err); - if (ret < 0) { - goto fail; - } - total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK; - - bdrv_unref(bs1); - - /* Create the temporary image */ - ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename)); - if (ret < 0) { - error_setg_errno(errp, -ret, "Could not get temporary filename"); - goto fail; - } - - bdrv_qcow2 = bdrv_find_format("qcow2"); - create_options = parse_option_parameters("", bdrv_qcow2->create_options, - NULL); - - set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size); - - ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err); - free_option_parameters(create_options); - if (ret < 0) { - error_setg_errno(errp, -ret, "Could not create temporary overlay " - "'%s': %s", tmp_filename, - error_get_pretty(local_err)); - error_free(local_err); - local_err = NULL; - goto fail; - } - - /* Prepare a new options QDict for the temporary file, where user - * options refer to the backing file */ - if (filename) { - qdict_put(options, "file.filename", qstring_from_str(filename)); - } - if (drv) { - qdict_put(options, "driver", qstring_from_str(drv->format_name)); - } - - snapshot_options = qdict_new(); - qdict_put(snapshot_options, "backing", options); - qdict_flatten(snapshot_options); - - bs->options = snapshot_options; - options = qdict_clone_shallow(bs->options); - - filename = tmp_filename; - drv = bdrv_qcow2; - bs->is_temporary = 1; - } - /* Open image file without format layer */ if (flags & BDRV_O_RDWR) { flags |= BDRV_O_ALLOW_RDWR; @@ -1372,6 +1374,17 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, } } + /* For snapshot=on, create a temporary qcow2 overlay. bs points to the + * temporary snapshot afterwards. */ + if (flags & BDRV_O_SNAPSHOT) { + bdrv_append_temp_snapshot(bs, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto close_and_fail; + } + } + + done: /* Check if any unknown options were used */ if (options && (qdict_size(options) != 0)) { diff --git a/block/iscsi.c b/block/iscsi.c index 21c18a39dc..64a509f8f4 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1101,8 +1101,10 @@ static struct scsi_task *iscsi_do_inquiry(struct iscsi_context *iscsi, int lun, return task; fail: - error_setg(errp, "iSCSI: Inquiry command failed : %s", - iscsi_get_error(iscsi)); + if (!error_is_set(errp)) { + error_setg(errp, "iSCSI: Inquiry command failed : %s", + iscsi_get_error(iscsi)); + } if (task != NULL) { scsi_free_scsi_task(task); } diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 60a6910b1e..331ab08022 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -491,6 +491,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, break; case QCOW2_CLUSTER_ZERO: if (s->qcow_version < 3) { + qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); return -EIO; } c = count_contiguous_clusters(nb_clusters, s->cluster_size, diff --git a/block/qcow2.c b/block/qcow2.c index 333e26d733..e903d971c3 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -269,12 +269,15 @@ static int qcow2_mark_clean(BlockDriverState *bs) BDRVQcowState *s = bs->opaque; if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) { - int ret = bdrv_flush(bs); + int ret; + + s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY; + + ret = bdrv_flush(bs); if (ret < 0) { return ret; } - s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY; return qcow2_update_header(bs); } return 0; @@ -900,11 +903,25 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key) return 0; } -/* We have nothing to do for QCOW2 reopen, stubs just return - * success */ +/* We have no actual commit/abort logic for qcow2, but we need to write out any + * unwritten data if we reopen read-only. */ static int qcow2_reopen_prepare(BDRVReopenState *state, BlockReopenQueue *queue, Error **errp) { + int ret; + + if ((state->flags & BDRV_O_RDWR) == 0) { + ret = bdrv_flush(state->bs); + if (ret < 0) { + return ret; + } + + ret = qcow2_mark_clean(state->bs); + if (ret < 0) { + return ret; + } + } + return 0; } diff --git a/dma-helpers.c b/dma-helpers.c index c9620a5bbd..5f421e9814 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -213,6 +213,7 @@ BlockDriverAIOCB *dma_bdrv_io( dbs->sg_cur_index = 0; dbs->sg_cur_byte = 0; dbs->dir = dir; + dbs->in_cancel = false; dbs->io_func = io_func; dbs->bh = NULL; qemu_iovec_init(&dbs->iov, sg->nsg); diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index f558b45a60..70b8a5ab75 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -23,7 +23,7 @@ #include "virtio-blk.h" #include "block/aio.h" #include "hw/virtio/virtio-bus.h" -#include "monitor/monitor.h" /* for object_add() */ +#include "qom/object_interfaces.h" enum { SEG_MAX = 126, /* maximum number of I/O segments */ @@ -59,7 +59,7 @@ struct VirtIOBlockDataPlane { * use it). */ IOThread *iothread; - bool internal_iothread; + IOThread internal_iothread_obj; AioContext *ctx; EventNotifier io_notifier; /* Linux AIO completion */ EventNotifier host_notifier; /* doorbell */ @@ -391,23 +391,19 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, s->blk = blk; if (blk->iothread) { - s->internal_iothread = false; s->iothread = blk->iothread; + object_ref(OBJECT(s->iothread)); } else { - /* Create per-device IOThread if none specified */ - Error *local_err = NULL; - - s->internal_iothread = true; - object_add(TYPE_IOTHREAD, vdev->name, NULL, NULL, &local_err); - if (error_is_set(&local_err)) { - error_propagate(errp, local_err); - g_free(s); - return; - } - s->iothread = iothread_find(vdev->name); - assert(s->iothread); + /* Create per-device IOThread if none specified. This is for + * x-data-plane option compatibility. If x-data-plane is removed we + * can drop this. + */ + object_initialize(&s->internal_iothread_obj, + sizeof(s->internal_iothread_obj), + TYPE_IOTHREAD); + user_creatable_complete(OBJECT(&s->internal_iothread_obj), &error_abort); + s->iothread = &s->internal_iothread_obj; } - object_ref(OBJECT(s->iothread)); s->ctx = iothread_get_aio_context(s->iothread); /* Prevent block operations that conflict with data plane thread */ @@ -426,9 +422,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) virtio_blk_data_plane_stop(s); bdrv_set_in_use(s->blk->conf.bs, 0); object_unref(OBJECT(s->iothread)); - if (s->internal_iothread) { - object_unparent(OBJECT(s->iothread)); - } g_free(s); } diff --git a/include/block/block.h b/include/block/block.h index 1ed55d839a..b3230a25f6 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -190,6 +190,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename, QDict *options, const char *bdref_key, int flags, bool allow_none, Error **errp); int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp); +void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp); int bdrv_open(BlockDriverState **pbs, const char *filename, const char *reference, QDict *options, int flags, BlockDriver *drv, Error **errp); diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h index a32214a647..7c01a61d5e 100644 --- a/include/sysemu/iothread.h +++ b/include/sysemu/iothread.h @@ -15,10 +15,20 @@ #define IOTHREAD_H #include "block/aio.h" +#include "qemu/thread.h" #define TYPE_IOTHREAD "iothread" -typedef struct IOThread IOThread; +typedef struct { + Object parent_obj; + + QemuThread thread; + AioContext *ctx; + QemuMutex init_done_lock; + QemuCond init_done_cond; /* is thread initialization done? */ + bool stopping; + int thread_id; +} IOThread; #define IOTHREAD(obj) \ OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD) diff --git a/iothread.c b/iothread.c index cb5986b6c9..1fbf9f1c49 100644 --- a/iothread.c +++ b/iothread.c @@ -14,7 +14,6 @@ #include "qom/object.h" #include "qom/object_interfaces.h" #include "qemu/module.h" -#include "qemu/thread.h" #include "block/aio.h" #include "sysemu/iothread.h" #include "qmp-commands.h" @@ -22,16 +21,6 @@ #define IOTHREADS_PATH "/objects" typedef ObjectClass IOThreadClass; -struct IOThread { - Object parent_obj; - - QemuThread thread; - AioContext *ctx; - QemuMutex init_done_lock; - QemuCond init_done_cond; /* is thread initialization done? */ - bool stopping; - int thread_id; -}; #define IOTHREAD_GET_CLASS(obj) \ OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD) diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 index 9b355c0977..b9cbe99560 100755 --- a/tests/qemu-iotests/039 +++ b/tests/qemu-iotests/039 @@ -131,6 +131,26 @@ ulimit -c "$old_ulimit" ./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features _check_test_img +echo +echo "== Committing to a backing file with lazy_refcounts=on ==" + +IMGOPTS="compat=1.1,lazy_refcounts=on" +TEST_IMG="$TEST_IMG".base _make_test_img $size + +IMGOPTS="compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base" +_make_test_img $size + +$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG commit "$TEST_IMG" + +# The dirty bit must not be set +./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features +./qcow2.py "$TEST_IMG".base dump-header | grep incompatible_features + +_check_test_img +TEST_IMG="$TEST_IMG".base _check_test_img + + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out index 077fa64cbf..fb31ae0624 100644 --- a/tests/qemu-iotests/039.out +++ b/tests/qemu-iotests/039.out @@ -54,4 +54,15 @@ wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) incompatible_features 0x0 No errors were found on the image. + +== Committing to a backing file with lazy_refcounts=on == +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base' +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Image committed. +incompatible_features 0x0 +incompatible_features 0x0 +No errors were found on the image. +No errors were found on the image. *** done diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 14694e176b..073dc7a2d3 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -204,6 +204,10 @@ run_qemu -hda foo:bar run_qemu -drive file=foo:bar run_qemu -drive file.filename=foo:bar +run_qemu -hda "file:$TEST_IMG" +run_qemu -drive file="file:$TEST_IMG" +run_qemu -drive file.filename="file:$TEST_IMG" + echo echo === Snapshot mode === echo @@ -214,6 +218,14 @@ echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG" echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,snapshot=on | _filter_qemu_io echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2 -snapshot | _filter_qemu_io +echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="file:$TEST_IMG" -snapshot | _filter_qemu_io +echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="file:$TEST_IMG",snapshot=on | _filter_qemu_io + +# Opening a read-only file r/w with snapshot=on +chmod u-w "$TEST_IMG" +echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG" -snapshot | _filter_qemu_io +echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io +chmod u+w "$TEST_IMG" $QEMU_IO -c "read -P 0x11 0 4k" "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index f5e33ff395..01b0384472 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -44,11 +44,11 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TE === Overriding backing file === Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults -QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K
-ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
- Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
-(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
+QEMU X.Y.Z monitor - type 'help' for more information +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K +ide0-hd0: TEST_DIR/t.qcow2 (qcow2) + Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K === Enable and disable lazy refcounting on the command line, plus some invalid values === @@ -275,6 +275,17 @@ QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: Unknown proto Testing: -drive file.filename=foo:bar QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open 'foo:bar': No such file or directory +Testing: -hda file:TEST_DIR/t.qcow2 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=file:TEST_DIR/t.qcow2 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file.filename=file:TEST_DIR/t.qcow2 +QEMU_PROG: -drive file.filename=file:TEST_DIR/t.qcow2: could not open disk image ide0-hd0: Could not open 'file:TEST_DIR/t.qcow2': No such file or directory + === Snapshot mode === @@ -308,6 +319,34 @@ wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +Testing: -drive file=file:TEST_DIR/t.qcow2 -snapshot +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2 -snapshot +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + read 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off |