]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'elmarco/tags/chr-tests-pull-request' into staging
authorStefan Hajnoczi <stefanha@redhat.com>
Fri, 5 May 2017 16:04:07 +0000 (17:04 +0100)
committerStefan Hajnoczi <stefanha@redhat.com>
Fri, 5 May 2017 16:07:55 +0000 (17:07 +0100)
# gpg: Signature made Thu 04 May 2017 12:42:10 PM BST
# gpg:                using RSA key 0xDAE8E10975969CE5
# gpg: Good signature from "Marc-AndrĂ© Lureau <marcandre.lureau@redhat.com>"
# gpg:                 aka "Marc-AndrĂ© Lureau <marcandre.lureau@gmail.com>"
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* elmarco/tags/chr-tests-pull-request: (21 commits)
  tests: add /char/console test
  tests: add /char/udp test
  tests: add /char/socket test
  tests: add /char/file test
  tests: add /char/pipe test
  tests: add alias check in /char/ringbuf
  char-udp: flush as much buffer as possible
  char-socket: add 'connected' property
  char-socket: add 'addr' property
  char-socket: update local address after listen
  char-socket: introduce update_disconnected_filename()
  char: useless NULL check
  char: remove chardevs list
  char: remove qemu_chardev_add
  char: use /chardevs container instead of chardevs list
  vl: add todo note about root container cleanup
  char: add a /chardevs container
  container: don't leak container reference
  xen: use a better chardev type check
  mux: simplfy muxes_realize_done
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
144 files changed:
MAINTAINERS
audio/audio.c
audio/wavcapture.c
block.c
block/blkdebug.c
block/blkreplay.c
block/blkverify.c
block/block-backend.c
block/commit.c
block/crypto.c
block/file-posix.c
block/file-win32.c
block/gluster.c
block/io.c
block/iscsi.c
block/mirror.c
block/nfs.c
block/parallels.c
block/qcow.c
block/qcow2-refcount.c
block/qcow2.c
block/qed.c
block/raw-format.c
block/rbd.c
block/sheepdog.c
block/vdi.c
block/vhdx-log.c
block/vhdx.c
block/vmdk.c
block/vpc.c
blockdev.c
chardev/char-socket.c
chardev/char.c
default-configs/s390x-softmmu.mak
hmp.c
hmp.h
hw/audio/Makefile.objs
hw/audio/adlib.c
hw/audio/fmopl.c
hw/audio/fmopl.h
hw/audio/gus.c
hw/audio/gusemu.h
hw/audio/gusemu_hal.c
hw/audio/gusemu_mixer.c
hw/audio/hda-codec.c
hw/audio/intel-hda.c
hw/audio/intel-hda.h
hw/char/Makefile.objs
hw/char/terminal3270.c [new file with mode: 0644]
hw/input/hid.c
hw/input/trace-events
hw/openrisc/cputimer.c
hw/s390x/3270-ccw.c [new file with mode: 0644]
hw/s390x/Makefile.objs
hw/s390x/css.c
hw/s390x/ipl.c
hw/s390x/ipl.h
hw/s390x/s390-virtio-ccw.c
hw/s390x/sclp.c
hw/vfio/common.c
hw/vfio/pci.c
include/block/block.h
include/block/block_int.h
include/exec/ram_addr.h
include/hw/s390x/3270-ccw.h [new file with mode: 0644]
include/hw/s390x/css.h
include/hw/s390x/s390-virtio-ccw.h
include/migration/cpu.h
include/migration/migration.h
include/migration/postcopy-ram.h [deleted file]
include/migration/vmstate.h
include/sysemu/block-backend.h
include/sysemu/char.h
include/sysemu/sysemu.h
linux-user/elfload.c
linux-user/main.c
linux-user/openrisc/target_cpu.h
linux-user/openrisc/target_signal.h
linux-user/signal.c
migration/exec.c
migration/migration.c
migration/postcopy-ram.c
migration/postcopy-ram.h [new file with mode: 0644]
migration/ram.c
migration/savevm.c
migration/socket.c
migration/tls.c
migration/trace-events
monitor.c
pc-bios/s390-ccw.img
pc-bios/s390-ccw/Makefile
pc-bios/s390-ccw/bootmap.c
pc-bios/s390-ccw/bootmap.h
pc-bios/s390-ccw/main.c
pc-bios/s390-ccw/s390-ccw.h
pc-bios/s390-ccw/sclp-ascii.c [deleted file]
pc-bios/s390-ccw/sclp.c [new file with mode: 0644]
pc-bios/s390-ccw/sclp.h
qapi-schema.json
qemu-img-cmds.hx
qemu-img.c
qemu-img.texi
qemu-io-cmds.c
qemu-options.hx
replay/replay-snapshot.c
target/openrisc/cpu.c
target/openrisc/cpu.h
target/openrisc/gdbstub.c
target/openrisc/interrupt.c
target/openrisc/machine.c
target/openrisc/mmu.c
target/openrisc/sys_helper.c
target/openrisc/translate.c
tests/qemu-iotests/026
tests/qemu-iotests/026.out
tests/qemu-iotests/026.out.nocache
tests/qemu-iotests/028.out
tests/qemu-iotests/051
tests/qemu-iotests/051.out
tests/qemu-iotests/051.pc.out
tests/qemu-iotests/066
tests/qemu-iotests/066.out
tests/qemu-iotests/068
tests/qemu-iotests/068.out
tests/qemu-iotests/109
tests/qemu-iotests/109.out
tests/qemu-iotests/122.out
tests/qemu-iotests/130.out
tests/qemu-iotests/142
tests/qemu-iotests/142.out
tests/qemu-iotests/145
tests/qemu-iotests/145.out
tests/qemu-iotests/181 [new file with mode: 0755]
tests/qemu-iotests/181.out [new file with mode: 0644]
tests/qemu-iotests/common
tests/qemu-iotests/common.config
tests/qemu-iotests/common.filter
tests/qemu-iotests/common.qemu
tests/qemu-iotests/common.rc
tests/qemu-iotests/group
ui/input.c
util/qemu-config.c
util/qemu-progress.c
vl.c

index a1d2b3a4d334f50c1eacce90c56c83382608ab84..efdec473196f9705e0f44edf486756c9e1d91688 100644 (file)
@@ -196,8 +196,8 @@ F: hw/nios2/
 F: disas/nios2.c
 
 OpenRISC
-M: Jia Liu <proljc@gmail.com>
-S: Maintained
+M: Stafford Horne <shorne@gmail.com>
+S: Odd Fixes
 F: target/openrisc/
 F: hw/openrisc/
 F: tests/tcg/openrisc/
index c8898d8422d58b6ec8cd4a9a09790234eff164df..beafed209bde7e3905c90b2a51df7d6d152ad044 100644 (file)
@@ -2028,6 +2028,8 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
                     sw = sw1;
                 }
                 QLIST_REMOVE (cap, entries);
+                g_free (cap->hw.mix_buf);
+                g_free (cap->buf);
                 g_free (cap);
             }
             return;
index 8bfb9e765468936137a12e844ce578846f8b393d..5863803584baa2bc02d3b51331e9d47ade480866 100644 (file)
@@ -88,6 +88,7 @@ static void wav_capture_destroy (void *opaque)
     WAVState *wav = opaque;
 
     AUD_del_capture (wav->cap, wav);
+    g_free (wav);
 }
 
 static void wav_capture_info (void *opaque)
diff --git a/block.c b/block.c
index 5db266be2103a1c6db107600f26afd39abd05a08..6c6bb3ec7af88ef111f6c2a8cdb4efb11f20657d 100644 (file)
--- a/block.c
+++ b/block.c
@@ -1204,7 +1204,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
         filename = qdict_get_try_str(options, "filename");
     }
 
-    if (drv->bdrv_needs_filename && !filename) {
+    if (drv->bdrv_needs_filename && (!filename || !filename[0])) {
         error_setg(errp, "The '%s' block driver requires a file name",
                    drv->format_name);
         ret = -EINVAL;
@@ -3307,26 +3307,30 @@ exit:
 /**
  * Truncate file to 'offset' bytes (needed only for file protocols)
  */
-int bdrv_truncate(BdrvChild *child, int64_t offset)
+int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp)
 {
     BlockDriverState *bs = child->bs;
     BlockDriver *drv = bs->drv;
     int ret;
 
-    /* FIXME: Some format block drivers use this function instead of implicitly
-     *        growing their file by writing beyond its end.
-     *        See bdrv_aligned_pwritev() for an explanation why we currently
-     *        cannot assert this permission in that case. */
-    // assert(child->perm & BLK_PERM_RESIZE);
+    assert(child->perm & BLK_PERM_RESIZE);
 
-    if (!drv)
+    if (!drv) {
+        error_setg(errp, "No medium inserted");
         return -ENOMEDIUM;
-    if (!drv->bdrv_truncate)
+    }
+    if (!drv->bdrv_truncate) {
+        error_setg(errp, "Image format driver does not support resize");
         return -ENOTSUP;
-    if (bs->read_only)
+    }
+    if (bs->read_only) {
+        error_setg(errp, "Image is read-only");
         return -EACCES;
+    }
+
+    assert(!(bs->open_flags & BDRV_O_INACTIVE));
 
-    ret = drv->bdrv_truncate(bs, offset);
+    ret = drv->bdrv_truncate(bs, offset, errp);
     if (ret == 0) {
         ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
         bdrv_dirty_bitmap_truncate(bs);
index 67e8024e36db9dbae51ec4a1711c4aeac759e833..d2a7561c4c06b6084b7a53602f55da0fb5106442 100644 (file)
@@ -389,14 +389,12 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     } else if (align) {
         error_setg(errp, "Invalid alignment");
         ret = -EINVAL;
-        goto fail_unref;
+        goto out;
     }
 
     ret = 0;
     goto out;
 
-fail_unref:
-    bdrv_unref_child(bs, bs->file);
 out:
     if (ret < 0) {
         g_free(s->config_file);
@@ -661,9 +659,9 @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
     return bdrv_getlength(bs->file->bs);
 }
 
-static int blkdebug_truncate(BlockDriverState *bs, int64_t offset)
+static int blkdebug_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
-    return bdrv_truncate(bs->file, offset);
+    return bdrv_truncate(bs->file, offset, errp);
 }
 
 static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
index e1102119fbeafc4d72fbca0cd1a1b029372ffb03..6aa5fd4156e61b8e718b47ad741c9889e10cdcf2 100755 (executable)
@@ -37,9 +37,6 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
 
     ret = 0;
 fail:
-    if (ret < 0) {
-        bdrv_unref_child(bs, bs->file);
-    }
     return ret;
 }
 
index 9a1e21c6ad3723375fa97a9ba0225e956732a31f..af23281669e979b5d2ddc740676c81235d7d125a 100644 (file)
@@ -142,9 +142,6 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
 
     ret = 0;
 fail:
-    if (ret < 0) {
-        bdrv_unref_child(bs, bs->file);
-    }
     qemu_opts_del(opts);
     return ret;
 }
index 7405024e08a438ffcf44cb79b162b0dfe0695b24..f5bf13eec90949facc7c7e85427e54053c77c692 100644 (file)
@@ -420,7 +420,7 @@ void monitor_remove_blk(BlockBackend *blk)
  * Return @blk's name, a non-null string.
  * Returns an empty string iff @blk is not referenced by the monitor.
  */
-const char *blk_name(BlockBackend *blk)
+const char *blk_name(const BlockBackend *blk)
 {
     return blk->name ?: "";
 }
@@ -1746,13 +1746,14 @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
                    BDRV_REQ_WRITE_COMPRESSED);
 }
 
-int blk_truncate(BlockBackend *blk, int64_t offset)
+int blk_truncate(BlockBackend *blk, int64_t offset, Error **errp)
 {
     if (!blk_is_available(blk)) {
+        error_setg(errp, "No medium inserted");
         return -ENOMEDIUM;
     }
 
-    return bdrv_truncate(blk->root, offset);
+    return bdrv_truncate(blk->root, offset, errp);
 }
 
 static void blk_pdiscard_entry(void *opaque)
index 91d2c344f62cc723e7f94cf5364de4763247c5d3..76a0d98c6f5c0678e0135e9bd83ffc7eb0063aca 100644 (file)
@@ -151,7 +151,7 @@ static void coroutine_fn commit_run(void *opaque)
     }
 
     if (base_len < s->common.len) {
-        ret = blk_truncate(s->base, s->common.len);
+        ret = blk_truncate(s->base, s->common.len, NULL);
         if (ret) {
             goto out;
         }
@@ -511,8 +511,9 @@ int bdrv_commit(BlockDriverState *bs)
      * grow the backing file image if possible.  If not possible,
      * we must return an error */
     if (length > backing_length) {
-        ret = blk_truncate(backing, length);
+        ret = blk_truncate(backing, length, &local_err);
         if (ret < 0) {
+            error_report_err(local_err);
             goto ro_cleanup;
         }
     }
index 34549b28a508e646786f2ccc4fe8e9ea088ffeb9..6828180840c30816fa8708c3dabb489da8043dcb 100644 (file)
@@ -381,7 +381,8 @@ static int block_crypto_create_generic(QCryptoBlockFormat format,
     return ret;
 }
 
-static int block_crypto_truncate(BlockDriverState *bs, int64_t offset)
+static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
+                                 Error **errp)
 {
     BlockCrypto *crypto = bs->opaque;
     size_t payload_offset =
@@ -389,7 +390,7 @@ static int block_crypto_truncate(BlockDriverState *bs, int64_t offset)
 
     offset += payload_offset;
 
-    return bdrv_truncate(bs->file, offset);
+    return bdrv_truncate(bs->file, offset, errp);
 }
 
 static void block_crypto_close(BlockDriverState *bs)
index 0c4896876e24d34ecaeffc6e883709761dad289f..1941fb6749a0efc07de978677ad8bfaafe006d08 100644 (file)
@@ -25,8 +25,6 @@
 #include "qapi/error.h"
 #include "qemu/cutils.h"
 #include "qemu/error-report.h"
-#include "qemu/timer.h"
-#include "qemu/log.h"
 #include "block/block_int.h"
 #include "qemu/module.h"
 #include "trace.h"
@@ -1409,24 +1407,31 @@ static void raw_close(BlockDriverState *bs)
     }
 }
 
-static int raw_truncate(BlockDriverState *bs, int64_t offset)
+static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
     BDRVRawState *s = bs->opaque;
     struct stat st;
+    int ret;
 
     if (fstat(s->fd, &st)) {
-        return -errno;
+        ret = -errno;
+        error_setg_errno(errp, -ret, "Failed to fstat() the file");
+        return ret;
     }
 
     if (S_ISREG(st.st_mode)) {
         if (ftruncate(s->fd, offset) < 0) {
-            return -errno;
+            ret = -errno;
+            error_setg_errno(errp, -ret, "Failed to resize the file");
+            return ret;
         }
     } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
-       if (offset > raw_getlength(bs)) {
-           return -EINVAL;
-       }
+        if (offset > raw_getlength(bs)) {
+            error_setg(errp, "Cannot grow device files");
+            return -EINVAL;
+        }
     } else {
+        error_setg(errp, "Resizing this file is not supported");
         return -ENOTSUP;
     }
 
index 800fabdd727f1d8290a7173707e9e57fc7499cf1..7872e00a2106cc3dae34826b937353cb0a653c45 100644 (file)
@@ -24,7 +24,6 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu/cutils.h"
-#include "qemu/timer.h"
 #include "block/block_int.h"
 #include "qemu/module.h"
 #include "block/raw-aio.h"
@@ -461,7 +460,7 @@ static void raw_close(BlockDriverState *bs)
     }
 }
 
-static int raw_truncate(BlockDriverState *bs, int64_t offset)
+static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
     BDRVRawState *s = bs->opaque;
     LONG low, high;
@@ -476,11 +475,11 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
      */
     dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN);
     if (dwPtrLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
-        fprintf(stderr, "SetFilePointer error: %lu\n", GetLastError());
+        error_setg_win32(errp, GetLastError(), "SetFilePointer error");
         return -EIO;
     }
     if (SetEndOfFile(s->hfile) == 0) {
-        fprintf(stderr, "SetEndOfFile error: %lu\n", GetLastError());
+        error_setg_win32(errp, GetLastError(), "SetEndOfFile error");
         return -EIO;
     }
     return 0;
index cf29b5f9a474910bafda3ffe6cdf166df2f916c8..1d4e2f7c52df135105a5f015899b63a75b3358ca 100644 (file)
@@ -1092,14 +1092,17 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
     return acb.ret;
 }
 
-static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset)
+static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset,
+                                 Error **errp)
 {
     int ret;
     BDRVGlusterState *s = bs->opaque;
 
     ret = glfs_ftruncate(s->fd, offset);
     if (ret < 0) {
-        return -errno;
+        ret = -errno;
+        error_setg_errno(errp, -ret, "Failed to truncate file");
+        return ret;
     }
 
     return 0;
index a7142e00e833fcb6f752c32b9bbd3f0a26956e89..40bd94f3235b5ae062a1bc08ccbafe8012ab1940 100644 (file)
@@ -1362,16 +1362,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
     assert(!waited || !req->serialising);
     assert(req->overlap_offset <= offset);
     assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
-    /* FIXME: Block migration uses the BlockBackend of the guest device at a
-     *        point when it has not yet taken write permissions. This will be
-     *        fixed by a future patch, but for now we have to bypass this
-     *        assertion for block migration to work. */
-    // assert(child->perm & BLK_PERM_WRITE);
-    /* FIXME: Because of the above, we also cannot guarantee that all format
-     *        BDS take the BLK_PERM_RESIZE permission on their file BDS, since
-     *        they are not obligated to do so if they do not have any parent
-     *        that has taken the permission to write to them. */
-    // assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
+    assert(child->perm & BLK_PERM_WRITE);
+    assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
 
     ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
 
@@ -1452,7 +1444,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
     int ret = 0;
 
     head_padding_bytes = offset & (align - 1);
-    tail_padding_bytes = align - ((offset + bytes) & (align - 1));
+    tail_padding_bytes = (align - (offset + bytes)) & (align - 1);
 
 
     assert(flags & BDRV_REQ_ZERO_WRITE);
@@ -2308,7 +2300,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
 
     bdrv_inc_in_flight(bs);
 
-    if (!bs || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs) ||
+    if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs) ||
         bdrv_is_sg(bs)) {
         goto early_exit;
     }
index 42fb0b019c5b34370e87690427cf88f2cd7cd25d..5daa20118191d90309f6deb5f585aa93fce6f874 100644 (file)
@@ -2059,22 +2059,24 @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
     }
 }
 
-static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
+static int iscsi_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
     IscsiLun *iscsilun = bs->opaque;
     Error *local_err = NULL;
 
     if (iscsilun->type != TYPE_DISK) {
+        error_setg(errp, "Cannot resize non-disk iSCSI devices");
         return -ENOTSUP;
     }
 
     iscsi_readcapacity_sync(iscsilun, &local_err);
     if (local_err != NULL) {
-        error_free(local_err);
+        error_propagate(errp, local_err);
         return -EIO;
     }
 
     if (offset > iscsi_getlength(bs)) {
+        error_setg(errp, "Cannot grow iSCSI devices");
         return -EINVAL;
     }
 
index 9f5eb692fd71b740cdc4de92b201e94bfc071a51..e86f8f8ad706268828812f0144ef3e57e6e22f2e 100644 (file)
@@ -724,7 +724,7 @@ static void coroutine_fn mirror_run(void *opaque)
         }
 
         if (s->bdev_length > base_length) {
-            ret = blk_truncate(s->target, s->bdev_length);
+            ret = blk_truncate(s->target, s->bdev_length, NULL);
             if (ret < 0) {
                 goto immediate_exit;
             }
index 6541dec1fcc1afd46a6226ae7c0381b6b9f727f5..76572ae54696ec68cc63d40b603de4265b78b9ba 100644 (file)
@@ -764,10 +764,18 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
     return (task.ret < 0 ? task.ret : st.st_blocks * 512);
 }
 
-static int nfs_file_truncate(BlockDriverState *bs, int64_t offset)
+static int nfs_file_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
     NFSClient *client = bs->opaque;
-    return nfs_ftruncate(client->context, client->fh, offset);
+    int ret;
+
+    ret = nfs_ftruncate(client->context, client->fh, offset);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "Failed to truncate file");
+        return ret;
+    }
+
+    return 0;
 }
 
 /* Note that this will not re-establish a connection with the NFS server
index 90acf796874e0e318132d7ee8689d2db66711769..8be46a7d48ac61d41fc9dbde7e67b5330913b71b 100644 (file)
@@ -223,7 +223,8 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
                                      space << BDRV_SECTOR_BITS, 0);
         } else {
             ret = bdrv_truncate(bs->file,
-                                (s->data_end + space) << BDRV_SECTOR_BITS);
+                                (s->data_end + space) << BDRV_SECTOR_BITS,
+                                NULL);
         }
         if (ret < 0) {
             return ret;
@@ -456,8 +457,10 @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
                 size - res->image_end_offset);
         res->leaks += count;
         if (fix & BDRV_FIX_LEAKS) {
-            ret = bdrv_truncate(bs->file, res->image_end_offset);
+            Error *local_err = NULL;
+            ret = bdrv_truncate(bs->file, res->image_end_offset, &local_err);
             if (ret < 0) {
+                error_report_err(local_err);
                 res->check_errors++;
                 return ret;
             }
@@ -504,7 +507,7 @@ static int parallels_create(const char *filename, QemuOpts *opts, Error **errp)
 
     blk_set_allow_write_beyond_eof(file, true);
 
-    ret = blk_truncate(file, 0);
+    ret = blk_truncate(file, 0, errp);
     if (ret < 0) {
         goto exit;
     }
@@ -696,7 +699,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
-            bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
+            bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs), NULL) != 0) {
         s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
     }
 
@@ -739,7 +742,7 @@ static void parallels_close(BlockDriverState *bs)
     }
 
     if (bs->open_flags & BDRV_O_RDWR) {
-        bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS);
+        bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, NULL);
     }
 
     g_free(s->bat_dirty_bmap);
index 9d6ac839593b74674ad8104589999486bd1cc105..5d147b962e6e821c0ac4b99d704e75d819c0f3cc 100644 (file)
@@ -473,7 +473,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
                 /* round to cluster size */
                 cluster_offset = (cluster_offset + s->cluster_size - 1) &
                     ~(s->cluster_size - 1);
-                bdrv_truncate(bs->file, cluster_offset + s->cluster_size);
+                bdrv_truncate(bs->file, cluster_offset + s->cluster_size, NULL);
                 /* if encrypted, we must initialize the cluster
                    content which won't be written */
                 if (bs->encrypted &&
@@ -833,7 +833,7 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
 
     blk_set_allow_write_beyond_eof(qcow_blk, true);
 
-    ret = blk_truncate(qcow_blk, 0);
+    ret = blk_truncate(qcow_blk, 0, errp);
     if (ret < 0) {
         goto exit;
     }
@@ -916,7 +916,7 @@ static int qcow_make_empty(BlockDriverState *bs)
     if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table,
             l1_length) < 0)
         return -1;
-    ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length);
+    ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, NULL);
     if (ret < 0)
         return ret;
 
index 9e96f64c8b59f2ff581d48cb97c4bbc0b79117c9..4efca7ebdbee687e5f0a54ff71fbffe9cc83f8f3 100644 (file)
@@ -1728,14 +1728,17 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
 
             if (fix & BDRV_FIX_ERRORS) {
                 int64_t new_nb_clusters;
+                Error *local_err = NULL;
 
                 if (offset > INT64_MAX - s->cluster_size) {
                     ret = -EINVAL;
                     goto resize_fail;
                 }
 
-                ret = bdrv_truncate(bs->file, offset + s->cluster_size);
+                ret = bdrv_truncate(bs->file, offset + s->cluster_size,
+                                    &local_err);
                 if (ret < 0) {
+                    error_report_err(local_err);
                     goto resize_fail;
                 }
                 size = bdrv_getlength(bs->file->bs);
index 6a92d2ef3f082cbcef67428d555838d698a083b7..5c1573c9993ad41df5dbb61738fe262c79901816 100644 (file)
@@ -2294,9 +2294,9 @@ static int qcow2_create2(const char *filename, int64_t total_size,
     }
 
     /* Okay, now that we have a valid image, let's give it the right size */
-    ret = blk_truncate(blk, total_size);
+    ret = blk_truncate(blk, total_size, errp);
     if (ret < 0) {
-        error_setg_errno(errp, -ret, "Could not resize image");
+        error_prepend(errp, "Could not resize image: ");
         goto out;
     }
 
@@ -2515,7 +2515,12 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
 
     if (!QEMU_IS_ALIGNED(offset | count, s->cluster_size)) {
         assert(count < s->cluster_size);
-        return -ENOTSUP;
+        /* Ignore partial clusters, except for the special case of the
+         * complete partial cluster at the end of an unaligned file */
+        if (!QEMU_IS_ALIGNED(offset, s->cluster_size) ||
+            offset + count != bs->total_sectors * BDRV_SECTOR_SIZE) {
+            return -ENOTSUP;
+        }
     }
 
     qemu_co_mutex_lock(&s->lock);
@@ -2525,32 +2530,33 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
     return ret;
 }
 
-static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
+static int qcow2_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
     BDRVQcow2State *s = bs->opaque;
     int64_t new_l1_size;
     int ret;
 
     if (offset & 511) {
-        error_report("The new size must be a multiple of 512");
+        error_setg(errp, "The new size must be a multiple of 512");
         return -EINVAL;
     }
 
     /* cannot proceed if image has snapshots */
     if (s->nb_snapshots) {
-        error_report("Can't resize an image which has snapshots");
+        error_setg(errp, "Can't resize an image which has snapshots");
         return -ENOTSUP;
     }
 
     /* shrinking is currently not supported */
     if (offset < bs->total_sectors * 512) {
-        error_report("qcow2 doesn't support shrinking images yet");
+        error_setg(errp, "qcow2 doesn't support shrinking images yet");
         return -ENOTSUP;
     }
 
     new_l1_size = size_to_l1(s, offset);
     ret = qcow2_grow_l1_table(bs, new_l1_size, true);
     if (ret < 0) {
+        error_setg_errno(errp, -ret, "Failed to grow the L1 table");
         return ret;
     }
 
@@ -2559,6 +2565,7 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
     ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
                            &offset, sizeof(uint64_t));
     if (ret < 0) {
+        error_setg_errno(errp, -ret, "Failed to update the image size");
         return ret;
     }
 
@@ -2584,7 +2591,7 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
         /* align end of file to a sector boundary to ease reading with
            sector based I/Os */
         cluster_offset = bdrv_getlength(bs->file->bs);
-        return bdrv_truncate(bs->file, cluster_offset);
+        return bdrv_truncate(bs->file, cluster_offset, NULL);
     }
 
     buf = qemu_blockalign(bs, s->cluster_size);
@@ -2674,6 +2681,7 @@ fail:
 static int make_completely_empty(BlockDriverState *bs)
 {
     BDRVQcow2State *s = bs->opaque;
+    Error *local_err = NULL;
     int ret, l1_clusters;
     int64_t offset;
     uint64_t *new_reftable = NULL;
@@ -2798,8 +2806,10 @@ static int make_completely_empty(BlockDriverState *bs)
         goto fail;
     }
 
-    ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size);
+    ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size,
+                        &local_err);
     if (ret < 0) {
+        error_report_err(local_err);
         goto fail;
     }
 
@@ -3273,9 +3283,10 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
             return ret;
         }
 
-        ret = blk_truncate(blk, new_size);
+        ret = blk_truncate(blk, new_size, &local_err);
         blk_unref(blk);
         if (ret < 0) {
+            error_report_err(local_err);
             return ret;
         }
     }
index 5ec7fd83f25954ac35fdfe7d5f1c7833d58feedb..fd76817cbb6a3ddfb38f3b42e68f93202bfa0b14 100644 (file)
@@ -635,7 +635,7 @@ static int qed_create(const char *filename, uint32_t cluster_size,
     blk_set_allow_write_beyond_eof(blk, true);
 
     /* File must start empty and grow, check truncate is supported */
-    ret = blk_truncate(blk, 0);
+    ret = blk_truncate(blk, 0, errp);
     if (ret < 0) {
         goto out;
     }
@@ -1518,7 +1518,7 @@ static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
     return cb.ret;
 }
 
-static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
+static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
     BDRVQEDState *s = bs->opaque;
     uint64_t old_image_size;
@@ -1526,11 +1526,12 @@ static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
 
     if (!qed_is_image_size_valid(offset, s->header.cluster_size,
                                  s->header.table_size)) {
+        error_setg(errp, "Invalid image size specified");
         return -EINVAL;
     }
 
-    /* Shrinking is currently not supported */
     if ((uint64_t)offset < s->header.image_size) {
+        error_setg(errp, "Shrinking images is currently not supported");
         return -ENOTSUP;
     }
 
@@ -1539,6 +1540,7 @@ static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
     ret = qed_write_header_sync(s);
     if (ret < 0) {
         s->header.image_size = old_image_size;
+        error_setg_errno(errp, -ret, "Failed to update the image size");
     }
     return ret;
 }
index 86fbc657ebeac4967bf7613e8e6e47dda7c04078..36e65036f075a3659656459d7922b3c34396e578 100644 (file)
@@ -327,21 +327,23 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
     }
 }
 
-static int raw_truncate(BlockDriverState *bs, int64_t offset)
+static int raw_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
     BDRVRawState *s = bs->opaque;
 
     if (s->has_size) {
+        error_setg(errp, "Cannot resize fixed-size raw disks");
         return -ENOTSUP;
     }
 
     if (INT64_MAX - offset < s->offset) {
+        error_setg(errp, "Disk size too large for the chosen offset");
         return -EINVAL;
     }
 
     s->size = offset;
     offset += s->offset;
-    return bdrv_truncate(bs->file, offset);
+    return bdrv_truncate(bs->file, offset, errp);
 }
 
 static int raw_media_changed(BlockDriverState *bs)
index 6471f4fd2bd16abeb1f1a269027f3dcc2f3a187c..fbf30591d16ffde887c4105b6276218363ef10d5 100644 (file)
@@ -916,13 +916,14 @@ static int64_t qemu_rbd_getlength(BlockDriverState *bs)
     return info.size;
 }
 
-static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset)
+static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
     BDRVRBDState *s = bs->opaque;
     int r;
 
     r = rbd_resize(s->image, offset);
     if (r < 0) {
+        error_setg_errno(errp, -r, "Failed to resize file");
         return r;
     }
 
index b2a5998188cc379a90ff3032ce9470a75a4f7a06..fe8fd923d54fd79fc83b51f96989d2592ea8933f 100644 (file)
@@ -2159,9 +2159,8 @@ static int64_t sd_getlength(BlockDriverState *bs)
     return s->inode.vdi_size;
 }
 
-static int sd_truncate(BlockDriverState *bs, int64_t offset)
+static int sd_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
 {
-    Error *local_err = NULL;
     BDRVSheepdogState *s = bs->opaque;
     int ret, fd;
     unsigned int datalen;
@@ -2169,16 +2168,15 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
 
     max_vdi_size = (UINT64_C(1) << s->inode.block_size_shift) * MAX_DATA_OBJS;
     if (offset < s->inode.vdi_size) {
-        error_report("shrinking is not supported");
+        error_setg(errp, "shrinking is not supported");
         return -EINVAL;
     } else if (offset > max_vdi_size) {
-        error_report("too big image size");
+        error_setg(errp, "too big image size");
         return -EINVAL;
     }
 
-    fd = connect_to_sdog(s, &local_err);
+    fd = connect_to_sdog(s, errp);
     if (fd < 0) {
-        error_report_err(local_err);
         return fd;
     }
 
@@ -2191,7 +2189,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
     close(fd);
 
     if (ret < 0) {
-        error_report("failed to update an inode.");
+        error_setg_errno(errp, -ret, "failed to update an inode");
     }
 
     return ret;
@@ -2456,7 +2454,7 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
     BDRVSheepdogState *s = bs->opaque;
 
     if (offset > s->inode.vdi_size) {
-        ret = sd_truncate(bs, offset);
+        ret = sd_truncate(bs, offset, NULL);
         if (ret < 0) {
             return ret;
         }
index 9b4f70e97747ae452689ceeba3c6a6610efe3a1b..d12d9cdc79ccee03db6f292f0c208227965c1282 100644 (file)
@@ -832,9 +832,9 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
     }
 
     if (image_type == VDI_TYPE_STATIC) {
-        ret = blk_truncate(blk, offset + blocks * block_size);
+        ret = blk_truncate(blk, offset + blocks * block_size, errp);
         if (ret < 0) {
-            error_setg(errp, "Failed to statically allocate %s", filename);
+            error_prepend(errp, "Failed to statically allocate %s", filename);
             goto exit;
         }
     }
index 67a91c0de55e69f6dc4235d743180729e65e68b3..3f4c2aa095ab6a01f444af0158666eb9083677e9 100644 (file)
@@ -548,7 +548,7 @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
             if (new_file_size % (1024*1024)) {
                 /* round up to nearest 1MB boundary */
                 new_file_size = ((new_file_size >> 20) + 1) << 20;
-                bdrv_truncate(bs->file, new_file_size);
+                bdrv_truncate(bs->file, new_file_size, NULL);
             }
         }
         qemu_vfree(desc_entries);
index 052a753159d6e649cc314da6bd7ccc588b7b4920..e8fe3fb5e9417ba851b50a0ebcdc89d9ec49aee6 100644 (file)
@@ -1171,7 +1171,7 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
     /* per the spec, the address for a block is in units of 1MB */
     *new_offset = ROUND_UP(*new_offset, 1024 * 1024);
 
-    return bdrv_truncate(bs->file, *new_offset + s->block_size);
+    return bdrv_truncate(bs->file, *new_offset + s->block_size, NULL);
 }
 
 /*
@@ -1586,7 +1586,7 @@ exit:
 static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
                            uint64_t image_size, VHDXImageType type,
                            bool use_zero_blocks, uint64_t file_offset,
-                           uint32_t length)
+                           uint32_t length, Error **errp)
 {
     int ret = 0;
     uint64_t data_file_offset;
@@ -1607,16 +1607,17 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
     if (type == VHDX_TYPE_DYNAMIC) {
         /* All zeroes, so we can just extend the file - the end of the BAT
          * is the furthest thing we have written yet */
-        ret = blk_truncate(blk, data_file_offset);
+        ret = blk_truncate(blk, data_file_offset, errp);
         if (ret < 0) {
             goto exit;
         }
     } else if (type == VHDX_TYPE_FIXED) {
-        ret = blk_truncate(blk, data_file_offset + image_size);
+        ret = blk_truncate(blk, data_file_offset + image_size, errp);
         if (ret < 0) {
             goto exit;
         }
     } else {
+        error_setg(errp, "Unsupported image type");
         ret = -ENOTSUP;
         goto exit;
     }
@@ -1627,6 +1628,7 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
         /* for a fixed file, the default BAT entry is not zero */
         s->bat = g_try_malloc0(length);
         if (length && s->bat == NULL) {
+            error_setg(errp, "Failed to allocate memory for the BAT");
             ret = -ENOMEM;
             goto exit;
         }
@@ -1646,6 +1648,7 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
         }
         ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
         if (ret < 0) {
+            error_setg_errno(errp, -ret, "Failed to write the BAT");
             goto exit;
         }
     }
@@ -1671,7 +1674,8 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
                                         uint32_t log_size,
                                         bool use_zero_blocks,
                                         VHDXImageType type,
-                                        uint64_t *metadata_offset)
+                                        uint64_t *metadata_offset,
+                                        Error **errp)
 {
     int ret = 0;
     uint32_t offset = 0;
@@ -1740,7 +1744,7 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
     /* The region table gives us the data we need to create the BAT,
      * so do that now */
     ret = vhdx_create_bat(blk, s, image_size, type, use_zero_blocks,
-                          bat_file_offset, bat_length);
+                          bat_file_offset, bat_length, errp);
     if (ret < 0) {
         goto exit;
     }
@@ -1749,12 +1753,14 @@ static int vhdx_create_new_region_table(BlockBackend *blk,
     ret = blk_pwrite(blk, VHDX_REGION_TABLE_OFFSET, buffer,
                      VHDX_HEADER_BLOCK_SIZE, 0);
     if (ret < 0) {
+        error_setg_errno(errp, -ret, "Failed to write first region table");
         goto exit;
     }
 
     ret = blk_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, buffer,
                      VHDX_HEADER_BLOCK_SIZE, 0);
     if (ret < 0) {
+        error_setg_errno(errp, -ret, "Failed to write second region table");
         goto exit;
     }
 
@@ -1825,6 +1831,7 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
         ret = -ENOTSUP;
         goto exit;
     } else {
+        error_setg(errp, "Invalid subformat '%s'", type);
         ret = -EINVAL;
         goto exit;
     }
@@ -1879,12 +1886,14 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
     ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature),
                      0);
     if (ret < 0) {
+        error_setg_errno(errp, -ret, "Failed to write file signature");
         goto delete_and_exit;
     }
     if (creator) {
         ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
                          creator, creator_items * sizeof(gunichar2), 0);
         if (ret < 0) {
+            error_setg_errno(errp, -ret, "Failed to write creator field");
             goto delete_and_exit;
         }
     }
@@ -1893,13 +1902,14 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
     /* Creates (B),(C) */
     ret = vhdx_create_new_headers(blk, image_size, log_size);
     if (ret < 0) {
+        error_setg_errno(errp, -ret, "Failed to write image headers");
         goto delete_and_exit;
     }
 
     /* Creates (D),(E),(G) explicitly. (F) created as by-product */
     ret = vhdx_create_new_region_table(blk, image_size, block_size, 512,
                                        log_size, use_zero_blocks, image_type,
-                                       &metadata_offset);
+                                       &metadata_offset, errp);
     if (ret < 0) {
         goto delete_and_exit;
     }
@@ -1908,6 +1918,7 @@ static int vhdx_create(const char *filename, QemuOpts *opts, Error **errp)
     ret = vhdx_create_new_metadata(blk, image_size, block_size, 512,
                                    metadata_offset, image_type);
     if (ret < 0) {
+        error_setg_errno(errp, -ret, "Failed to initialize metadata");
         goto delete_and_exit;
     }
 
index a9bd22bf9353b23000505cc54bea1d19af27f29e..c61b9cc8e061e9f711d59984848b3aca9ba49d04 100644 (file)
@@ -1714,10 +1714,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
     blk_set_allow_write_beyond_eof(blk, true);
 
     if (flat) {
-        ret = blk_truncate(blk, filesize);
-        if (ret < 0) {
-            error_setg_errno(errp, -ret, "Could not truncate file");
-        }
+        ret = blk_truncate(blk, filesize, errp);
         goto exit;
     }
     magic = cpu_to_be32(VMDK4_MAGIC);
@@ -1780,9 +1777,8 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
         goto exit;
     }
 
-    ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9);
+    ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, errp);
     if (ret < 0) {
-        error_setg_errno(errp, -ret, "Could not truncate file");
         goto exit;
     }
 
@@ -2090,10 +2086,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
     /* bdrv_pwrite write padding zeros to align to sector, we don't need that
      * for description file */
     if (desc_offset == 0) {
-        ret = blk_truncate(new_blk, desc_len);
-        if (ret < 0) {
-            error_setg_errno(errp, -ret, "Could not truncate file");
-        }
+        ret = blk_truncate(new_blk, desc_len, errp);
     }
 exit:
     if (new_blk) {
index f591d4be38d648e6fbe1c2de057073a86542589a..ecfee77149738ce7d8b8fb96e34c0cee20795feb 100644 (file)
@@ -851,20 +851,21 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf,
 }
 
 static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
-                             int64_t total_size)
+                             int64_t total_size, Error **errp)
 {
     int ret;
 
     /* Add footer to total size */
     total_size += HEADER_SIZE;
 
-    ret = blk_truncate(blk, total_size);
+    ret = blk_truncate(blk, total_size, errp);
     if (ret < 0) {
         return ret;
     }
 
     ret = blk_pwrite(blk, total_size - HEADER_SIZE, buf, HEADER_SIZE, 0);
     if (ret < 0) {
+        error_setg_errno(errp, -ret, "Unable to write VHD header");
         return ret;
     }
 
@@ -996,11 +997,11 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
 
     if (disk_type == VHD_DYNAMIC) {
         ret = create_dynamic_disk(blk, buf, total_sectors);
+        if (ret < 0) {
+            error_setg(errp, "Unable to create or write VHD header");
+        }
     } else {
-        ret = create_fixed_disk(blk, buf, total_size);
-    }
-    if (ret < 0) {
-        error_setg(errp, "Unable to create or write VHD header");
+        ret = create_fixed_disk(blk, buf, total_size, errp);
     }
 
 out:
index 64282065d8f7ff1173e080b9a143ff937826458a..4d8cdedd54a0df11a26549caa19aabb130d4cb4e 100644 (file)
@@ -2930,26 +2930,7 @@ void qmp_block_resize(bool has_device, const char *device,
     /* complete all in-flight operations before resizing the device */
     bdrv_drain_all();
 
-    ret = blk_truncate(blk, size);
-    switch (ret) {
-    case 0:
-        break;
-    case -ENOMEDIUM:
-        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
-        break;
-    case -ENOTSUP:
-        error_setg(errp, QERR_UNSUPPORTED);
-        break;
-    case -EACCES:
-        error_setg(errp, "Device '%s' is read only", device);
-        break;
-    case -EBUSY:
-        error_setg(errp, QERR_DEVICE_IN_USE, device);
-        break;
-    default:
-        error_setg_errno(errp, -ret, "Could not resize");
-        break;
-    }
+    ret = blk_truncate(blk, size, errp);
 
 out:
     blk_unref(blk);
index 0118252002779737b8aa5e02a21cdf48285849cf..9d5f062c624df4123edcf208e9149add3de0376b 100644 (file)
@@ -55,6 +55,7 @@ typedef struct {
     SocketAddress *addr;
     bool is_listen;
     bool is_telnet;
+    bool is_tn3270;
 
     guint reconnect_timer;
     int64_t reconnect_time;
@@ -141,19 +142,25 @@ static int tcp_chr_read_poll(void *opaque)
     return s->max_size;
 }
 
-#define IAC 255
-#define IAC_BREAK 243
 static void tcp_chr_process_IAC_bytes(Chardev *chr,
                                       SocketChardev *s,
                                       uint8_t *buf, int *size)
 {
-    /* Handle any telnet client's basic IAC options to satisfy char by
-     * char mode with no echo.  All IAC options will be removed from
-     * the buf and the do_telnetopt variable will be used to track the
-     * state of the width of the IAC information.
+    /* Handle any telnet or tn3270 client's basic IAC options.
+     * For telnet options, it satisfies char by char mode with no echo.
+     * For tn3270 options, it satisfies binary mode with EOR.
+     * All IAC options will be removed from the buf and the do_opt
+     * pointer will be used to track the state of the width of the
+     * IAC information.
      *
-     * IAC commands come in sets of 3 bytes with the exception of the
-     * "IAC BREAK" command and the double IAC.
+     * RFC854: "All TELNET commands consist of at least a two byte sequence.
+     * The commands dealing with option negotiation are three byte sequences,
+     * the third byte being the code for the option referenced."
+     * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes.
+     * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data boundary
+     * for tn3270.
+     * NOP, Break and Interrupt Process(IP) might be encountered during a TN3270
+     * session, and NOP and IP need to be done later.
      */
 
     int i;
@@ -174,6 +181,18 @@ static void tcp_chr_process_IAC_bytes(Chardev *chr,
                     /* Handle IAC break commands by sending a serial break */
                     qemu_chr_be_event(chr, CHR_EVENT_BREAK);
                     s->do_telnetopt++;
+                } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_EOR
+                           || (unsigned char)buf[i] == IAC_SB
+                           || (unsigned char)buf[i] == IAC_SE)
+                           && s->do_telnetopt == 2) {
+                    buf[j++] = IAC;
+                    buf[j++] = buf[i];
+                    s->do_telnetopt++;
+                } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_IP
+                           || (unsigned char)buf[i] == IAC_NOP)
+                           && s->do_telnetopt == 2) {
+                    /* TODO: IP and NOP need to be implemented later. */
+                    s->do_telnetopt++;
                 }
                 s->do_telnetopt++;
             }
@@ -520,7 +539,7 @@ static void tcp_chr_update_read_handler(Chardev *chr,
 
 typedef struct {
     Chardev *chr;
-    char buf[12];
+    char buf[21];
     size_t buflen;
 } TCPChardevTelnetInit;
 
@@ -558,9 +577,6 @@ static void tcp_chr_telnet_init(Chardev *chr)
     TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
     size_t n = 0;
 
-    init->chr = chr;
-    init->buflen = 12;
-
 #define IACSET(x, a, b, c)                      \
     do {                                        \
         x[n++] = a;                             \
@@ -568,12 +584,26 @@ static void tcp_chr_telnet_init(Chardev *chr)
         x[n++] = c;                             \
     } while (0)
 
-    /* Prep the telnet negotion to put telnet in binary,
-     * no echo, single char mode */
-    IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
-    IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
-    IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
-    IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
+    init->chr = chr;
+    if (!s->is_tn3270) {
+        init->buflen = 12;
+        /* Prep the telnet negotion to put telnet in binary,
+         * no echo, single char mode */
+        IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
+        IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
+        IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
+        IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
+    } else {
+        init->buflen = 21;
+        /* Prep the TN3270 negotion based on RFC1576 */
+        IACSET(init->buf, 0xff, 0xfd, 0x19);  /* IAC DO EOR */
+        IACSET(init->buf, 0xff, 0xfb, 0x19);  /* IAC WILL EOR */
+        IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO BINARY */
+        IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL BINARY */
+        IACSET(init->buf, 0xff, 0xfd, 0x18);  /* IAC DO TERMINAL TYPE */
+        IACSET(init->buf, 0xff, 0xfa, 0x18);  /* IAC SB TERMINAL TYPE */
+        IACSET(init->buf, 0x01, 0xff, 0xf0);  /* SEND IAC SE */
+    }
 
 #undef IACSET
 
@@ -593,7 +623,8 @@ static void tcp_chr_tls_handshake(QIOTask *task,
     if (qio_task_propagate_error(task, NULL)) {
         tcp_chr_disconnect(chr);
     } else {
-        if (s->do_telnetopt) {
+        /* tn3270 does not support TLS yet */
+        if (s->do_telnetopt && !s->is_tn3270) {
             tcp_chr_telnet_init(chr);
         } else {
             tcp_chr_connect(chr);
@@ -832,12 +863,14 @@ static void qmp_chardev_open_socket(Chardev *chr,
     bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
     bool is_listen      = sock->has_server  ? sock->server  : true;
     bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
+    bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
     bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
     int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
     QIOChannelSocket *sioc = NULL;
 
     s->is_listen = is_listen;
     s->is_telnet = is_telnet;
+    s->is_tn3270 = is_tn3270;
     s->do_nodelay = do_nodelay;
     if (sock->tls_creds) {
         Object *creds;
@@ -886,7 +919,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
     update_disconnected_filename(s);
 
     if (is_listen) {
-        if (is_telnet) {
+        if (is_telnet || is_tn3270) {
             s->do_telnetopt = 1;
         }
     } else if (reconnect > 0) {
@@ -945,6 +978,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
     bool is_listen      = qemu_opt_get_bool(opts, "server", false);
     bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
     bool is_telnet      = qemu_opt_get_bool(opts, "telnet", false);
+    bool is_tn3270      = qemu_opt_get_bool(opts, "tn3270", false);
     bool do_nodelay     = !qemu_opt_get_bool(opts, "delay", true);
     int64_t reconnect   = qemu_opt_get_number(opts, "reconnect", 0);
     const char *path = qemu_opt_get(opts, "path");
@@ -980,6 +1014,8 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
     sock->server = is_listen;
     sock->has_telnet = true;
     sock->telnet = is_telnet;
+    sock->has_tn3270 = true;
+    sock->tn3270 = is_tn3270;
     sock->has_wait = true;
     sock->wait = is_waitconnect;
     sock->has_reconnect = true;
index 33dbab6981d7ce3077eaaa0cd4eecbfaf4fdf168..fadfedb8361d50c86e187d86a21b5425ca9519c5 100644 (file)
@@ -690,7 +690,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
         return opts;
     }
     if (strstart(filename, "tcp:", &p) ||
-        strstart(filename, "telnet:", &p)) {
+        strstart(filename, "telnet:", &p) ||
+        strstart(filename, "tn3270:", &p)) {
         if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
             host[0] = 0;
             if (sscanf(p, ":%32[^,]%n", port, &pos) < 1)
@@ -706,8 +707,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
                 goto fail;
             }
         }
-        if (strstart(filename, "telnet:", &p))
+        if (strstart(filename, "telnet:", &p)) {
             qemu_opt_set(opts, "telnet", "on", &error_abort);
+        } else if (strstart(filename, "tn3270:", &p)) {
+            qemu_opt_set(opts, "tn3270", "on", &error_abort);
+        }
         return opts;
     }
     if (strstart(filename, "udp:", &p)) {
@@ -1148,6 +1152,9 @@ QemuOptsList qemu_chardev_opts = {
         },{
             .name = "telnet",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "tn3270",
+            .type = QEMU_OPT_BOOL,
         },{
             .name = "tls-creds",
             .type = QEMU_OPT_STRING,
index 36e15de336ee7c865bc9796c5b2d8703b0ad9f2b..9615a48f8072152ea90c654c21037d509346f6a8 100644 (file)
@@ -2,6 +2,7 @@ CONFIG_PCI=y
 CONFIG_VIRTIO_PCI=y
 CONFIG_VIRTIO=y
 CONFIG_SCLPCONSOLE=y
+CONFIG_TERMINAL3270=y
 CONFIG_S390_FLIC=y
 CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
 CONFIG_WDT_DIAG288=y
diff --git a/hmp.c b/hmp.c
index ab407d6fd0139e10f9351ee451ea88fea23d4dbe..bd7b1caf2b091b2b2956eb1d4d81e2e32adfda02 100644 (file)
--- a/hmp.c
+++ b/hmp.c
@@ -19,6 +19,7 @@
 #include "net/eth.h"
 #include "sysemu/char.h"
 #include "sysemu/block-backend.h"
+#include "sysemu/sysemu.h"
 #include "qemu/config-file.h"
 #include "qemu/option.h"
 #include "qemu/timer.h"
@@ -1268,6 +1269,179 @@ void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict)
     hmp_handle_error(mon, &err);
 }
 
+void hmp_loadvm(Monitor *mon, const QDict *qdict)
+{
+    int saved_vm_running  = runstate_is_running();
+    const char *name = qdict_get_str(qdict, "name");
+
+    vm_stop(RUN_STATE_RESTORE_VM);
+
+    if (load_vmstate(name) == 0 && saved_vm_running) {
+        vm_start();
+    }
+}
+
+void hmp_savevm(Monitor *mon, const QDict *qdict)
+{
+    save_vmstate(qdict_get_try_str(qdict, "name"));
+}
+
+void hmp_delvm(Monitor *mon, const QDict *qdict)
+{
+    BlockDriverState *bs;
+    Error *err;
+    const char *name = qdict_get_str(qdict, "name");
+
+    if (bdrv_all_delete_snapshot(name, &bs, &err) < 0) {
+        error_reportf_err(err,
+                          "Error while deleting snapshot on device '%s': ",
+                          bdrv_get_device_name(bs));
+    }
+}
+
+void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
+{
+    BlockDriverState *bs, *bs1;
+    BdrvNextIterator it1;
+    QEMUSnapshotInfo *sn_tab, *sn;
+    bool no_snapshot = true;
+    int nb_sns, i;
+    int total;
+    int *global_snapshots;
+    AioContext *aio_context;
+
+    typedef struct SnapshotEntry {
+        QEMUSnapshotInfo sn;
+        QTAILQ_ENTRY(SnapshotEntry) next;
+    } SnapshotEntry;
+
+    typedef struct ImageEntry {
+        const char *imagename;
+        QTAILQ_ENTRY(ImageEntry) next;
+        QTAILQ_HEAD(, SnapshotEntry) snapshots;
+    } ImageEntry;
+
+    QTAILQ_HEAD(, ImageEntry) image_list =
+        QTAILQ_HEAD_INITIALIZER(image_list);
+
+    ImageEntry *image_entry, *next_ie;
+    SnapshotEntry *snapshot_entry;
+
+    bs = bdrv_all_find_vmstate_bs();
+    if (!bs) {
+        monitor_printf(mon, "No available block device supports snapshots\n");
+        return;
+    }
+    aio_context = bdrv_get_aio_context(bs);
+
+    aio_context_acquire(aio_context);
+    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
+    aio_context_release(aio_context);
+
+    if (nb_sns < 0) {
+        monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
+        return;
+    }
+
+    for (bs1 = bdrv_first(&it1); bs1; bs1 = bdrv_next(&it1)) {
+        int bs1_nb_sns = 0;
+        ImageEntry *ie;
+        SnapshotEntry *se;
+        AioContext *ctx = bdrv_get_aio_context(bs1);
+
+        aio_context_acquire(ctx);
+        if (bdrv_can_snapshot(bs1)) {
+            sn = NULL;
+            bs1_nb_sns = bdrv_snapshot_list(bs1, &sn);
+            if (bs1_nb_sns > 0) {
+                no_snapshot = false;
+                ie = g_new0(ImageEntry, 1);
+                ie->imagename = bdrv_get_device_name(bs1);
+                QTAILQ_INIT(&ie->snapshots);
+                QTAILQ_INSERT_TAIL(&image_list, ie, next);
+                for (i = 0; i < bs1_nb_sns; i++) {
+                    se = g_new0(SnapshotEntry, 1);
+                    se->sn = sn[i];
+                    QTAILQ_INSERT_TAIL(&ie->snapshots, se, next);
+                }
+            }
+            g_free(sn);
+        }
+        aio_context_release(ctx);
+    }
+
+    if (no_snapshot) {
+        monitor_printf(mon, "There is no snapshot available.\n");
+        return;
+    }
+
+    global_snapshots = g_new0(int, nb_sns);
+    total = 0;
+    for (i = 0; i < nb_sns; i++) {
+        SnapshotEntry *next_sn;
+        if (bdrv_all_find_snapshot(sn_tab[i].name, &bs1) == 0) {
+            global_snapshots[total] = i;
+            total++;
+            QTAILQ_FOREACH(image_entry, &image_list, next) {
+                QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots,
+                                    next, next_sn) {
+                    if (!strcmp(sn_tab[i].name, snapshot_entry->sn.name)) {
+                        QTAILQ_REMOVE(&image_entry->snapshots, snapshot_entry,
+                                      next);
+                        g_free(snapshot_entry);
+                    }
+                }
+            }
+        }
+    }
+
+    monitor_printf(mon, "List of snapshots present on all disks:\n");
+
+    if (total > 0) {
+        bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, NULL);
+        monitor_printf(mon, "\n");
+        for (i = 0; i < total; i++) {
+            sn = &sn_tab[global_snapshots[i]];
+            /* The ID is not guaranteed to be the same on all images, so
+             * overwrite it.
+             */
+            pstrcpy(sn->id_str, sizeof(sn->id_str), "--");
+            bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, sn);
+            monitor_printf(mon, "\n");
+        }
+    } else {
+        monitor_printf(mon, "None\n");
+    }
+
+    QTAILQ_FOREACH(image_entry, &image_list, next) {
+        if (QTAILQ_EMPTY(&image_entry->snapshots)) {
+            continue;
+        }
+        monitor_printf(mon,
+                       "\nList of partial (non-loadable) snapshots on '%s':\n",
+                       image_entry->imagename);
+        bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, NULL);
+        monitor_printf(mon, "\n");
+        QTAILQ_FOREACH(snapshot_entry, &image_entry->snapshots, next) {
+            bdrv_snapshot_dump((fprintf_function)monitor_printf, mon,
+                               &snapshot_entry->sn);
+            monitor_printf(mon, "\n");
+        }
+    }
+
+    QTAILQ_FOREACH_SAFE(image_entry, &image_list, next, next_ie) {
+        SnapshotEntry *next_sn;
+        QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, next,
+                            next_sn) {
+            g_free(snapshot_entry);
+        }
+        g_free(image_entry);
+    }
+    g_free(sn_tab);
+    g_free(global_snapshots);
+
+}
+
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
 {
     qmp_migrate_cancel(NULL);
diff --git a/hmp.h b/hmp.h
index 799fd371fac7bd1cf3e368df5ba141402c346aba..37bb65a8507b0a9da4885388ead5613aab947535 100644 (file)
--- a/hmp.h
+++ b/hmp.h
@@ -63,6 +63,10 @@ void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict);
 void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict);
 void hmp_drive_mirror(Monitor *mon, const QDict *qdict);
 void hmp_drive_backup(Monitor *mon, const QDict *qdict);
+void hmp_loadvm(Monitor *mon, const QDict *qdict);
+void hmp_savevm(Monitor *mon, const QDict *qdict);
+void hmp_delvm(Monitor *mon, const QDict *qdict);
+void hmp_info_snapshots(Monitor *mon, const QDict *qdict);
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate_incoming(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
index 7ce85a2e881905e4b5a74d909cb8530e4fcc632d..bb6f07a91e11ecc256ba7a007a2bc4c876507f8f 100644 (file)
@@ -14,5 +14,3 @@ common-obj-$(CONFIG_PL041) += pl041.o lm4549.o
 common-obj-$(CONFIG_CS4231) += cs4231.o
 common-obj-$(CONFIG_MARVELL_88W8618) += marvell_88w8618.o
 common-obj-$(CONFIG_MILKYMIST) += milkymist-ac97.o
-
-$(obj)/adlib.o $(obj)/fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
index 7836446fc80f5996d35dfdf6a9f09b6d97563461..09b8248cdac0ffc7f69217b6c058b5a9470ce98c 100644 (file)
 
 #define ADLIB_KILL_TIMERS 1
 
-#ifdef HAS_YMF262
-#define ADLIB_DESC "Yamaha YMF262 (OPL3)"
-#else
 #define ADLIB_DESC "Yamaha YM3812 (OPL2)"
-#endif
 
 #ifdef DEBUG
 #include "qemu/timer.h"
 #define ldebug(...)
 #endif
 
-#ifdef HAS_YMF262
-#include "ymf262.h"
-void YMF262UpdateOneQEMU (int which, INT16 *dst, int length);
-#define SHIFT 2
-#else
 #include "fmopl.h"
 #define SHIFT 1
-#endif
 
 #define TYPE_ADLIB "adlib"
 #define ADLIB(obj) OBJECT_CHECK(AdlibState, (obj), TYPE_ADLIB)
@@ -80,9 +70,7 @@ typedef struct {
     SWVoiceOut *voice;
     int left, pos, samples;
     QEMUAudioTimeStamp ats;
-#ifndef HAS_YMF262
     FM_OPL *opl;
-#endif
     PortioList port_list;
 } AdlibState;
 
@@ -90,11 +78,7 @@ static AdlibState *glob_adlib;
 
 static void adlib_stop_opl_timer (AdlibState *s, size_t n)
 {
-#ifdef HAS_YMF262
-    YMF262TimerOver (0, n);
-#else
     OPLTimerOver (s->opl, n);
-#endif
     s->ticking[n] = 0;
 }
 
@@ -131,11 +115,7 @@ static void adlib_write(void *opaque, uint32_t nport, uint32_t val)
 
     adlib_kill_timers (s);
 
-#ifdef HAS_YMF262
-    YMF262Write (0, a, val);
-#else
     OPLWrite (s->opl, a, val);
-#endif
 }
 
 static uint32_t adlib_read(void *opaque, uint32_t nport)
@@ -145,12 +125,8 @@ static uint32_t adlib_read(void *opaque, uint32_t nport)
     int a = nport & 3;
 
     adlib_kill_timers (s);
-
-#ifdef HAS_YMF262
-    data = YMF262Read (0, a);
-#else
     data = OPLRead (s->opl, a);
-#endif
+
     return data;
 }
 
@@ -240,11 +216,7 @@ static void adlib_callback (void *opaque, int free)
         return;
     }
 
-#ifdef HAS_YMF262
-    YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples);
-#else
     YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples);
-#endif
 
     while (samples) {
         written = write_audio (s, samples);
@@ -263,14 +235,10 @@ static void adlib_callback (void *opaque, int free)
 
 static void Adlib_fini (AdlibState *s)
 {
-#ifdef HAS_YMF262
-    YMF262Shutdown ();
-#else
     if (s->opl) {
         OPLDestroy (s->opl);
         s->opl = NULL;
     }
-#endif
 
     g_free(s->mixbuf);
 
@@ -297,17 +265,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
     }
     glob_adlib = s;
 
-#ifdef HAS_YMF262
-    if (YMF262Init (1, 14318180, s->freq)) {
-        error_setg (errp, "YMF262Init %d failed", s->freq);
-        return;
-    }
-    else {
-        YMF262SetTimerHandler (0, timer_handler, 0);
-        s->enabled = 1;
-    }
-#else
-    s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, s->freq);
+    s->opl = OPLCreate (3579545, s->freq);
     if (!s->opl) {
         error_setg (errp, "OPLCreate %d failed", s->freq);
         return;
@@ -316,7 +274,6 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
         OPLSetTimerHandler (s->opl, timer_handler, 0);
         s->enabled = 1;
     }
-#endif
 
     as.freq = s->freq;
     as.nchannels = SHIFT;
index 731110fe86ab1a167115d175332fb8eedddcd6fd..202f752c5d9b6ee764cdefd494e7c7448f3e7f6a 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#define HAS_YM3812     1
-
 #include "qemu/osdep.h"
 #include <math.h>
 //#include "driver.h"          /* use M.A.M.E. */
 #include "fmopl.h"
-
+#include "qemu/osdep.h"
 #ifndef PI
 #define PI 3.14159265358979323846
 #endif
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#endif
-
 /* -------------------- for debug --------------------- */
 /* #define OPL_OUTPUT_LOG */
 #ifdef OPL_OUTPUT_LOG
@@ -124,7 +118,7 @@ static const int slot_array[32]=
 /* key scale level */
 /* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
 #define DV (EG_STEP/2)
-static const UINT32 KSL_TABLE[8*16]=
+static const uint32_t KSL_TABLE[8*16]=
 {
        /* OCT 0 */
         0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
@@ -172,7 +166,7 @@ static const UINT32 KSL_TABLE[8*16]=
 /* sustain lebel table (3db per step) */
 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
 #define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
-static const INT32 SL_TABLE[16]={
+static const int32_t SL_TABLE[16]={
  SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
  SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
 };
@@ -182,22 +176,22 @@ static const INT32 SL_TABLE[16]={
 /* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
 /* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
 /* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
-static INT32 *TL_TABLE;
+static int32_t *TL_TABLE;
 
 /* pointers to TL_TABLE with sinwave output offset */
-static INT32 **SIN_TABLE;
+static int32_t **SIN_TABLE;
 
 /* LFO table */
-static INT32 *AMS_TABLE;
-static INT32 *VIB_TABLE;
+static int32_t *AMS_TABLE;
+static int32_t *VIB_TABLE;
 
 /* envelope output curve table */
 /* attack + decay + OFF */
-static INT32 ENV_CURVE[2*EG_ENT+1];
+static int32_t ENV_CURVE[2*EG_ENT+1];
 
 /* multiple table */
 #define ML 2
-static const UINT32 MUL_TABLE[16]= {
+static const uint32_t MUL_TABLE[16]= {
 /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
    0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
    8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
@@ -205,7 +199,7 @@ static const UINT32 MUL_TABLE[16]= {
 #undef ML
 
 /* dummy attack / decay rate ( when rate == 0 ) */
-static INT32 RATE_0[16]=
+static int32_t RATE_0[16]=
 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 
 /* -------------------- static state --------------------- */
@@ -221,14 +215,14 @@ static OPL_CH *S_CH;
 static OPL_CH *E_CH;
 static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
 
-static INT32 outd[1];
-static INT32 ams;
-static INT32 vib;
-static INT32 *ams_table;
-static INT32 *vib_table;
-static INT32 amsIncr;
-static INT32 vibIncr;
-static INT32 feedback2;                /* connect for SLOT 2 */
+static int32_t outd[1];
+static int32_t ams;
+static int32_t vib;
+static int32_t *ams_table;
+static int32_t *vib_table;
+static int32_t amsIncr;
+static int32_t vibIncr;
+static int32_t feedback2;              /* connect for SLOT 2 */
 
 /* log output level */
 #define LOG_ERR  3      /* ERROR       */
@@ -262,8 +256,6 @@ static inline void OPL_STATUS_SET(FM_OPL *OPL,int flag)
                if(OPL->status & OPL->statusmask)
                {       /* IRQ on */
                        OPL->status |= 0x80;
-                       /* callback user interrupt handler (IRQ is OFF to ON) */
-                       if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
                }
        }
 }
@@ -278,8 +270,6 @@ static inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
                if (!(OPL->status & OPL->statusmask) )
                {
                        OPL->status &= 0x7f;
-                       /* callback user interrupt handler (IRQ is ON to OFF) */
-                       if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
                }
        }
 }
@@ -321,7 +311,7 @@ static inline void OPL_KEYOFF(OPL_SLOT *SLOT)
 
 /* ---------- calcrate Envelope Generator & Phase Generator ---------- */
 /* return : envelope output */
-static inline UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
+static inline uint32_t OPL_CALC_SLOT( OPL_SLOT *SLOT )
 {
        /* calcrate envelope generator */
        if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
@@ -361,7 +351,7 @@ static inline UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
 /* set algorithm connection */
 static void set_algorithm( OPL_CH *CH)
 {
-       INT32 *carrier = &outd[0];
+       int32_t *carrier = &outd[0];
        CH->connect1 = CH->CON ? carrier : &feedback2;
        CH->connect2 = carrier;
 }
@@ -453,7 +443,7 @@ static inline void set_sl_rr(FM_OPL *OPL,int slot,int v)
 /* ---------- calcrate one of channel ---------- */
 static inline void OPL_CALC_CH( OPL_CH *CH )
 {
-       UINT32 env_out;
+       uint32_t env_out;
        OPL_SLOT *SLOT;
 
        feedback2 = 0;
@@ -498,9 +488,9 @@ static inline void OPL_CALC_CH( OPL_CH *CH )
 #define WHITE_NOISE_db 6.0
 static inline void OPL_CALC_RH( OPL_CH *CH )
 {
-       UINT32 env_tam,env_sd,env_top,env_hh;
+       uint32_t env_tam,env_sd,env_top,env_hh;
        int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
-       INT32 tone8;
+       int32_t tone8;
 
        OPL_SLOT *SLOT;
        int env_out;
@@ -618,20 +608,20 @@ static int OPLOpenTable( void )
        double pom;
 
        /* allocate dynamic tables */
-       if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
+       if( (TL_TABLE = malloc(TL_MAX*2*sizeof(int32_t))) == NULL)
                return 0;
-       if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
+       if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(int32_t *))) == NULL)
        {
                free(TL_TABLE);
                return 0;
        }
-       if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
+       if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(int32_t))) == NULL)
        {
                free(TL_TABLE);
                free(SIN_TABLE);
                return 0;
        }
-       if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
+       if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(int32_t))) == NULL)
        {
                free(TL_TABLE);
                free(SIN_TABLE);
@@ -763,18 +753,15 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
                {
                case 0x01:
                        /* wave selector enable */
-                       if(OPL->type&OPL_TYPE_WAVESEL)
+                       OPL->wavesel = v&0x20;
+                        if(!OPL->wavesel)
                        {
-                               OPL->wavesel = v&0x20;
-                               if(!OPL->wavesel)
+                               /* preset compatible mode */
+                               int c;
+                               for(c=0;c<OPL->max_ch;c++)
                                {
-                                       /* preset compatible mode */
-                                       int c;
-                                       for(c=0;c<OPL->max_ch;c++)
-                                       {
-                                               OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
-                                               OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
-                                       }
+                                       OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
+                                       OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
                                }
                        }
                        return;
@@ -791,8 +778,8 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
                        }
                        else
                        {       /* set IRQ mask ,timer enable*/
-                               UINT8 st1 = v&1;
-                               UINT8 st2 = (v>>1)&1;
+                               uint8_t st1 = v&1;
+                               uint8_t st2 = (v>>1)&1;
                                /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
                                OPL_STATUS_RESET(OPL,v&0x78);
                                OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
@@ -812,57 +799,6 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
                                }
                        }
                        return;
-#if BUILD_Y8950
-               case 0x06:              /* Key Board OUT */
-                       if(OPL->type&OPL_TYPE_KEYBOARD)
-                       {
-                               if(OPL->keyboardhandler_w)
-                                       OPL->keyboardhandler_w(OPL->keyboard_param,v);
-                               else
-                                       LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));
-                       }
-                       return;
-               case 0x07:      /* DELTA-T control : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
-                       if(OPL->type&OPL_TYPE_ADPCM)
-                               YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
-                       return;
-               case 0x08:      /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
-                       OPL->mode = v;
-                       v&=0x1f;        /* for DELTA-T unit */
-               case 0x09:              /* START ADD */
-               case 0x0a:
-               case 0x0b:              /* STOP ADD  */
-               case 0x0c:
-               case 0x0d:              /* PRESCALE   */
-               case 0x0e:
-               case 0x0f:              /* ADPCM data */
-               case 0x10:              /* DELTA-N    */
-               case 0x11:              /* DELTA-N    */
-               case 0x12:              /* EG-CTRL    */
-                       if(OPL->type&OPL_TYPE_ADPCM)
-                               YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
-                       return;
-#if 0
-               case 0x15:              /* DAC data    */
-               case 0x16:
-               case 0x17:              /* SHIFT    */
-                       return;
-               case 0x18:              /* I/O CTRL (Direction) */
-                       if(OPL->type&OPL_TYPE_IO)
-                               OPL->portDirection = v&0x0f;
-                       return;
-               case 0x19:              /* I/O DATA */
-                       if(OPL->type&OPL_TYPE_IO)
-                       {
-                               OPL->portLatch = v;
-                               if(OPL->porthandler_w)
-                                       OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
-                       }
-                       return;
-               case 0x1a:              /* PCM data */
-                       return;
-#endif
-#endif
                }
                break;
        case 0x20:      /* am,vib,ksr,eg type,mul */
@@ -891,7 +827,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
                case 0xbd:
                        /* amsep,vibdep,r,bd,sd,tom,tc,hh */
                        {
-                       UINT8 rkey = OPL->rhythm^v;
+                       uint8_t rkey = OPL->rhythm^v;
                        OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
                        OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
                        OPL->rhythm  = v&0x3f;
@@ -1032,20 +968,19 @@ static void OPL_UnLockTable(void)
        OPLCloseTable();
 }
 
-#if (BUILD_YM3812 || BUILD_YM3526)
 /*******************************************************************************/
 /*             YM3812 local section                                                   */
 /*******************************************************************************/
 
 /* ---------- update one of chip ----------- */
-void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
+void YM3812UpdateOne(FM_OPL *OPL, int16_t *buffer, int length)
 {
     int i;
        int data;
-       OPLSAMPLE *buf = buffer;
-       UINT32 amsCnt  = OPL->amsCnt;
-       UINT32 vibCnt  = OPL->vibCnt;
-       UINT8 rhythm = OPL->rhythm&0x20;
+       int16_t *buf = buffer;
+       uint32_t amsCnt  = OPL->amsCnt;
+       uint32_t  vibCnt  = OPL->vibCnt;
+       uint8_t rhythm = OPL->rhythm&0x20;
        OPL_CH *CH,*R_CH;
 
        if( (void *)OPL != cur_chip ){
@@ -1095,72 +1030,9 @@ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
        }
 #endif
 }
-#endif /* (BUILD_YM3812 || BUILD_YM3526) */
-
-#if BUILD_Y8950
-
-void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
-{
-    int i;
-       int data;
-       OPLSAMPLE *buf = buffer;
-       UINT32 amsCnt  = OPL->amsCnt;
-       UINT32 vibCnt  = OPL->vibCnt;
-       UINT8 rhythm = OPL->rhythm&0x20;
-       OPL_CH *CH,*R_CH;
-       YM_DELTAT *DELTAT = OPL->deltat;
-
-       /* setup DELTA-T unit */
-       YM_DELTAT_DECODE_PRESET(DELTAT);
-
-       if( (void *)OPL != cur_chip ){
-               cur_chip = (void *)OPL;
-               /* channel pointers */
-               S_CH = OPL->P_CH;
-               E_CH = &S_CH[9];
-               /* rhythm slot */
-               SLOT7_1 = &S_CH[7].SLOT[SLOT1];
-               SLOT7_2 = &S_CH[7].SLOT[SLOT2];
-               SLOT8_1 = &S_CH[8].SLOT[SLOT1];
-               SLOT8_2 = &S_CH[8].SLOT[SLOT2];
-               /* LFO state */
-               amsIncr = OPL->amsIncr;
-               vibIncr = OPL->vibIncr;
-               ams_table = OPL->ams_table;
-               vib_table = OPL->vib_table;
-       }
-       R_CH = rhythm ? &S_CH[6] : E_CH;
-    for( i=0; i < length ; i++ )
-       {
-               /*            channel A         channel B         channel C      */
-               /* LFO */
-               ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
-               vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
-               outd[0] = 0;
-               /* deltaT ADPCM */
-               if( DELTAT->portstate )
-                       YM_DELTAT_ADPCM_CALC(DELTAT);
-               /* FM part */
-               for(CH=S_CH ; CH < R_CH ; CH++)
-                       OPL_CALC_CH(CH);
-               /* Rythn part */
-               if(rhythm)
-                       OPL_CALC_RH(S_CH);
-               /* limit check */
-               data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
-               /* store to sound buffer */
-               buf[i] = data >> OPL_OUTSB;
-       }
-       OPL->amsCnt = amsCnt;
-       OPL->vibCnt = vibCnt;
-       /* deltaT START flag */
-       if( !DELTAT->portstate )
-               OPL->status &= 0xfe;
-}
-#endif
 
 /* ---------- reset one of chip ---------- */
-void OPLResetChip(FM_OPL *OPL)
+static void OPLResetChip(FM_OPL *OPL)
 {
        int c,s;
        int i;
@@ -1189,23 +1061,11 @@ void OPLResetChip(FM_OPL *OPL)
                        CH->SLOT[s].evs = 0;
                }
        }
-#if BUILD_Y8950
-       if(OPL->type&OPL_TYPE_ADPCM)
-       {
-               YM_DELTAT *DELTAT = OPL->deltat;
-
-               DELTAT->freqbase = OPL->freqbase;
-               DELTAT->output_pointer = outd;
-               DELTAT->portshift = 5;
-               DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
-               YM_DELTAT_ADPCM_Reset(DELTAT,0);
-       }
-#endif
 }
 
 /* ----------  Create one of vietual YM3812 ----------       */
 /* 'rate'  is sampling rate and 'bufsiz' is the size of the  */
-FM_OPL *OPLCreate(int type, int clock, int rate)
+FM_OPL *OPLCreate(int clock, int rate)
 {
        char *ptr;
        FM_OPL *OPL;
@@ -1216,9 +1076,6 @@ FM_OPL *OPLCreate(int type, int clock, int rate)
        /* allocate OPL state space */
        state_size  = sizeof(FM_OPL);
        state_size += sizeof(OPL_CH)*max_ch;
-#if BUILD_Y8950
-       if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
-#endif
        /* allocate memory block */
        ptr = malloc(state_size);
        if(ptr==NULL) return NULL;
@@ -1226,11 +1083,7 @@ FM_OPL *OPLCreate(int type, int clock, int rate)
        memset(ptr,0,state_size);
        OPL        = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
        OPL->P_CH  = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
-#if BUILD_Y8950
-       if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
-#endif
        /* set channel state pointer */
-       OPL->type  = type;
        OPL->clock = clock;
        OPL->rate  = rate;
        OPL->max_ch = max_ch;
@@ -1280,31 +1133,7 @@ void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOff
        OPL->TimerHandler   = TimerHandler;
        OPL->TimerParam = channelOffset;
 }
-void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
-{
-       OPL->IRQHandler     = IRQHandler;
-       OPL->IRQParam = param;
-}
-void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
-{
-       OPL->UpdateHandler = UpdateHandler;
-       OPL->UpdateParam = param;
-}
-#if BUILD_Y8950
-void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
-{
-       OPL->porthandler_w = PortHandler_w;
-       OPL->porthandler_r = PortHandler_r;
-       OPL->port_param = param;
-}
 
-void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
-{
-       OPL->keyboardhandler_w = KeyboardHandler_w;
-       OPL->keyboardhandler_r = KeyboardHandler_r;
-       OPL->keyboard_param = param;
-}
-#endif
 /* ---------- YM3812 I/O interface ---------- */
 int OPLWrite(FM_OPL *OPL,int a,int v)
 {
@@ -1314,7 +1143,6 @@ int OPLWrite(FM_OPL *OPL,int a,int v)
        }
        else
        {       /* data port */
-               if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
 #ifdef OPL_OUTPUT_LOG
        if(opl_dbg_fp)
        {
@@ -1338,28 +1166,12 @@ unsigned char OPLRead(FM_OPL *OPL,int a)
        switch(OPL->address)
        {
        case 0x05: /* KeyBoard IN */
-               if(OPL->type&OPL_TYPE_KEYBOARD)
-               {
-                       if(OPL->keyboardhandler_r)
-                               return OPL->keyboardhandler_r(OPL->keyboard_param);
-                       else {
-                               LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n"));
-                       }
-               }
                return 0;
 #if 0
        case 0x0f: /* ADPCM-DATA  */
                return 0;
 #endif
        case 0x19: /* I/O DATA    */
-               if(OPL->type&OPL_TYPE_IO)
-               {
-                       if(OPL->porthandler_r)
-                               return OPL->porthandler_r(OPL->port_param);
-                       else {
-                               LOG(LOG_WAR,("OPL:read unmapped I/O port\n"));
-                       }
-               }
                return 0;
        case 0x1a: /* PCM-DATA    */
                return 0;
@@ -1380,7 +1192,6 @@ int OPLTimerOver(FM_OPL *OPL,int c)
                if( OPL->mode & 0x80 )
                {       /* CSM mode total level latch and auto key on */
                        int ch;
-                       if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
                        for(ch=0;ch<9;ch++)
                                CSMKeyControll( &OPL->P_CH[ch] );
                }
index fdda7f9f51afca3e7dd789c4933083b6480c55d6..fc9f16b58a638a154b64c6d8f8a21aeb6b83835a 100644 (file)
 #ifndef FMOPL_H
 #define FMOPL_H
 
-/* --- select emulation chips --- */
-#define BUILD_YM3812 (HAS_YM3812)
-//#define BUILD_YM3526 (HAS_YM3526)
-//#define BUILD_Y8950  (HAS_Y8950)
-
-/* --- system optimize --- */
-/* select bit size of output : 8 or 16 */
-#define OPL_OUTPUT_BIT 16
-
-/* compiler dependence */
-#ifndef OSD_CPU_H
-#define OSD_CPU_H
-typedef unsigned char  UINT8;   /* unsigned  8bit */
-typedef unsigned short UINT16;  /* unsigned 16bit */
-typedef unsigned int   UINT32;  /* unsigned 32bit */
-typedef signed char            INT8;    /* signed  8bit   */
-typedef signed short   INT16;   /* signed 16bit   */
-typedef signed int             INT32;   /* signed 32bit   */
-#endif
-
-#if (OPL_OUTPUT_BIT==16)
-typedef INT16 OPLSAMPLE;
-#endif
-#if (OPL_OUTPUT_BIT==8)
-typedef unsigned char  OPLSAMPLE;
-#endif
-
-
-#if BUILD_Y8950
-#include "ymdeltat.h"
-#endif
+#include <stdint.h>
 
 typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
-typedef void (*OPL_IRQHANDLER)(int param,int irq);
-typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
-typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
-typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
 
 /* !!!!! here is private section , do not access there member direct !!!!! */
 
-#define OPL_TYPE_WAVESEL   0x01  /* waveform select    */
-#define OPL_TYPE_ADPCM     0x02  /* DELTA-T ADPCM unit */
-#define OPL_TYPE_KEYBOARD  0x04  /* keyboard interface */
-#define OPL_TYPE_IO        0x08  /* I/O port */
-
 /* Saving is necessary for member of the 'R' mark for suspend/resume */
 /* ---------- OPL one of slot  ---------- */
 typedef struct fm_opl_slot {
-       INT32 TL;               /* total level     :TL << 8            */
-       INT32 TLL;              /* adjusted now TL                     */
-       UINT8  KSR;             /* key scale rate  :(shift down bit)   */
-       INT32 *AR;              /* attack rate     :&AR_TABLE[AR<<2]   */
-       INT32 *DR;              /* decay rate      :&DR_TALBE[DR<<2]   */
-       INT32 SL;               /* sustin level    :SL_TALBE[SL]       */
-       INT32 *RR;              /* release rate    :&DR_TABLE[RR<<2]   */
-       UINT8 ksl;              /* keyscale level  :(shift down bits)  */
-       UINT8 ksr;              /* key scale rate  :kcode>>KSR         */
-       UINT32 mul;             /* multiple        :ML_TABLE[ML]       */
-       UINT32 Cnt;             /* frequency count :                   */
-       UINT32 Incr;    /* frequency step  :                   */
+       int32_t TL;             /* total level     :TL << 8            */
+       int32_t TLL;            /* adjusted now TL                     */
+       uint8_t  KSR;           /* key scale rate  :(shift down bit)   */
+       int32_t *AR;            /* attack rate     :&AR_TABLE[AR<<2]   */
+       int32_t *DR;            /* decay rate      :&DR_TALBE[DR<<2]   */
+       int32_t SL;             /* sustin level    :SL_TALBE[SL]       */
+       int32_t *RR;            /* release rate    :&DR_TABLE[RR<<2]   */
+       uint8_t ksl;            /* keyscale level  :(shift down bits)  */
+       uint8_t ksr;            /* key scale rate  :kcode>>KSR         */
+       uint32_t mul;           /* multiple        :ML_TABLE[ML]       */
+       uint32_t Cnt;           /* frequency count :                   */
+       uint32_t Incr;  /* frequency step  :                   */
        /* envelope generator state */
-       UINT8 eg_typ;   /* envelope type flag                  */
-       UINT8 evm;              /* envelope phase                      */
-       INT32 evc;              /* envelope counter                    */
-       INT32 eve;              /* envelope counter end point          */
-       INT32 evs;              /* envelope counter step               */
-       INT32 evsa;     /* envelope step for AR :AR[ksr]           */
-       INT32 evsd;     /* envelope step for DR :DR[ksr]           */
-       INT32 evsr;     /* envelope step for RR :RR[ksr]           */
+       uint8_t eg_typ; /* envelope type flag                  */
+       uint8_t evm;            /* envelope phase                      */
+       int32_t evc;            /* envelope counter                    */
+       int32_t eve;            /* envelope counter end point          */
+       int32_t evs;            /* envelope counter step               */
+       int32_t evsa;   /* envelope step for AR :AR[ksr]           */
+       int32_t evsd;   /* envelope step for DR :DR[ksr]           */
+       int32_t evsr;   /* envelope step for RR :RR[ksr]           */
        /* LFO */
-       UINT8 ams;              /* ams flag                            */
-       UINT8 vib;              /* vibrate flag                        */
+       uint8_t ams;            /* ams flag                            */
+       uint8_t vib;            /* vibrate flag                        */
        /* wave selector */
-       INT32 **wavetable;
+       int32_t **wavetable;
 }OPL_SLOT;
 
 /* ---------- OPL one of channel  ---------- */
 typedef struct fm_opl_channel {
        OPL_SLOT SLOT[2];
-       UINT8 CON;                      /* connection type                     */
-       UINT8 FB;                       /* feed back       :(shift down bit)   */
-       INT32 *connect1;        /* slot1 output pointer                */
-       INT32 *connect2;        /* slot2 output pointer                */
-       INT32 op1_out[2];       /* slot1 output for selfeedback        */
+       uint8_t CON;                    /* connection type                     */
+       uint8_t FB;                     /* feed back       :(shift down bit)   */
+       int32_t *connect1;      /* slot1 output pointer                */
+       int32_t *connect2;      /* slot2 output pointer                */
+       int32_t op1_out[2];     /* slot1 output for selfeedback        */
        /* phase generator state */
-       UINT32  block_fnum;     /* block+fnum      :                   */
-       UINT8 kcode;            /* key code        : KeyScaleCode      */
-       UINT32  fc;                     /* Freq. Increment base                */
-       UINT32  ksl_base;       /* KeyScaleLevel Base step             */
-       UINT8 keyon;            /* key on/off flag                     */
+       uint32_t  block_fnum;   /* block+fnum      :                   */
+       uint8_t kcode;          /* key code        : KeyScaleCode      */
+       uint32_t  fc;                   /* Freq. Increment base                */
+       uint32_t  ksl_base;     /* KeyScaleLevel Base step             */
+       uint8_t keyon;          /* key on/off flag                     */
 } OPL_CH;
 
 /* OPL state */
 typedef struct fm_opl_f {
-       UINT8 type;                     /* chip type                         */
        int clock;                      /* master clock  (Hz)                */
        int rate;                       /* sampling rate (Hz)                */
        double freqbase;        /* frequency base                    */
        double TimerBase;       /* Timer base time (==sampling time) */
-       UINT8 address;          /* address register                  */
-       UINT8 status;           /* status flag                       */
-       UINT8 statusmask;       /* status mask                       */
-       UINT32 mode;            /* Reg.08 : CSM , notesel,etc.       */
+       uint8_t address;                /* address register                  */
+       uint8_t status;         /* status flag                       */
+       uint8_t statusmask;     /* status mask                       */
+       uint32_t mode;          /* Reg.08 : CSM , notesel,etc.       */
        /* Timer */
        int T[2];                       /* timer counter                     */
-       UINT8 st[2];            /* timer enable                      */
+       uint8_t st[2];          /* timer enable                      */
        /* FM channel slots */
        OPL_CH *P_CH;           /* pointer of CH                     */
        int     max_ch;                 /* maximum channel                   */
        /* Rhythm sention */
-       UINT8 rhythm;           /* Rhythm mode , key flag */
-#if BUILD_Y8950
-       /* Delta-T ADPCM unit (Y8950) */
-       YM_DELTAT *deltat;                      /* DELTA-T ADPCM       */
-#endif
-       /* Keyboard / I/O interface unit (Y8950) */
-       UINT8 portDirection;
-       UINT8 portLatch;
-       OPL_PORTHANDLER_R porthandler_r;
-       OPL_PORTHANDLER_W porthandler_w;
-       int port_param;
-       OPL_PORTHANDLER_R keyboardhandler_r;
-       OPL_PORTHANDLER_W keyboardhandler_w;
-       int keyboard_param;
+       uint8_t rhythm;         /* Rhythm mode , key flag */
        /* time tables */
-       INT32 AR_TABLE[75];     /* atttack rate tables */
-       INT32 DR_TABLE[75];     /* decay rate tables   */
-       UINT32 FN_TABLE[1024];  /* fnumber -> increment counter */
+       int32_t AR_TABLE[75];   /* atttack rate tables */
+       int32_t DR_TABLE[75];   /* decay rate tables   */
+       uint32_t FN_TABLE[1024];  /* fnumber -> increment counter */
        /* LFO */
-       INT32 *ams_table;
-       INT32 *vib_table;
-       INT32 amsCnt;
-       INT32 amsIncr;
-       INT32 vibCnt;
-       INT32 vibIncr;
+       int32_t *ams_table;
+       int32_t *vib_table;
+       int32_t amsCnt;
+       int32_t amsIncr;
+       int32_t vibCnt;
+       int32_t vibIncr;
        /* wave selector enable flag */
-       UINT8 wavesel;
+       uint8_t wavesel;
        /* external event callback handler */
        OPL_TIMERHANDLER  TimerHandler;         /* TIMER handler   */
        int TimerParam;                                         /* TIMER parameter */
-       OPL_IRQHANDLER    IRQHandler;           /* IRQ handler    */
-       int IRQParam;                                           /* IRQ parameter  */
-       OPL_UPDATEHANDLER UpdateHandler;        /* stream update handler   */
-       int UpdateParam;                                        /* stream update parameter */
 } FM_OPL;
 
 /* ---------- Generic interface section ---------- */
-#define OPL_TYPE_YM3526 (0)
-#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
-#define OPL_TYPE_Y8950  (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
-
-FM_OPL *OPLCreate(int type, int clock, int rate);
+FM_OPL *OPLCreate(int clock, int rate);
 void OPLDestroy(FM_OPL *OPL);
 void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
-void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
-void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
-/* Y8950 port handlers */
-void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
-void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
 
-void OPLResetChip(FM_OPL *OPL);
 int OPLWrite(FM_OPL *OPL,int a,int v);
 unsigned char OPLRead(FM_OPL *OPL,int a);
 int OPLTimerOver(FM_OPL *OPL,int c);
 
-/* YM3626/YM3812 local section */
-void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
-
-void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
-
+void YM3812UpdateOne(FM_OPL *OPL, int16_t *buffer, int length);
 #endif
index 3d08a6576a1023b12d97212445e091cc8d4a2efd..ec103a4db9501be3bf8cd078a822b437c0de3efc 100644 (file)
@@ -53,7 +53,7 @@ typedef struct GUSState {
     uint32_t freq;
     uint32_t port;
     int pos, left, shift, irqs;
-    GUSsample *mixbuf;
+    int16_t *mixbuf;
     uint8_t himem[1024 * 1024 + 32 + 4096];
     int samples;
     SWVoiceOut *voice;
index 9aec7bf8e76f78b43cf5ba132122cb98c04d6f19..ab591eefb790452d81fa92fa4d277f210f78630e 100644 (file)
 #ifndef GUSEMU_H
 #define GUSEMU_H
 
-/* data types (need to be adjusted if neither a VC6 nor a C99 compatible compiler is used) */
-
-#if defined _WIN32 && defined _MSC_VER /* doesn't support other win32 compilers yet, do it yourself... */
- typedef unsigned char GUSbyte;
- typedef unsigned short GUSword;
- typedef unsigned int GUSdword;
- typedef signed char GUSchar;
- typedef signed short GUSsample;
-#else
- typedef int8_t GUSchar;
- typedef uint8_t GUSbyte;
- typedef uint16_t GUSword;
- typedef uint32_t GUSdword;
- typedef int16_t GUSsample;
-#endif
-
 typedef struct _GUSEmuState
 {
GUSbyte *himemaddr; /* 1024*1024 bytes used for storing uploaded samples (+32 additional bytes for read padding) */
GUSbyte *gusdatapos; /* (gusdataend-gusdata) bytes used for storing emulated GF1/mixer register states (32*32+4 bytes in initial GUSemu32 version) */
uint8_t *himemaddr; /* 1024*1024 bytes used for storing uploaded samples (+32 additional bytes for read padding) */
uint8_t *gusdatapos; /* (gusdataend-gusdata) bytes used for storing emulated GF1/mixer register states (32*32+4 bytes in initial GUSemu32 version) */
  uint32_t gusirq;
  uint32_t gusdma;
  unsigned int timer1fraction;
@@ -92,7 +76,7 @@ void gus_dma_transferdata(GUSEmuState *state, char *dma_addr, unsigned int count
 /* If the interrupts are asynchronous, it may be needed to use a separate thread mixing into a temporary */
 /* audio buffer in order to avoid quality loss caused by large numsamples and elapsed_time values. */
 
-void gus_mixvoices(GUSEmuState *state, unsigned int playback_freq, unsigned int numsamples, GUSsample *bufferpos);
+void gus_mixvoices(GUSEmuState *state, unsigned int playback_freq, unsigned int numsamples, int16_t *bufferpos);
 /* recommended range: 10 < numsamples < 100 */
 /* lower values may result in increased rounding error, higher values often cause audible timing delays */
 
index 973d6b9f4f491586bd533c6919ccc4e8e8a3a782..1150fc4426989272d507b66c13f4a7f03f1c0e60 100644 (file)
 #include "gusemu.h"
 
 #define GUSregb(position) (*            (gusptr+(position)))
-#define GUSregw(position) (*(GUSword *) (gusptr+(position)))
-#define GUSregd(position) (*(GUSdword *)(gusptr+(position)))
+#define GUSregw(position) (*(uint16_t *) (gusptr+(position)))
+#define GUSregd(position) (*(uint16_t *)(gusptr+(position)))
 
 /* size given in bytes */
 unsigned int gus_read(GUSEmuState * state, int port, int size)
 {
     int             value_read = 0;
 
-    GUSbyte        *gusptr;
+    uint8_t        *gusptr;
     gusptr = state->gusdatapos;
     GUSregd(portaccesses)++;
 
@@ -125,7 +125,7 @@ unsigned int gus_read(GUSEmuState * state, int port, int size)
                 if (!GUSregb(IRQStatReg2x6))
                     GUS_irqclear(state, state->gusirq);
             }
-            return (GUSbyte) value_read;
+            return (uint8_t) value_read;
             /* DramDMAmemPosReg */
             /* case 0x42: value_read=GUSregw(GUS42DMAStart); break;*/
             /* 43h+44h write only */
@@ -173,12 +173,12 @@ unsigned int gus_read(GUSEmuState * state, int port, int size)
                 value_read = value_read >> 8;
             value_read &= 0xff;
         }
-        return (GUSword) value_read;
+        return (uint16_t) value_read;
     /* case 0x306:                                  */ /* Mixer/Version info */
         /*  return 0xff; */ /* Pre 3.6 boards, ICS mixer NOT present */
     case 0x307:                                     /* DRAMaccess */
         {
-            GUSbyte        *adr;
+            uint8_t        *adr;
             adr = state->himemaddr + (GUSregd(GUSDRAMPOS24bit) & 0xfffff);
             return *adr;
         }
@@ -189,14 +189,14 @@ unsigned int gus_read(GUSEmuState * state, int port, int size)
 
 void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
 {
-    GUSbyte        *gusptr;
+    uint8_t        *gusptr;
     gusptr = state->gusdatapos;
     GUSregd(portaccesses)++;
 
     switch (port & 0xff0f)
     {
     case 0x200:                 /* MixerCtrlReg */
-        GUSregb(MixerCtrlReg2x0) = (GUSbyte) data;
+        GUSregb(MixerCtrlReg2x0) = (uint8_t) data;
         break;
     case 0x206:                 /* IRQstatReg / SB2x6IRQ */
         if (GUSregb(GUS45TimerCtrl) & 0x20) /* SB IRQ enabled? -> set 2x6IRQ bit */
@@ -208,7 +208,7 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
         break;
     case 0x308:                /* AdLib 388h */
     case 0x208:                /* AdLibCommandReg */
-        GUSregb(AdLibCommand2xA) = (GUSbyte) data;
+        GUSregb(AdLibCommand2xA) = (uint8_t) data;
         break;
     case 0x309:                /* AdLib 389h */
     case 0x209:                /* AdLibDataReg */
@@ -217,11 +217,11 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
             if (data & 0x80)
                 GUSregb(TimerStatus2x8) &= 0x1f; /* AdLib IRQ reset? -> clear maskable adl. timer int regs */
             else
-                GUSregb(TimerDataReg2x9) = (GUSbyte) data;
+                GUSregb(TimerDataReg2x9) = (uint8_t) data;
         }
         else
         {
-            GUSregb(AdLibData2x9) = (GUSbyte) data;
+            GUSregb(AdLibData2x9) = (uint8_t) data;
             if (GUSregb(GUS45TimerCtrl) & 0x02)
             {
                 GUSregb(TimerStatus2x8) |= 0x01;
@@ -231,16 +231,16 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
         }
         break;
     case 0x20A:
-        GUSregb(AdLibStatus2x8) = (GUSbyte) data;
+        GUSregb(AdLibStatus2x8) = (uint8_t) data;
         break;                 /* AdLibStatus2x8 */
     case 0x20B:                /* GUS hidden registers */
         switch (GUSregb(RegCtrl_2xF) & 0x7)
         {
         case 0:
             if (GUSregb(MixerCtrlReg2x0) & 0x40)
-                GUSregb(IRQ_2xB) = (GUSbyte) data; /* control register select bit */
+                GUSregb(IRQ_2xB) = (uint8_t) data; /* control register select bit */
             else
-                GUSregb(DMA_2xB) = (GUSbyte) data;
+                GUSregb(DMA_2xB) = (uint8_t) data;
             break;
             /* case 1-4: general purpose emulation regs */
         case 5:                                    /* clear stat reg 2xF */
@@ -249,7 +249,7 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
                 GUS_irqclear(state, state->gusirq);
             break;
         case 6:                                    /* Jumper reg (Joystick/MIDI enable) */
-            GUSregb(Jumper_2xB) = (GUSbyte) data;
+            GUSregb(Jumper_2xB) = (uint8_t) data;
             break;
         default:;
         }
@@ -262,20 +262,20 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
             GUS_irqrequest(state, state->gusirq, 1);
         }
     case 0x20D:                /* SB2xCd no IRQ */
-        GUSregb(SB2xCd) = (GUSbyte) data;
+        GUSregb(SB2xCd) = (uint8_t) data;
         break;
     case 0x20E:                /* SB2xE */
-        GUSregb(SB2xE) = (GUSbyte) data;
+        GUSregb(SB2xE) = (uint8_t) data;
         break;
     case 0x20F:
-        GUSregb(RegCtrl_2xF) = (GUSbyte) data;
+        GUSregb(RegCtrl_2xF) = (uint8_t) data;
         break;                 /* CtrlReg2xF */
     case 0x302:                /* VoiceSelReg */
-        GUSregb(VoiceSelReg3x2) = (GUSbyte) data;
+        GUSregb(VoiceSelReg3x2) = (uint8_t) data;
         break;
     case 0x303:                /* FunkSelReg */
-        GUSregb(FunkSelReg3x3) = (GUSbyte) data;
-        if ((GUSbyte) data == 0x8f) /* set irqstatreg, get voicereg and clear IRQ */
+        GUSregb(FunkSelReg3x3) = (uint8_t) data;
+        if ((uint8_t) data == 0x8f) /* set irqstatreg, get voicereg and clear IRQ */
         {
             int             voice;
             if (GUSregd(voicewavetableirq)) /* WavetableIRQ */
@@ -318,15 +318,15 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
     case 0x304:
     case 0x305:
         {
-            GUSword         writedata = (GUSword) data;
-            GUSword         readmask = 0x0000;
+            uint16_t         writedata = (uint16_t) data;
+            uint16_t         readmask = 0x0000;
             if (size == 1)
             {
                 readmask = 0xff00;
                 writedata &= 0xff;
                 if ((port & 0xff0f) == 0x305)
                 {
-                    writedata = (GUSword) (writedata << 8);
+                    writedata = (uint16_t) (writedata << 8);
                     readmask = 0x00ff;
                 }
             }
@@ -353,17 +353,17 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
                         break;  /* reset flag active? */
                     offset = 2 * (GUSregb(FunkSelReg3x3) & 0x0f);
                     offset += (GUSregb(VoiceSelReg3x2) & 0x1f) << 5; /*  = Voice*32 + Funktion*2 */
-                    GUSregw(offset) = (GUSword) ((GUSregw(offset) & readmask) | writedata);
+                    GUSregw(offset) = (uint16_t) ((GUSregw(offset) & readmask) | writedata);
                 }
                 break;
                 /* voice unspecific functions */
             case 0x0e:         /* NumVoices */
-                GUSregb(NumVoices) = (GUSbyte) data;
+                GUSregb(NumVoices) = (uint8_t) data;
                 break;
             /* case 0x0f:      */ /* read only */
                 /* common functions */
             case 0x41:         /* DramDMAContrReg */
-                GUSregb(GUS41DMACtrl) = (GUSbyte) data;
+                GUSregb(GUS41DMACtrl) = (uint8_t) data;
                 if (data & 0x01)
                     GUS_dmarequest(state);
                 break;
@@ -380,7 +380,7 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
                     (GUSregd(GUSDRAMPOS24bit) & 0xffff) | ((data & 0x0f) << 16);
                 break;
             case 0x45:         /* TCtrlReg */
-                GUSregb(GUS45TimerCtrl) = (GUSbyte) data;
+                GUSregb(GUS45TimerCtrl) = (uint8_t) data;
                 if (!(data & 0x20))
                     GUSregb(TimerStatus2x8) &= 0xe7;    /* sb IRQ dis? -> clear 2x8/2xC sb IRQ flags */
                 if (!(data & 0x02))
@@ -434,18 +434,18 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
                     GUS_irqclear(state, state->gusirq);
                 break;
             case 0x46:          /* Counter1 */
-                GUSregb(GUS46Counter1) = (GUSbyte) data;
+                GUSregb(GUS46Counter1) = (uint8_t) data;
                 break;
             case 0x47:          /* Counter2 */
-                GUSregb(GUS47Counter2) = (GUSbyte) data;
+                GUSregb(GUS47Counter2) = (uint8_t) data;
                 break;
             /* case 0x48:       */ /* sampling freq reg not emulated (same as interwave) */
             case 0x49:          /* SampCtrlReg */
-                GUSregb(GUS49SampCtrl) = (GUSbyte) data;
+                GUSregb(GUS49SampCtrl) = (uint8_t) data;
                 break;
             /* case 0x4b:       */ /* joystick trim not emulated */
             case 0x4c:          /* GUSreset */
-                GUSregb(GUS4cReset) = (GUSbyte) data;
+                GUSregb(GUS4cReset) = (uint8_t) data;
                 if (!(GUSregb(GUS4cReset) & 1)) /* reset... */
                 {
                     GUSregd(voicewavetableirq) = 0;
@@ -471,9 +471,9 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
         break;
     case 0x307:                /* DRAMaccess */
         {
-            GUSbyte        *adr;
+            uint8_t        *adr;
             adr = state->himemaddr + (GUSregd(GUSDRAMPOS24bit) & 0xfffff);
-            *adr = (GUSbyte) data;
+            *adr = (uint8_t) data;
         }
         break;
     }
@@ -510,7 +510,7 @@ void gus_dma_transferdata(GUSEmuState * state, char *dma_addr, unsigned int coun
     char           *srcaddr;
     char           *destaddr;
     char            msbmask = 0;
-    GUSbyte        *gusptr;
+    uint8_t        *gusptr;
     gusptr = state->gusdatapos;
 
     srcaddr = dma_addr; /* system memory address */
@@ -521,8 +521,8 @@ void gus_dma_transferdata(GUSEmuState * state, char *dma_addr, unsigned int coun
         destaddr = (char *) state->himemaddr + offset; /* wavetable RAM address */
     }
 
-    GUSregw(GUS42DMAStart) += (GUSword)  (count >> 4);                           /* ToDo: add 16bit GUS page limit? */
-    GUSregb(GUS50DMAHigh)   = (GUSbyte) ((count + GUSregb(GUS50DMAHigh)) & 0xf); /* ToDo: add 16bit GUS page limit? */
+    GUSregw(GUS42DMAStart) += (uint16_t)  (count >> 4);                           /* ToDo: add 16bit GUS page limit? */
+    GUSregb(GUS50DMAHigh)   = (uint8_t) ((count + GUSregb(GUS50DMAHigh)) & 0xf); /* ToDo: add 16bit GUS page limit? */
 
     if (GUSregb(GUS41DMACtrl) & 0x02)   /* direction, 0 := sysram->gusram */
     {
index 701e8fb0ede434afba9560d52ee9509046698f6c..00b9861b92b222b48a9d7a484a8f4a70a4217a24 100644 (file)
 #include "gustate.h"
 
 #define GUSregb(position)  (*            (gusptr+(position)))
-#define GUSregw(position)  (*(GUSword *) (gusptr+(position)))
-#define GUSregd(position)  (*(GUSdword *)(gusptr+(position)))
+#define GUSregw(position)  (*(uint16_t *) (gusptr+(position)))
+#define GUSregd(position)  (*(uint16_t *)(gusptr+(position)))
 
-#define GUSvoice(position) (*(GUSword *)(voiceptr+(position)))
+#define GUSvoice(position) (*(uint16_t *)(voiceptr+(position)))
 
 /* samples are always 16bit stereo (4 bytes each, first right then left interleaved) */
 void gus_mixvoices(GUSEmuState * state, unsigned int playback_freq, unsigned int numsamples,
-                   GUSsample *bufferpos)
+                   int16_t *bufferpos)
 {
     /* note that byte registers are stored in the upper half of each voice register! */
-    GUSbyte        *gusptr;
+    uint8_t        *gusptr;
     int             Voice;
-    GUSword        *voiceptr;
+    uint16_t       *voiceptr;
 
     unsigned int    count;
     for (count = 0; count < numsamples * 2; count++)
         *(bufferpos + count) = 0;       /* clear */
 
     gusptr = state->gusdatapos;
-    voiceptr = (GUSword *) gusptr;
+    voiceptr = (uint16_t *) gusptr;
     if (!(GUSregb(GUS4cReset) & 0x01))  /* reset flag active? */
         return;
 
@@ -85,16 +85,16 @@ void gus_mixvoices(GUSEmuState * state, unsigned int playback_freq, unsigned int
                 if (GUSvoice(wVSRControl) & 0x400)      /* 16bit */
                 {
                     int offset = ((CurrPos >> 9) & 0xc0000) + (((CurrPos >> 9) & 0x1ffff) << 1);
-                    GUSchar *adr;
-                    adr = (GUSchar *) state->himemaddr + offset;
+                    int8_t *adr;
+                    adr = (int8_t *) state->himemaddr + offset;
                     sample1 = (*adr & 0xff) + (*(adr + 1) * 256);
                     sample2 = (*(adr + 2) & 0xff) + (*(adr + 2 + 1) * 256);
                 }
                 else            /* 8bit */
                 {
                     int offset = (CurrPos >> 9) & 0xfffff;
-                    GUSchar *adr;
-                    adr = (GUSchar *) state->himemaddr + offset;
+                    int8_t *adr;
+                    adr = (int8_t *) state->himemaddr + offset;
                     sample1 = (*adr) * 256;
                     sample2 = (*(adr + 1)) * 256;
                 }
@@ -171,8 +171,8 @@ void gus_mixvoices(GUSEmuState * state, unsigned int playback_freq, unsigned int
                 }
 
                 /* mix samples into buffer */
-                *(bufferpos + 2 * sample)     += (GUSsample) ((sample1 * PanningPos) >> 4);        /* right */
-                *(bufferpos + 2 * sample + 1) += (GUSsample) ((sample1 * (15 - PanningPos)) >> 4); /* left */
+                *(bufferpos + 2 * sample)     += (int16_t) ((sample1 * PanningPos) >> 4);        /* right */
+                *(bufferpos + 2 * sample + 1) += (int16_t) ((sample1 * (15 - PanningPos)) >> 4); /* left */
             }
             /* write back voice and volume */
             GUSvoice(wVSRCurrVol)   = Volume32 / 32;
@@ -187,7 +187,7 @@ void gus_irqgen(GUSEmuState * state, unsigned int elapsed_time)
 /* time given in microseconds */
 {
     int             requestedIRQs = 0;
-    GUSbyte        *gusptr;
+    uint8_t        *gusptr;
     gusptr = state->gusdatapos;
     if (GUSregb(TimerDataReg2x9) & 1) /* start timer 1 (80us decrement rate) */
     {
index 52d4640e60b7d489b0e9466cb92f7ba9315d515f..5402cd196c6d36442235a9f4a37289fe4eef5f6d 100644 (file)
@@ -520,7 +520,7 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
     return 0;
 }
 
-static int hda_audio_exit(HDACodecDevice *hda)
+static void hda_audio_exit(HDACodecDevice *hda)
 {
     HDAAudioState *a = HDA_AUDIO(hda);
     HDAAudioStream *st;
@@ -539,7 +539,6 @@ static int hda_audio_exit(HDACodecDevice *hda)
         }
     }
     AUD_remove_card(&a->card);
-    return 0;
 }
 
 static int hda_audio_post_load(void *opaque, int version)
index 537face94d8e1ea4d6a48fa5b31a7099a9f3974b..2c497eb174b72d7c1ba39f874407f0717ce90a38 100644 (file)
@@ -70,7 +70,7 @@ static void hda_codec_dev_realize(DeviceState *qdev, Error **errp)
     }
 }
 
-static int hda_codec_dev_exit(DeviceState *qdev)
+static void hda_codec_dev_unrealize(DeviceState *qdev, Error **errp)
 {
     HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
     HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
@@ -78,7 +78,6 @@ static int hda_codec_dev_exit(DeviceState *qdev)
     if (cdc->exit) {
         cdc->exit(dev);
     }
-    return 0;
 }
 
 HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
@@ -1318,7 +1317,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *k = DEVICE_CLASS(klass);
     k->realize = hda_codec_dev_realize;
-    k->exit = hda_codec_dev_exit;
+    k->unrealize = hda_codec_dev_unrealize;
     set_bit(DEVICE_CATEGORY_SOUND, k->categories);
     k->bus_type = TYPE_HDA_BUS;
     k->props = hda_props;
index d784bcf5fc9f3e22e49fc9b11228722665cd0c39..53b78da4df0cdb96a46973c4fc66c77e61bd127e 100644 (file)
@@ -38,7 +38,7 @@ typedef struct HDACodecDeviceClass
     DeviceClass parent_class;
 
     int (*init)(HDACodecDevice *dev);
-    int (*exit)(HDACodecDevice *dev);
+    void (*exit)(HDACodecDevice *dev);
     void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
     void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool output);
 } HDACodecDeviceClass;
index 725fdc46f4d17df2e6bddb74ee1ff8f35d945053..55fcb68fd269e59834cde20cbbb6c42d8818eddf 100644 (file)
@@ -29,3 +29,4 @@ common-obj-$(CONFIG_MILKYMIST) += milkymist-uart.o
 common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o
 
 obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
+obj-$(CONFIG_TERMINAL3270) += terminal3270.o
diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
new file mode 100644 (file)
index 0000000..b2dda01
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Terminal 3270 implementation
+ *
+ * Copyright 2017 IBM Corp.
+ *
+ * Authors: Yang Chen <bjcyang@linux.vnet.ibm.com>
+ *          Jing Liu <liujbjl@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "sysemu/char.h"
+#include "hw/s390x/3270-ccw.h"
+
+/* Enough spaces for different window sizes. */
+#define INPUT_BUFFER_SIZE  1000
+/*
+ * 1 for header, 1024*2 for datastream, 2 for tail
+ * Reserve enough spaces for telnet IAC escape.
+ */
+#define OUTPUT_BUFFER_SIZE 2051
+
+typedef struct Terminal3270 {
+    EmulatedCcw3270Device cdev;
+    CharBackend chr;
+    uint8_t inv[INPUT_BUFFER_SIZE];
+    uint8_t outv[OUTPUT_BUFFER_SIZE];
+    int in_len;
+    int out_len;
+    bool handshake_done;
+    guint timer_tag;
+} Terminal3270;
+
+#define TYPE_TERMINAL_3270 "x-terminal3270"
+#define TERMINAL_3270(obj) \
+        OBJECT_CHECK(Terminal3270, (obj), TYPE_TERMINAL_3270)
+
+static int terminal_can_read(void *opaque)
+{
+    Terminal3270 *t = opaque;
+
+    return INPUT_BUFFER_SIZE - t->in_len;
+}
+
+/*
+ * Protocol handshake done,
+ * signal guest by an unsolicited DE irq.
+ */
+static void TN3270_handshake_done(Terminal3270 *t)
+{
+    CcwDevice *ccw_dev = CCW_DEVICE(t);
+    SubchDev *sch = ccw_dev->sch;
+
+    t->handshake_done = true;
+    sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END;
+    css_conditional_io_interrupt(sch);
+}
+
+/*
+ * Called when the interval is timeout to detect
+ * if the client is still alive by Timing Mark.
+ */
+static gboolean send_timing_mark_cb(gpointer opaque)
+{
+    Terminal3270 *t = opaque;
+    const uint8_t timing[] = {0xff, 0xfd, 0x06};
+
+    qemu_chr_fe_write_all(&t->chr, timing, sizeof(timing));
+    return true;
+}
+
+/*
+ * Receive inbound data from socket.
+ * For data given to guest, drop the data boundary IAC, IAC_EOR.
+ * TODO:
+ * Using "Reset" key on x3270 may result multiple commands in one packet.
+ * This usually happens when the user meets a poor traffic of the network.
+ * As of now, for such case, we simply terminate the connection,
+ * and we should come back here later with a better solution.
+ */
+static void terminal_read(void *opaque, const uint8_t *buf, int size)
+{
+    Terminal3270 *t = opaque;
+    CcwDevice *ccw_dev = CCW_DEVICE(t);
+    SubchDev *sch = ccw_dev->sch;
+    int end;
+
+    assert(size <= (INPUT_BUFFER_SIZE - t->in_len));
+
+    if (t->timer_tag) {
+        g_source_remove(t->timer_tag);
+        t->timer_tag = 0;
+    }
+    t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
+
+    memcpy(&t->inv[t->in_len], buf, size);
+    t->in_len += size;
+    if (t->in_len < 2) {
+        return;
+    }
+
+    if (!t->handshake_done) {
+        /*
+         * Receiving Terminal Type is the last step of handshake.
+         * The data format: IAC SB Terminal-Type IS <terminal type> IAC SE
+         * The code for Terminal-Type is 0x18, for IS is 0.
+         * Simply check the data format and mark handshake_done.
+         */
+        if (t->in_len > 6 && t->inv[2] == 0x18 && t->inv[3] == 0x0 &&
+            t->inv[t->in_len - 2] == IAC && t->inv[t->in_len - 1] == IAC_SE) {
+            TN3270_handshake_done(t);
+            t->in_len = 0;
+        }
+        return;
+    }
+
+    for (end = 0; end < t->in_len - 1; end++) {
+        if (t->inv[end] == IAC && t->inv[end + 1] == IAC_EOR) {
+            break;
+        }
+    }
+    if (end == t->in_len - 2) {
+        /* Data is valid for consuming. */
+        t->in_len -= 2;
+        sch->curr_status.scsw.dstat = SCSW_DSTAT_ATTENTION;
+        css_conditional_io_interrupt(sch);
+    } else if (end < t->in_len - 2) {
+        /* "Reset" key is used. */
+        qemu_chr_fe_disconnect(&t->chr);
+    } else {
+        /* Gathering data. */
+        return;
+    }
+}
+
+static void chr_event(void *opaque, int event)
+{
+    Terminal3270 *t = opaque;
+    CcwDevice *ccw_dev = CCW_DEVICE(t);
+    SubchDev *sch = ccw_dev->sch;
+
+    /* Ensure the initial status correct, always reset them. */
+    t->in_len = 0;
+    t->out_len = 0;
+    t->handshake_done = false;
+    if (t->timer_tag) {
+        g_source_remove(t->timer_tag);
+        t->timer_tag = 0;
+    }
+
+    switch (event) {
+    case CHR_EVENT_OPENED:
+        /*
+         * 3270 does handshake firstly by the negotiate options in
+         * char-socket.c. Once qemu receives the terminal-type of the
+         * client, mark handshake done and trigger everything rolling again.
+         */
+        t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
+        break;
+    case CHR_EVENT_CLOSED:
+        sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END;
+        css_conditional_io_interrupt(sch);
+        break;
+    }
+}
+
+static void terminal_init(EmulatedCcw3270Device *dev, Error **errp)
+{
+    Terminal3270 *t = TERMINAL_3270(dev);
+    static bool terminal_available;
+
+    if (terminal_available) {
+        error_setg(errp, "Multiple 3270 terminals are not supported.");
+        return;
+    }
+    terminal_available = true;
+    qemu_chr_fe_set_handlers(&t->chr, terminal_can_read,
+                             terminal_read, chr_event, t, NULL, true);
+}
+
+static int read_payload_3270(EmulatedCcw3270Device *dev, uint32_t cda,
+                             uint16_t count)
+{
+    Terminal3270 *t = TERMINAL_3270(dev);
+    int len;
+
+    len = MIN(count, t->in_len);
+    cpu_physical_memory_write(cda, t->inv, len);
+    t->in_len -= len;
+
+    return len;
+}
+
+/* TN3270 uses binary transmission, which needs escape IAC to IAC IAC */
+static int insert_IAC_escape_char(uint8_t *outv, int out_len)
+{
+    int IAC_num = 0, new_out_len, i, j;
+
+    for (i = 0; i < out_len; i++) {
+        if (outv[i] == IAC) {
+            IAC_num++;
+        }
+    }
+    if (IAC_num == 0) {
+        return out_len;
+    }
+    new_out_len = out_len + IAC_num;
+    for (i = out_len - 1, j = new_out_len - 1; j > i && i >= 0; i--, j--) {
+        outv[j] = outv[i];
+        if (outv[i] == IAC) {
+            outv[--j] = IAC;
+        }
+    }
+    return new_out_len;
+}
+
+/*
+ * Write 3270 outbound to socket.
+ * Return the count of 3270 data field if succeeded, zero if failed.
+ */
+static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd,
+                              uint32_t cda, uint16_t count)
+{
+    Terminal3270 *t = TERMINAL_3270(dev);
+    int retval = 0;
+
+    assert(count <= (OUTPUT_BUFFER_SIZE - 3) / 2);
+
+    if (!t->handshake_done) {
+        if (!(t->outv[0] == IAC && t->outv[1] != IAC)) {
+            /*
+             * Before having finished 3270 negotiation,
+             * sending outbound data except protocol options is prohibited.
+             */
+            return 0;
+        }
+    }
+    if (!qemu_chr_fe_get_driver(&t->chr)) {
+        /* We just say we consumed all data if there's no backend. */
+        return count;
+    }
+    t->outv[0] = cmd;
+    cpu_physical_memory_read(cda, &t->outv[1], count);
+    t->out_len = count + 1;
+
+    t->out_len = insert_IAC_escape_char(t->outv, t->out_len);
+    t->outv[t->out_len++] = IAC;
+    t->outv[t->out_len++] = IAC_EOR;
+
+    retval = qemu_chr_fe_write_all(&t->chr, t->outv, t->out_len);
+    return (retval <= 0) ? 0 : (retval - 3);
+}
+
+static Property terminal_properties[] = {
+    DEFINE_PROP_CHR("chardev", Terminal3270, chr),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription terminal3270_vmstate = {
+    .name = TYPE_TERMINAL_3270,
+    .unmigratable = 1,
+};
+
+static void terminal_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_CLASS(klass);
+
+    dc->props = terminal_properties;
+    dc->vmsd = &terminal3270_vmstate;
+    ck->init = terminal_init;
+    ck->read_payload_3270 = read_payload_3270;
+    ck->write_payload_3270 = write_payload_3270;
+}
+
+static const TypeInfo ccw_terminal_info = {
+    .name = TYPE_TERMINAL_3270,
+    .parent = TYPE_EMULATED_CCW_3270,
+    .instance_size = sizeof(Terminal3270),
+    .class_init = terminal_class_init,
+    .class_size = sizeof(EmulatedCcw3270Class),
+};
+
+static void register_types(void)
+{
+    type_register_static(&ccw_terminal_info);
+}
+
+type_init(register_types)
index fa9cc4c61630e0f562137081dae41a6f7db53b2b..93887ecc43acce453e8aa977be18d451e7d9a247 100644 (file)
@@ -256,6 +256,10 @@ static void hid_keyboard_process_keycode(HIDState *hs)
     slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
     keycode = hs->kbd.keycodes[slot];
 
+    if (!hs->n) {
+        trace_hid_kbd_queue_empty();
+    }
+
     key = keycode & 0x7f;
     index = key | ((hs->kbd.modifiers & (1 << 8)) >> 1);
     hid_code = hid_usage_keys[index];
index f3bfbede5c4363f1cd8aa71144f914e2044160a4..5a87818b4929a3a9b4672cfd61e92c22e9b2b030 100644 (file)
@@ -24,6 +24,7 @@ milkymist_softusb_pulse_irq(void) "Pulse IRQ"
 
 # hw/input/hid.c
 hid_kbd_queue_full(void) "queue full"
+hid_kbd_queue_empty(void) "queue empty"
 
 # hw/input/virtio
 virtio_input_queue_full(void) "queue full"
index a98c799de66bbb3a2c530ae26e9458911a24cbc6..febc469170e74f75c0f2e587bb42db7e473483d6 100644 (file)
@@ -61,6 +61,7 @@ void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
     }
     next = now + (uint64_t)wait * TIMER_PERIOD;
     timer_mod(cpu->env.timer, next);
+    qemu_cpu_kick(CPU(cpu));
 }
 
 void cpu_openrisc_count_start(OpenRISCCPU *cpu)
diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
new file mode 100644 (file)
index 0000000..a7a5b41
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Emulated ccw-attached 3270 implementation
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
+ *            Jing Liu <liujbjl@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "cpu.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/css-bridge.h"
+#include "hw/s390x/3270-ccw.h"
+
+/* Handle READ ccw commands from guest */
+static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
+{
+    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
+    CcwDevice *ccw_dev = CCW_DEVICE(dev);
+    int len;
+
+    if (!ccw->cda) {
+        return -EFAULT;
+    }
+
+    len = ck->read_payload_3270(dev, ccw->cda, ccw->count);
+    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
+
+    return 0;
+}
+
+/* Handle WRITE ccw commands to write data to client */
+static int handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw)
+{
+    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
+    CcwDevice *ccw_dev = CCW_DEVICE(dev);
+    int len;
+
+    if (!ccw->cda) {
+        return -EFAULT;
+    }
+
+    len = ck->write_payload_3270(dev, ccw->cmd_code, ccw->cda, ccw->count);
+
+    if (len <= 0) {
+        return -EIO;
+    }
+
+    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
+    return 0;
+}
+
+static int emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
+{
+    int rc = 0;
+    EmulatedCcw3270Device *dev = sch->driver_data;
+
+    switch (ccw.cmd_code) {
+    case TC_WRITESF:
+    case TC_WRITE:
+    case TC_EWRITE:
+    case TC_EWRITEA:
+        rc = handle_payload_3270_write(dev, &ccw);
+        break;
+    case TC_RDBUF:
+    case TC_READMOD:
+        rc = handle_payload_3270_read(dev, &ccw);
+        break;
+    default:
+        rc = -ENOSYS;
+        break;
+    }
+
+    if (rc == -EIO) {
+        /* I/O error, specific devices generate specific conditions */
+        SCSW *s = &sch->curr_status.scsw;
+
+        sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_CHECK;
+        sch->sense_data[0] = 0x40;    /* intervention-req */
+        s->ctrl &= ~SCSW_ACTL_START_PEND;
+        s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+        s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
+                   SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+    }
+
+    return rc;
+}
+
+static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
+{
+    uint16_t chpid;
+    EmulatedCcw3270Device *dev = EMULATED_CCW_3270(ds);
+    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
+    CcwDevice *cdev = CCW_DEVICE(ds);
+    CCWDeviceClass *cdk = CCW_DEVICE_GET_CLASS(cdev);
+    SubchDev *sch = css_create_virtual_sch(cdev->devno, errp);
+    Error *err = NULL;
+
+    if (!sch) {
+        return;
+    }
+
+    if (!ck->init) {
+        goto out_err;
+    }
+
+    sch->driver_data = dev;
+    cdev->sch = sch;
+    chpid = css_find_free_chpid(sch->cssid);
+
+    if (chpid > MAX_CHPID) {
+        error_setg(&err, "No available chpid to use.");
+        goto out_err;
+    }
+
+    sch->id.reserved = 0xff;
+    sch->id.cu_type = EMULATED_CCW_3270_CU_TYPE;
+    css_sch_build_virtual_schib(sch, (uint8_t)chpid,
+                                EMULATED_CCW_3270_CHPID_TYPE);
+    sch->ccw_cb = emulated_ccw_3270_cb;
+
+    ck->init(dev, &err);
+    if (err) {
+        goto out_err;
+    }
+
+    cdk->realize(cdev, &err);
+    if (err) {
+        goto out_err;
+    }
+
+    return;
+
+out_err:
+    error_propagate(errp, err);
+    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
+    cdev->sch = NULL;
+    g_free(sch);
+}
+
+static Property emulated_ccw_3270_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void emulated_ccw_3270_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = emulated_ccw_3270_properties;
+    dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
+    dc->realize = emulated_ccw_3270_realize;
+    dc->hotpluggable = false;
+}
+
+static const TypeInfo emulated_ccw_3270_info = {
+    .name = TYPE_EMULATED_CCW_3270,
+    .parent = TYPE_CCW_DEVICE,
+    .instance_size = sizeof(EmulatedCcw3270Device),
+    .class_init = emulated_ccw_3270_class_init,
+    .class_size = sizeof(EmulatedCcw3270Class),
+    .abstract = true,
+};
+
+static void emulated_ccw_register(void)
+{
+    type_register_static(&emulated_ccw_3270_info);
+}
+
+type_init(emulated_ccw_register)
index 41ac4ec32544b76d80bead87b2361c499826c098..36bd4b16459905dde87162a65cc5bfe0f32a179e 100644 (file)
@@ -7,6 +7,7 @@ obj-y += sclpcpu.o
 obj-y += ipl.o
 obj-y += css.o
 obj-y += s390-virtio-ccw.o
+obj-y += 3270-ccw.o
 obj-y += virtio-ccw.o
 obj-y += css-bridge.o
 obj-y += ccw-device.o
index c03bb20bc994a8cba2b87ca82f83b90b0f908c7e..15c4f4b249d9eb1bdc1ac0c14e2af684f098c2a5 100644 (file)
@@ -576,6 +576,9 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
             s->dstat = SCSW_DSTAT_CHANNEL_END | SCSW_DSTAT_DEVICE_END;
             s->cpa = sch->channel_prog + 8;
             break;
+        case -EIO:
+            /* I/O errors, status depends on specific devices */
+            break;
         case -ENOSYS:
             /* unsupported command, generate unit check (command reject) */
             s->ctrl &= ~SCSW_ACTL_START_PEND;
@@ -1302,6 +1305,27 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
                                  (MAX_SCHID + 1) / sizeof(unsigned long));
 }
 
+unsigned int css_find_free_chpid(uint8_t cssid)
+{
+    CssImage *css = channel_subsys.css[cssid];
+    unsigned int chpid;
+
+    if (!css) {
+        return MAX_CHPID + 1;
+    }
+
+    for (chpid = 0; chpid <= MAX_CHPID; chpid++) {
+        /* skip reserved chpid */
+        if (chpid == VIRTIO_CCW_CHPID) {
+            continue;
+        }
+        if (!css->chpids[chpid].in_use) {
+            return chpid;
+        }
+    }
+    return MAX_CHPID + 1;
+}
+
 static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
 {
     CssImage *css;
index 7978c7d52a89f1e4df6bf9ea20cdc28fb9ebf83f..75d3c681a42f1b0fdc7ad4727401d931f5b9c7d6 100644 (file)
 #include "cpu.h"
 #include "elf.h"
 #include "hw/loader.h"
+#include "hw/boards.h"
 #include "hw/s390x/virtio-ccw.h"
 #include "hw/s390x/css.h"
+#include "hw/s390x/ebcdic.h"
 #include "ipl.h"
 #include "qemu/error-report.h"
 
@@ -243,12 +245,17 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
             ipl->iplb.pbt = S390_IPL_TYPE_CCW;
             ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
             ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
-            return true;
         } else if (sd) {
             SCSIBus *bus = scsi_bus_from_device(sd);
             VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
             VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev);
-            CcwDevice *ccw_dev = CCW_DEVICE(scsi_ccw);
+            CcwDevice *ccw_dev;
+
+            ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
+                                                       TYPE_CCW_DEVICE);
+            if (!ccw_dev) {       /* It might be a PCI device instead */
+                return false;
+            }
 
             ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
             ipl->iplb.blk0_len =
@@ -259,13 +266,39 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
             ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
             ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
             ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
-            return true;
+        } else {
+            return false; /* unknown device */
         }
+
+        if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
+            ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
+        }
+        return true;
     }
 
     return false;
 }
 
+int s390_ipl_set_loadparm(uint8_t *loadparm)
+{
+    MachineState *machine = MACHINE(qdev_get_machine());
+    char *lp = object_property_get_str(OBJECT(machine), "loadparm", NULL);
+
+    if (lp) {
+        int i;
+
+        /* lp is an uppercase string without leading/embedded spaces */
+        for (i = 0; i < 8 && lp[i]; i++) {
+            loadparm[i] = ascii2ebcdic[(uint8_t) lp[i]];
+        }
+
+        g_free(lp);
+        return 0;
+    }
+
+    return -1;
+}
+
 static int load_netboot_image(Error **errp)
 {
     S390IPLState *ipl = get_ipl_device();
index 46930e4c649bf333e6d4266dc598d5a8e785050e..8a705e0428a3127cb5470a2c35b5384c96f894b9 100644 (file)
@@ -57,6 +57,8 @@ struct IplBlockQemuScsi {
 } QEMU_PACKED;
 typedef struct IplBlockQemuScsi IplBlockQemuScsi;
 
+#define DIAG308_FLAGS_LP_VALID 0x80
+
 union IplParameterBlock {
     struct {
         uint32_t len;
@@ -82,6 +84,7 @@ union IplParameterBlock {
 } QEMU_PACKED;
 typedef union IplParameterBlock IplParameterBlock;
 
+int s390_ipl_set_loadparm(uint8_t *loadparm);
 void s390_ipl_update_diag308(IplParameterBlock *iplb);
 void s390_ipl_prepare_cpu(S390CPU *cpu);
 IplParameterBlock *s390_ipl_get_iplb(void);
index 04bd0ebe40b827727a785a1ce9accba4702e2125..fdd4384ff0beab97ef0ec0c29ca495c9be69c23c 100644 (file)
@@ -274,6 +274,36 @@ bool cpu_model_allowed(void)
     return true;
 }
 
+static char *machine_get_loadparm(Object *obj, Error **errp)
+{
+    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+
+    return g_memdup(ms->loadparm, sizeof(ms->loadparm));
+}
+
+static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
+{
+    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+    int i;
+
+    for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) {
+        uint8_t c = toupper(val[i]); /* mimic HMC */
+
+        if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || (c == '.') ||
+            (c == ' ')) {
+            ms->loadparm[i] = c;
+        } else {
+            error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)",
+                       c, c);
+            return;
+        }
+    }
+
+    for (; i < sizeof(ms->loadparm); i++) {
+        ms->loadparm[i] = ' '; /* pad right with spaces */
+    }
+}
+
 static inline void s390_machine_initfn(Object *obj)
 {
     object_property_add_bool(obj, "aes-key-wrap",
@@ -291,6 +321,13 @@ static inline void s390_machine_initfn(Object *obj)
             "enable/disable DEA key wrapping using the CPACF wrapping key",
             NULL);
     object_property_set_bool(obj, true, "dea-key-wrap", NULL);
+    object_property_add_str(obj, "loadparm",
+            machine_get_loadparm, machine_set_loadparm, NULL);
+    object_property_set_description(obj, "loadparm",
+            "Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
+            " to upper case) to pass to machine loader, boot manager,"
+            " and guest kernel",
+            NULL);
 }
 
 static const TypeInfo ccw_machine_info = {
index e741da1141191bb5874c1e29eef6e07bb8aae918..b4f6dd58dd7ab8c62272dde7d0c598e7e4c5e8c7 100644 (file)
@@ -23,6 +23,7 @@
 #include "hw/s390x/sclp.h"
 #include "hw/s390x/event-facility.h"
 #include "hw/s390x/s390-pci-bus.h"
+#include "hw/s390x/ipl.h"
 
 static inline SCLPDevice *get_sclp_device(void)
 {
@@ -57,6 +58,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
     int cpu_count = 0;
     int rnsize, rnmax;
     int slots = MIN(machine->ram_slots, s390_get_memslot_count(kvm_state));
+    IplParameterBlock *ipib = s390_ipl_get_iplb();
 
     CPU_FOREACH(cpu) {
         cpu_count++;
@@ -129,6 +131,13 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
         read_info->rnmax2 = cpu_to_be64(rnmax);
     }
 
+    if (ipib && ipib->flags & DIAG308_FLAGS_LP_VALID) {
+        memcpy(&read_info->loadparm, &ipib->loadparm,
+               sizeof(read_info->loadparm));
+    } else {
+        s390_ipl_set_loadparm(read_info->loadparm);
+    }
+
     sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
 }
 
index 6b33b9f55df182d7fd2bea58ef11fbc553c39bbd..a8f12eeb358932023fcf78df703f598bd8e6276c 100644 (file)
@@ -119,6 +119,9 @@ void vfio_region_write(void *opaque, hwaddr addr,
     case 4:
         buf.dword = cpu_to_le32(data);
         break;
+    case 8:
+        buf.qword = cpu_to_le64(data);
+        break;
     default:
         hw_error("vfio: unsupported write size, %d bytes", size);
         break;
@@ -173,6 +176,9 @@ uint64_t vfio_region_read(void *opaque,
     case 4:
         data = le32_to_cpu(buf.dword);
         break;
+    case 8:
+        data = le64_to_cpu(buf.qword);
+        break;
     default:
         hw_error("vfio: unsupported read size, %d bytes", size);
         break;
@@ -190,6 +196,14 @@ const MemoryRegionOps vfio_region_ops = {
     .read = vfio_region_read,
     .write = vfio_region_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
 };
 
 /*
index 03a3d01549765b23adf61b6c7591382bc7446772..32aca7770177a479c7d31a617604e38ec11f8bbc 100644 (file)
@@ -2625,8 +2625,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
         if (!(~vdev->host.domain || ~vdev->host.bus ||
               ~vdev->host.slot || ~vdev->host.function)) {
             error_setg(errp, "No provided host device");
-            error_append_hint(errp, "Use -vfio-pci,host=DDDD:BB:DD.F "
-                              "or -vfio-pci,sysfsdev=PATH_TO_DEVICE\n");
+            error_append_hint(errp, "Use -device vfio-pci,host=DDDD:BB:DD.F "
+                              "or -device vfio-pci,sysfsdev=PATH_TO_DEVICE\n");
             return;
         }
         vdev->vbasedev.sysfsdev =
index 144df0ddfb9e3c48ff4440aac3da13200066a822..862eb56fc72333317447195e2c9653e388cfc843 100644 (file)
@@ -294,7 +294,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
     const char *backing_file);
 int bdrv_get_backing_file_depth(BlockDriverState *bs);
 void bdrv_refresh_filename(BlockDriverState *bs);
-int bdrv_truncate(BdrvChild *child, int64_t offset);
+int bdrv_truncate(BdrvChild *child, int64_t offset, Error **errp);
 int64_t bdrv_nb_sectors(BlockDriverState *bs);
 int64_t bdrv_getlength(BlockDriverState *bs);
 int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
index 4f8cd29ae4defc9018772b909a0a12259ffb2109..87739405d5e22589f6a72dff0d42a5f372e64c9e 100644 (file)
@@ -196,7 +196,7 @@ struct BlockDriver {
     int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs);
 
     const char *protocol_name;
-    int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
+    int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset, Error **errp);
 
     int64_t (*bdrv_getlength)(BlockDriverState *bs);
     bool has_variable_length;
@@ -252,7 +252,7 @@ struct BlockDriver {
      * Returns 0 for completed check, -errno for internal errors.
      * The check results are stored in result.
      */
-    int (*bdrv_check)(BlockDriverStatebs, BdrvCheckResult *result,
+    int (*bdrv_check)(BlockDriverState *bs, BdrvCheckResult *result,
         BdrvCheckMode fix);
 
     int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
@@ -454,13 +454,13 @@ struct BdrvChildRole {
     /* Returns a name that is supposedly more useful for human users than the
      * node name for identifying the node in question (in particular, a BB
      * name), or NULL if the parent can't provide a better name. */
-    const char(*get_name)(BdrvChild *child);
+    const char *(*get_name)(BdrvChild *child);
 
     /* Returns a malloced string that describes the parent of the child for a
      * human reader. This could be a node-name, BlockBackend name, qdev ID or
      * QOM path of the device owning the BlockBackend, job type and ID etc. The
      * caller is responsible for freeing the memory. */
-    char(*get_parent_desc)(BdrvChild *child);
+    char *(*get_parent_desc)(BdrvChild *child);
 
     /*
      * If this pair of functions is implemented, the parent doesn't issue new
index dbe2f08d4733b367d236c69083e911c9461deb93..140efa840c47c045b5149d615c7dbe370628f1a7 100644 (file)
@@ -39,6 +39,14 @@ struct RAMBlock {
     QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers;
     int fd;
     size_t page_size;
+    /* dirty bitmap used during migration */
+    unsigned long *bmap;
+    /* bitmap of pages that haven't been sent even once
+     * only maintained and used in postcopy at the moment
+     * where it's used to send the dirtymap at the start
+     * of the postcopy phase
+     */
+    unsigned long *unsentmap;
 };
 
 static inline bool offset_in_ramblock(RAMBlock *b, ram_addr_t offset)
@@ -360,16 +368,15 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
 
 
 static inline
-uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
-                                               RAMBlock *rb,
+uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb,
                                                ram_addr_t start,
                                                ram_addr_t length,
                                                uint64_t *real_dirty_pages)
 {
     ram_addr_t addr;
-    start = rb->offset + start;
     unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
     uint64_t num_dirty = 0;
+    unsigned long *dest = rb->bmap;
 
     /* start address is aligned at the start of a word? */
     if (((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) {
diff --git a/include/hw/s390x/3270-ccw.h b/include/hw/s390x/3270-ccw.h
new file mode 100644 (file)
index 0000000..46bee25
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Emulated ccw-attached 3270 definitions
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
+ *            Jing Liu <liujbjl@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_S390X_3270_CCW_H
+#define HW_S390X_3270_CCW_H
+
+#include "hw/sysbus.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/ccw-device.h"
+
+#define EMULATED_CCW_3270_CU_TYPE 0x3270
+#define EMULATED_CCW_3270_CHPID_TYPE 0x1a
+
+#define TYPE_EMULATED_CCW_3270 "emulated-ccw-3270"
+
+/* Local Channel Commands */
+#define TC_WRITE   0x01         /* Write */
+#define TC_RDBUF   0x02         /* Read buffer */
+#define TC_EWRITE  0x05         /* Erase write */
+#define TC_READMOD 0x06         /* Read modified */
+#define TC_EWRITEA 0x0d         /* Erase write alternate */
+#define TC_WRITESF 0x11         /* Write structured field */
+
+#define EMULATED_CCW_3270(obj) \
+     OBJECT_CHECK(EmulatedCcw3270Device, (obj), TYPE_EMULATED_CCW_3270)
+#define EMULATED_CCW_3270_CLASS(klass) \
+     OBJECT_CLASS_CHECK(EmulatedCcw3270Class, (klass), TYPE_EMULATED_CCW_3270)
+#define EMULATED_CCW_3270_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(EmulatedCcw3270Class, (obj), TYPE_EMULATED_CCW_3270)
+
+typedef struct EmulatedCcw3270Device {
+    CcwDevice parent_obj;
+} EmulatedCcw3270Device;
+
+typedef struct EmulatedCcw3270Class {
+    CCWDeviceClass parent_class;
+
+    void (*init)(EmulatedCcw3270Device *, Error **);
+    int (*read_payload_3270)(EmulatedCcw3270Device *, uint32_t, uint16_t);
+    int (*write_payload_3270)(EmulatedCcw3270Device *, uint8_t, uint32_t,
+                              uint16_t);
+} EmulatedCcw3270Class;
+
+#endif
index f1f0d7f07a0be4ee2cc04e4abace927a12546e01..e61fa74d9b049acb84734fafe405cd2afd0e69e8 100644 (file)
@@ -28,6 +28,7 @@
 #define MAX_CIWS 62
 
 #define VIRTUAL_CSSID 0xfe
+#define VIRTIO_CCW_CHPID 0   /* used by convention */
 
 typedef struct CIW {
     uint8_t type;
@@ -115,6 +116,7 @@ bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno);
 void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
                       uint16_t devno, SubchDev *sch);
 void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
+unsigned int css_find_free_chpid(uint8_t cssid);
 uint16_t css_build_subchannel_id(SubchDev *sch);
 void css_reset(void);
 void css_reset_sch(SubchDev *sch);
index 6ecae0038609301169b1fbc3efba8297b4dcf1f2..7b8a3e4d749cdab4d3810a30a03614683995e5a4 100644 (file)
@@ -28,6 +28,7 @@ typedef struct S390CcwMachineState {
     /*< public >*/
     bool aes_key_wrap;
     bool dea_key_wrap;
+    uint8_t loadparm[8];
 } S390CcwMachineState;
 
 typedef struct S390CcwMachineClass {
index f3d5dfcf613a43286a6f38e341beba3925cab497..a40bd3549f4743f7bf0c7c70feb32df0958c084f 100644 (file)
@@ -18,6 +18,8 @@
     VMSTATE_UINT64_EQUAL_V(_f, _s, _v)
 #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v)
+#define VMSTATE_UINTTL_2DARRAY_V(_f, _s, _n1, _n2, _v)                \
+    VMSTATE_UINT64_2DARRAY_V(_f, _s, _n1, _n2, _v)
 #define VMSTATE_UINTTL_TEST(_f, _s, _t)                               \
     VMSTATE_UINT64_TEST(_f, _s, _t)
 #define vmstate_info_uinttl vmstate_info_uint64
@@ -37,6 +39,8 @@
     VMSTATE_UINT32_EQUAL_V(_f, _s, _v)
 #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)
+#define VMSTATE_UINTTL_2DARRAY_V(_f, _s, _n1, _n2, _v)                \
+    VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, _v)
 #define VMSTATE_UINTTL_TEST(_f, _s, _t)                               \
     VMSTATE_UINT32_TEST(_f, _s, _t)
 #define vmstate_info_uinttl vmstate_info_uint32
@@ -48,5 +52,8 @@
     VMSTATE_UINTTL_EQUAL_V(_f, _s, 0)
 #define VMSTATE_UINTTL_ARRAY(_f, _s, _n)                              \
     VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, 0)
+#define VMSTATE_UINTTL_2DARRAY(_f, _s, _n1, _n2)                      \
+    VMSTATE_UINTTL_2DARRAY_V(_f, _s, _n1, _n2, 0)
+
 
 #endif
index ba1a16cbc1ba99d40beb1fac620af02698e2ee8b..e29cb0144b9f94fccfb475bf116183064a975462 100644 (file)
@@ -266,7 +266,8 @@ uint64_t xbzrle_mig_pages_cache_miss(void);
 double xbzrle_mig_cache_miss_rate(void);
 
 void ram_handle_compressed(void *host, uint8_t ch, uint64_t size);
-void ram_debug_dump_bitmap(unsigned long *todump, bool expected);
+void ram_debug_dump_bitmap(unsigned long *todump, bool expected,
+                           unsigned long pages);
 /* For outgoing discard bitmap */
 int ram_postcopy_send_discard_bitmap(MigrationState *ms);
 /* For incoming postcopy discard */
diff --git a/include/migration/postcopy-ram.h b/include/migration/postcopy-ram.h
deleted file mode 100644 (file)
index 8e036b9..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Postcopy migration for RAM
- *
- * Copyright 2013 Red Hat, Inc. and/or its affiliates
- *
- * Authors:
- *  Dave Gilbert  <dgilbert@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-#ifndef QEMU_POSTCOPY_RAM_H
-#define QEMU_POSTCOPY_RAM_H
-
-/* Return true if the host supports everything we need to do postcopy-ram */
-bool postcopy_ram_supported_by_host(void);
-
-/*
- * Make all of RAM sensitive to accesses to areas that haven't yet been written
- * and wire up anything necessary to deal with it.
- */
-int postcopy_ram_enable_notify(MigrationIncomingState *mis);
-
-/*
- * Initialise postcopy-ram, setting the RAM to a state where we can go into
- * postcopy later; must be called prior to any precopy.
- * called from ram.c's similarly named ram_postcopy_incoming_init
- */
-int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages);
-
-/*
- * At the end of a migration where postcopy_ram_incoming_init was called.
- */
-int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis);
-
-/*
- * Userfault requires us to mark RAM as NOHUGEPAGE prior to discard
- * however leaving it until after precopy means that most of the precopy
- * data is still THPd
- */
-int postcopy_ram_prepare_discard(MigrationIncomingState *mis);
-
-/*
- * Called at the start of each RAMBlock by the bitmap code.
- * 'offset' is the bitmap offset of the named RAMBlock in the migration
- * bitmap.
- * Returns a new PDS
- */
-PostcopyDiscardState *postcopy_discard_send_init(MigrationState *ms,
-                                                 unsigned long offset,
-                                                 const char *name);
-
-/*
- * Called by the bitmap code for each chunk to discard.
- * May send a discard message, may just leave it queued to
- * be sent later.
- * @start,@length: a range of pages in the migration bitmap in the
- *  RAM block passed to postcopy_discard_send_init() (length=1 is one page)
- */
-void postcopy_discard_send_range(MigrationState *ms, PostcopyDiscardState *pds,
-                                 unsigned long start, unsigned long length);
-
-/*
- * Called at the end of each RAMBlock by the bitmap code.
- * Sends any outstanding discard messages, frees the PDS.
- */
-void postcopy_discard_send_finish(MigrationState *ms,
-                                  PostcopyDiscardState *pds);
-
-/*
- * Place a page (from) at (host) efficiently
- *    There are restrictions on how 'from' must be mapped, in general best
- *    to use other postcopy_ routines to allocate.
- * returns 0 on success
- */
-int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from,
-                        size_t pagesize);
-
-/*
- * Place a zero page at (host) atomically
- * returns 0 on success
- */
-int postcopy_place_page_zero(MigrationIncomingState *mis, void *host,
-                             size_t pagesize);
-
-/*
- * Allocate a page of memory that can be mapped at a later point in time
- * using postcopy_place_page
- * Returns: Pointer to allocated page
- */
-void *postcopy_get_tmp_page(MigrationIncomingState *mis);
-
-#endif
index dad3984c077efc1fb2fa597700377eee52ec65e7..f4bf3f1b4e203c6aa6cd9906c4ef8739a1921ec3 100644 (file)
@@ -500,6 +500,19 @@ extern const VMStateInfo vmstate_info_qtailq;
     .offset       = vmstate_offset_array(_state, _field, _type, _num),\
 }
 
+#define VMSTATE_STRUCT_2DARRAY_TEST(_field, _state, _n1, _n2, _test, \
+                                    _version, _vmsd, _type) {        \
+    .name         = (stringify(_field)),                             \
+    .num          = (_n1) * (_n2),                                   \
+    .field_exists = (_test),                                         \
+    .version_id   = (_version),                                      \
+    .vmsd         = &(_vmsd),                                        \
+    .size         = sizeof(_type),                                   \
+    .flags        = VMS_STRUCT | VMS_ARRAY,                          \
+    .offset       = vmstate_offset_2darray(_state, _field, _type,    \
+                                           _n1, _n2),                \
+}
+
 #define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
     .name       = (stringify(_field)),                               \
     .num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \
@@ -747,6 +760,11 @@ extern const VMStateInfo vmstate_info_qtailq;
     VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version,   \
             _vmsd, _type)
 
+#define VMSTATE_STRUCT_2DARRAY(_field, _state, _n1, _n2, _version,    \
+            _vmsd, _type)                                             \
+    VMSTATE_STRUCT_2DARRAY_TEST(_field, _state, _n1, _n2, NULL,       \
+            _version, _vmsd, _type)
+
 #define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) \
     VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _state, NULL, _version, _info, \
             _size)
index 7462228ac1274ed789568ba603b4863b0d47083c..840ad6134cd3d52a6be5dc55fa87237e118a15b6 100644 (file)
@@ -99,7 +99,7 @@ int blk_get_refcnt(BlockBackend *blk);
 void blk_ref(BlockBackend *blk);
 void blk_unref(BlockBackend *blk);
 void blk_remove_all_bs(void);
-const char *blk_name(BlockBackend *blk);
+const char *blk_name(const BlockBackend *blk);
 BlockBackend *blk_by_name(const char *name);
 BlockBackend *blk_next(BlockBackend *blk);
 bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp);
@@ -225,7 +225,7 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
                                       int count, BdrvRequestFlags flags);
 int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
                           int count);
-int blk_truncate(BlockBackend *blk, int64_t offset);
+int blk_truncate(BlockBackend *blk, int64_t offset, Error **errp);
 int blk_pdiscard(BlockBackend *blk, int64_t offset, int count);
 int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
                      int64_t pos, int size);
index 729d186d011c5145ec3ca514ff39169a6a1c5048..ea9f2cb7d6998790d933a94e183776d00a2c9885 100644 (file)
@@ -7,6 +7,14 @@
 #include "qemu/bitmap.h"
 #include "qom/object.h"
 
+#define IAC_EOR 239
+#define IAC_SE 240
+#define IAC_NOP 241
+#define IAC_BREAK 243
+#define IAC_IP 244
+#define IAC_SB 250
+#define IAC 255
+
 /* character device */
 
 typedef enum {
index 16175f7295b403bf7adddf2a776c02ad764e1a01..15656b7c362c279c5ba84711100fb7d4a48fa94a 100644 (file)
@@ -75,11 +75,8 @@ void qemu_remove_exit_notifier(Notifier *notify);
 void qemu_add_machine_init_done_notifier(Notifier *notify);
 void qemu_remove_machine_init_done_notifier(Notifier *notify);
 
-void hmp_savevm(Monitor *mon, const QDict *qdict);
-int save_vmstate(Monitor *mon, const char *name);
+int save_vmstate(const char *name);
 int load_vmstate(const char *name);
-void hmp_delvm(Monitor *mon, const QDict *qdict);
-void hmp_info_snapshots(Monitor *mon, const QDict *qdict);
 
 void qemu_announce_self(void);
 
index f520d7723c04d31c27d9d54c38eb8d013978b723..ce77317e0965662b0738b2438facf11de61f8a2f 100644 (file)
@@ -1052,7 +1052,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
     int i;
 
     for (i = 0; i < 32; i++) {
-        (*regs)[i] = tswapreg(env->gpr[i]);
+        (*regs)[i] = tswapreg(cpu_get_gpr(env, i));
     }
     (*regs)[32] = tswapreg(env->pc);
     (*regs)[33] = tswapreg(cpu_get_sr(env));
index 10a3bb3a123830ddf50503df8b8b12308a1db563..79d621b87232eac567c15e78af9fe4ff4d9622b1 100644 (file)
@@ -2590,17 +2590,17 @@ void cpu_loop(CPUOpenRISCState *env)
         case EXCP_SYSCALL:
             env->pc += 4;   /* 0xc00; */
             ret = do_syscall(env,
-                             env->gpr[11], /* return value       */
-                             env->gpr[3],  /* r3 - r7 are params */
-                             env->gpr[4],
-                             env->gpr[5],
-                             env->gpr[6],
-                             env->gpr[7],
-                             env->gpr[8], 0, 0);
+                             cpu_get_gpr(env, 11), /* return value       */
+                             cpu_get_gpr(env, 3),  /* r3 - r7 are params */
+                             cpu_get_gpr(env, 4),
+                             cpu_get_gpr(env, 5),
+                             cpu_get_gpr(env, 6),
+                             cpu_get_gpr(env, 7),
+                             cpu_get_gpr(env, 8), 0, 0);
             if (ret == -TARGET_ERESTARTSYS) {
                 env->pc -= 4;
             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
-                env->gpr[11] = ret;
+                cpu_set_gpr(env, 11, ret);
             }
             break;
         case EXCP_DPF:
@@ -4765,7 +4765,7 @@ int main(int argc, char **argv, char **envp)
         int i;
 
         for (i = 0; i < 32; i++) {
-            env->gpr[i] = regs->gpr[i];
+            cpu_set_gpr(env, i, regs->gpr[i]);
         }
         env->pc = regs->pc;
         cpu_set_sr(env, regs->sr);
index f283d96a9353ed85b2316e5b1eddd8bab26fd41e..606ad6f69581f829dbaed125cf68c37705ec25df 100644 (file)
 static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
 {
     if (newsp) {
-        env->gpr[1] = newsp;
+        cpu_set_gpr(env, 1, newsp);
     }
-    env->gpr[11] = 0;
+    cpu_set_gpr(env, 11, 0);
 }
 
 static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls)
 {
-    env->gpr[10] = newtls;
+    cpu_set_gpr(env, 10, newtls);
 }
 
 #endif
index 9f2c493f79c1a48772f273f4384f817ea96feed2..95a733e15af4aaa95027075f94e1e1541f7d4cac 100644 (file)
@@ -20,7 +20,7 @@ typedef struct target_sigaltstack {
 
 static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state)
 {
-    return state->gpr[1];
+    return cpu_get_gpr(state, 1);
 }
 
 
index a67db04e1a48c5f354d449c9387af5a6749d0f9e..3d18d1b3ee6069597a9b296de1042626bc1ff3b8 100644 (file)
@@ -4411,7 +4411,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
                              CPUOpenRISCState *regs,
                              unsigned long mask)
 {
-    unsigned long usp = regs->gpr[1];
+    unsigned long usp = cpu_get_gpr(regs, 1);
 
     /* copy the regs. they are first in sc so we can use sc directly */
 
@@ -4436,7 +4436,7 @@ static inline abi_ulong get_sigframe(struct target_sigaction *ka,
                                      CPUOpenRISCState *regs,
                                      size_t frame_size)
 {
-    unsigned long sp = regs->gpr[1];
+    unsigned long sp = cpu_get_gpr(regs, 1);
     int onsigstack = on_sig_stack(sp);
 
     /* redzone */
@@ -4489,7 +4489,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     __put_user(0, &frame->uc.tuc_link);
     __put_user(target_sigaltstack_used.ss_sp,
                &frame->uc.tuc_stack.ss_sp);
-    __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags);
+    __put_user(sas_ss_flags(cpu_get_gpr(env, 1)),
+               &frame->uc.tuc_stack.ss_flags);
     __put_user(target_sigaltstack_used.ss_size,
                &frame->uc.tuc_stack.ss_size);
     setup_sigcontext(&frame->sc, env, set->sig[0]);
@@ -4512,13 +4513,13 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
 
     /* Set up registers for signal handler */
     env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */
-    env->gpr[9] = (unsigned long)return_ip;     /* what we enter LATER */
-    env->gpr[3] = (unsigned long)sig;           /* arg 1: signo */
-    env->gpr[4] = (unsigned long)&frame->info;  /* arg 2: (siginfo_t*) */
-    env->gpr[5] = (unsigned long)&frame->uc;    /* arg 3: ucontext */
+    cpu_set_gpr(env, 9, (unsigned long)return_ip);     /* what we enter LATER */
+    cpu_set_gpr(env, 3, (unsigned long)sig);           /* arg 1: signo */
+    cpu_set_gpr(env, 4, (unsigned long)&frame->info);  /* arg 2: (siginfo_t*) */
+    cpu_set_gpr(env, 5, (unsigned long)&frame->uc);    /* arg 3: ucontext */
 
     /* actually move the usp to reflect the stacked frame */
-    env->gpr[1] = (unsigned long)frame;
+    cpu_set_gpr(env, 1, (unsigned long)frame);
 
     return;
 
index 9157721dfe596e3a4a83a92a80b9ca8fb2b92c7a..aba9089466262e3fd824a08fb82b397696d0a525 100644 (file)
@@ -32,7 +32,7 @@ void exec_start_outgoing_migration(MigrationState *s, const char *command, Error
 
     trace_migration_exec_outgoing(command);
     ioc = QIO_CHANNEL(qio_channel_command_new_spawn(argv,
-                                                    O_WRONLY,
+                                                    O_RDWR,
                                                     errp));
     if (!ioc) {
         return;
@@ -59,7 +59,7 @@ void exec_start_incoming_migration(const char *command, Error **errp)
 
     trace_migration_exec_incoming(command);
     ioc = QIO_CHANNEL(qio_channel_command_new_spawn(argv,
-                                                    O_RDONLY,
+                                                    O_RDWR,
                                                     errp));
     if (!ioc) {
         return;
index 353f2728cf737eeeb750d5be99f8c380bfcf41f2..799952ce99a41ba2e13d9da30616394fc366238e 100644 (file)
@@ -26,7 +26,7 @@
 #include "qemu/sockets.h"
 #include "qemu/rcu.h"
 #include "migration/block.h"
-#include "migration/postcopy-ram.h"
+#include "postcopy-ram.h"
 #include "qemu/thread.h"
 #include "qmp-commands.h"
 #include "trace.h"
index 85fd8d72b3988e00d79e02bcdef0cc40dd175e66..cdadaf65784a424bca22f535de2f3550f5d6aeb3 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "qemu-common.h"
 #include "migration/migration.h"
-#include "migration/postcopy-ram.h"
+#include "postcopy-ram.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/balloon.h"
 #include "qemu/error-report.h"
@@ -33,7 +33,6 @@
 
 struct PostcopyDiscardState {
     const char *ramblock_name;
-    uint64_t offset; /* Bitmap entry for the 1st bit of this RAMBlock */
     uint16_t cur_entry;
     /*
      * Start and length of a discard range (bytes)
@@ -717,14 +716,12 @@ void *postcopy_get_tmp_page(MigrationIncomingState *mis)
  * returns: a new PDS.
  */
 PostcopyDiscardState *postcopy_discard_send_init(MigrationState *ms,
-                                                 unsigned long offset,
                                                  const char *name)
 {
     PostcopyDiscardState *res = g_malloc0(sizeof(PostcopyDiscardState));
 
     if (res) {
         res->ramblock_name = name;
-        res->offset = offset;
     }
 
     return res;
@@ -745,7 +742,7 @@ void postcopy_discard_send_range(MigrationState *ms, PostcopyDiscardState *pds,
 {
     size_t tp_size = qemu_target_page_size();
     /* Convert to byte offsets within the RAM block */
-    pds->start_list[pds->cur_entry] = (start - pds->offset) * tp_size;
+    pds->start_list[pds->cur_entry] = start  * tp_size;
     pds->length_list[pds->cur_entry] = length * tp_size;
     trace_postcopy_discard_send_range(pds->ramblock_name, start, length);
     pds->cur_entry++;
diff --git a/migration/postcopy-ram.h b/migration/postcopy-ram.h
new file mode 100644 (file)
index 0000000..4c25f03
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Postcopy migration for RAM
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Dave Gilbert  <dgilbert@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+#ifndef QEMU_POSTCOPY_RAM_H
+#define QEMU_POSTCOPY_RAM_H
+
+/* Return true if the host supports everything we need to do postcopy-ram */
+bool postcopy_ram_supported_by_host(void);
+
+/*
+ * Make all of RAM sensitive to accesses to areas that haven't yet been written
+ * and wire up anything necessary to deal with it.
+ */
+int postcopy_ram_enable_notify(MigrationIncomingState *mis);
+
+/*
+ * Initialise postcopy-ram, setting the RAM to a state where we can go into
+ * postcopy later; must be called prior to any precopy.
+ * called from ram.c's similarly named ram_postcopy_incoming_init
+ */
+int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages);
+
+/*
+ * At the end of a migration where postcopy_ram_incoming_init was called.
+ */
+int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis);
+
+/*
+ * Userfault requires us to mark RAM as NOHUGEPAGE prior to discard
+ * however leaving it until after precopy means that most of the precopy
+ * data is still THPd
+ */
+int postcopy_ram_prepare_discard(MigrationIncomingState *mis);
+
+/*
+ * Called at the start of each RAMBlock by the bitmap code.
+ * Returns a new PDS
+ */
+PostcopyDiscardState *postcopy_discard_send_init(MigrationState *ms,
+                                                 const char *name);
+
+/*
+ * Called by the bitmap code for each chunk to discard.
+ * May send a discard message, may just leave it queued to
+ * be sent later.
+ * @start,@length: a range of pages in the migration bitmap in the
+ *  RAM block passed to postcopy_discard_send_init() (length=1 is one page)
+ */
+void postcopy_discard_send_range(MigrationState *ms, PostcopyDiscardState *pds,
+                                 unsigned long start, unsigned long length);
+
+/*
+ * Called at the end of each RAMBlock by the bitmap code.
+ * Sends any outstanding discard messages, frees the PDS.
+ */
+void postcopy_discard_send_finish(MigrationState *ms,
+                                  PostcopyDiscardState *pds);
+
+/*
+ * Place a page (from) at (host) efficiently
+ *    There are restrictions on how 'from' must be mapped, in general best
+ *    to use other postcopy_ routines to allocate.
+ * returns 0 on success
+ */
+int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from,
+                        size_t pagesize);
+
+/*
+ * Place a zero page at (host) atomically
+ * returns 0 on success
+ */
+int postcopy_place_page_zero(MigrationIncomingState *mis, void *host,
+                             size_t pagesize);
+
+/*
+ * Allocate a page of memory that can be mapped at a later point in time
+ * using postcopy_place_page
+ * Returns: Pointer to allocated page
+ */
+void *postcopy_get_tmp_page(MigrationIncomingState *mis);
+
+#endif
index f48664ec624b8f701518d3cd35b72ffb4ad7e1e1..293d27ce835e1bb600f0d654a93d69dbdbb2f9d0 100644 (file)
@@ -36,7 +36,7 @@
 #include "qemu/timer.h"
 #include "qemu/main-loop.h"
 #include "migration/migration.h"
-#include "migration/postcopy-ram.h"
+#include "postcopy-ram.h"
 #include "exec/address-spaces.h"
 #include "migration/page_cache.h"
 #include "qemu/error-report.h"
@@ -138,19 +138,6 @@ out:
     return ret;
 }
 
-struct RAMBitmap {
-    struct rcu_head rcu;
-    /* Main migration bitmap */
-    unsigned long *bmap;
-    /* bitmap of pages that haven't been sent even once
-     * only maintained and used in postcopy at the moment
-     * where it's used to send the dirtymap at the start
-     * of the postcopy phase
-     */
-    unsigned long *unsentmap;
-};
-typedef struct RAMBitmap RAMBitmap;
-
 /*
  * An outstanding page request, on the source, having been received
  * and queued
@@ -220,8 +207,6 @@ struct RAMState {
     uint64_t postcopy_requests;
     /* protects modification of the bitmap */
     QemuMutex bitmap_mutex;
-    /* Ram Bitmap protected by RCU */
-    RAMBitmap *ram_bitmap;
     /* The RAMBlock used in the last src_page_requests */
     RAMBlock *last_req_rb;
     /* Queue of outstanding page requests from the destination */
@@ -614,22 +599,17 @@ static inline
 unsigned long migration_bitmap_find_dirty(RAMState *rs, RAMBlock *rb,
                                           unsigned long start)
 {
-    unsigned long base = rb->offset >> TARGET_PAGE_BITS;
-    unsigned long nr = base + start;
-    uint64_t rb_size = rb->used_length;
-    unsigned long size = base + (rb_size >> TARGET_PAGE_BITS);
-    unsigned long *bitmap;
-
+    unsigned long size = rb->used_length >> TARGET_PAGE_BITS;
+    unsigned long *bitmap = rb->bmap;
     unsigned long next;
 
-    bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
-    if (rs->ram_bulk_stage && nr > base) {
-        next = nr + 1;
+    if (rs->ram_bulk_stage && start > 0) {
+        next = start + 1;
     } else {
-        next = find_next_bit(bitmap, size, nr);
+        next = find_next_bit(bitmap, size, start);
     }
 
-    return next - base;
+    return next;
 }
 
 static inline bool migration_bitmap_clear_dirty(RAMState *rs,
@@ -637,10 +617,8 @@ static inline bool migration_bitmap_clear_dirty(RAMState *rs,
                                                 unsigned long page)
 {
     bool ret;
-    unsigned long *bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
-    unsigned long nr = (rb->offset >> TARGET_PAGE_BITS) + page;
 
-    ret = test_and_clear_bit(nr, bitmap);
+    ret = test_and_clear_bit(page, rb->bmap);
 
     if (ret) {
         rs->migration_dirty_pages--;
@@ -651,10 +629,8 @@ static inline bool migration_bitmap_clear_dirty(RAMState *rs,
 static void migration_bitmap_sync_range(RAMState *rs, RAMBlock *rb,
                                         ram_addr_t start, ram_addr_t length)
 {
-    unsigned long *bitmap;
-    bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
     rs->migration_dirty_pages +=
-        cpu_physical_memory_sync_dirty_bitmap(bitmap, rb, start, length,
+        cpu_physical_memory_sync_dirty_bitmap(rb, start, length,
                                               &rs->num_dirty_pages_period);
 }
 
@@ -812,6 +788,7 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss, bool last_stage)
     ram_addr_t offset = pss->page << TARGET_PAGE_BITS;
 
     p = block->host + offset;
+    trace_ram_save_page(block->idstr, (uint64_t)offset, p);
 
     /* In doubt sent page as normal */
     bytes_xmit = 0;
@@ -1153,17 +1130,13 @@ static bool get_queued_page(RAMState *rs, PageSearchStatus *pss)
          * search already sent it.
          */
         if (block) {
-            unsigned long *bitmap;
             unsigned long page;
 
-            bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
-            page = (block->offset + offset) >> TARGET_PAGE_BITS;
-            dirty = test_bit(page, bitmap);
+            page = offset >> TARGET_PAGE_BITS;
+            dirty = test_bit(page, block->bmap);
             if (!dirty) {
                 trace_get_queued_page_not_dirty(block->idstr, (uint64_t)offset,
-                    page,
-                    test_bit(page,
-                             atomic_rcu_read(&rs->ram_bitmap)->unsentmap));
+                       page, test_bit(page, block->unsentmap));
             } else {
                 trace_get_queued_page(block->idstr, (uint64_t)offset, page);
             }
@@ -1301,16 +1274,13 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss,
 
     /* Check the pages is dirty and if it is send it */
     if (migration_bitmap_clear_dirty(rs, pss->block, pss->page)) {
-        unsigned long *unsentmap;
         /*
          * If xbzrle is on, stop using the data compression after first
          * round of migration even if compression is enabled. In theory,
          * xbzrle can do better than compression.
          */
-        unsigned long page =
-            (pss->block->offset >> TARGET_PAGE_BITS) + pss->page;
-        if (migrate_use_compression()
-            && (rs->ram_bulk_stage || !migrate_use_xbzrle())) {
+        if (migrate_use_compression() &&
+            (rs->ram_bulk_stage || !migrate_use_xbzrle())) {
             res = ram_save_compressed_page(rs, pss, last_stage);
         } else {
             res = ram_save_page(rs, pss, last_stage);
@@ -1319,9 +1289,8 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss,
         if (res < 0) {
             return res;
         }
-        unsentmap = atomic_rcu_read(&rs->ram_bitmap)->unsentmap;
-        if (unsentmap) {
-            clear_bit(page, unsentmap);
+        if (pss->block->unsentmap) {
+            clear_bit(pss->page, pss->block->unsentmap);
         }
     }
 
@@ -1451,25 +1420,20 @@ void free_xbzrle_decoded_buf(void)
     xbzrle_decoded_buf = NULL;
 }
 
-static void migration_bitmap_free(RAMBitmap *bmap)
-{
-    g_free(bmap->bmap);
-    g_free(bmap->unsentmap);
-    g_free(bmap);
-}
-
 static void ram_migration_cleanup(void *opaque)
 {
-    RAMState *rs = opaque;
+    RAMBlock *block;
 
     /* caller have hold iothread lock or is in a bh, so there is
      * no writing race against this migration_bitmap
      */
-    RAMBitmap *bitmap = rs->ram_bitmap;
-    atomic_rcu_set(&rs->ram_bitmap, NULL);
-    if (bitmap) {
-        memory_global_dirty_log_stop();
-        call_rcu(bitmap, migration_bitmap_free, rcu);
+    memory_global_dirty_log_stop();
+
+    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+        g_free(block->bmap);
+        block->bmap = NULL;
+        g_free(block->unsentmap);
+        block->unsentmap = NULL;
     }
 
     XBZRLE_cache_lock();
@@ -1501,27 +1465,22 @@ static void ram_state_reset(RAMState *rs)
  * of; it won't bother printing lines that are all this value.
  * If 'todump' is null the migration bitmap is dumped.
  */
-void ram_debug_dump_bitmap(unsigned long *todump, bool expected)
+void ram_debug_dump_bitmap(unsigned long *todump, bool expected,
+                           unsigned long pages)
 {
-    unsigned long ram_pages = last_ram_page();
-    RAMState *rs = &ram_state;
     int64_t cur;
     int64_t linelen = 128;
     char linebuf[129];
 
-    if (!todump) {
-        todump = atomic_rcu_read(&rs->ram_bitmap)->bmap;
-    }
-
-    for (cur = 0; cur < ram_pages; cur += linelen) {
+    for (cur = 0; cur < pages; cur += linelen) {
         int64_t curb;
         bool found = false;
         /*
          * Last line; catch the case where the line length
          * is longer than remaining ram
          */
-        if (cur + linelen > ram_pages) {
-            linelen = ram_pages - cur;
+        if (cur + linelen > pages) {
+            linelen = pages - cur;
         }
         for (curb = 0; curb < linelen; curb++) {
             bool thisbit = test_bit(cur + curb, todump);
@@ -1539,14 +1498,12 @@ void ram_debug_dump_bitmap(unsigned long *todump, bool expected)
 
 void ram_postcopy_migrated_memory_release(MigrationState *ms)
 {
-    RAMState *rs = &ram_state;
     struct RAMBlock *block;
-    unsigned long *bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
 
     QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
-        unsigned long first = block->offset >> TARGET_PAGE_BITS;
-        unsigned long range = first + (block->used_length >> TARGET_PAGE_BITS);
-        unsigned long run_start = find_next_zero_bit(bitmap, range, first);
+        unsigned long *bitmap = block->bmap;
+        unsigned long range = block->used_length >> TARGET_PAGE_BITS;
+        unsigned long run_start = find_next_zero_bit(bitmap, range, 0);
 
         while (run_start < range) {
             unsigned long run_end = find_next_bit(bitmap, range, run_start + 1);
@@ -1573,16 +1530,13 @@ void ram_postcopy_migrated_memory_release(MigrationState *ms)
  */
 static int postcopy_send_discard_bm_ram(MigrationState *ms,
                                         PostcopyDiscardState *pds,
-                                        unsigned long start,
-                                        unsigned long length)
+                                        RAMBlock *block)
 {
-    RAMState *rs = &ram_state;
-    unsigned long end = start + length; /* one after the end */
+    unsigned long end = block->used_length >> TARGET_PAGE_BITS;
     unsigned long current;
-    unsigned long *unsentmap;
+    unsigned long *unsentmap = block->unsentmap;
 
-    unsentmap = atomic_rcu_read(&rs->ram_bitmap)->unsentmap;
-    for (current = start; current < end; ) {
+    for (current = 0; current < end; ) {
         unsigned long one = find_next_bit(unsentmap, end, current);
 
         if (one <= end) {
@@ -1625,18 +1579,15 @@ static int postcopy_each_ram_send_discard(MigrationState *ms)
     int ret;
 
     QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
-        unsigned long first = block->offset >> TARGET_PAGE_BITS;
-        PostcopyDiscardState *pds = postcopy_discard_send_init(ms,
-                                                               first,
-                                                               block->idstr);
+        PostcopyDiscardState *pds =
+            postcopy_discard_send_init(ms, block->idstr);
 
         /*
          * Postcopy sends chunks of bitmap over the wire, but it
          * just needs indexes at this point, avoids it having
          * target page specific code.
          */
-        ret = postcopy_send_discard_bm_ram(ms, pds, first,
-                                    block->used_length >> TARGET_PAGE_BITS);
+        ret = postcopy_send_discard_bm_ram(ms, pds, block);
         postcopy_discard_send_finish(ms, pds);
         if (ret) {
             return ret;
@@ -1667,12 +1618,10 @@ static void postcopy_chunk_hostpages_pass(MigrationState *ms, bool unsent_pass,
                                           PostcopyDiscardState *pds)
 {
     RAMState *rs = &ram_state;
-    unsigned long *bitmap;
-    unsigned long *unsentmap;
+    unsigned long *bitmap = block->bmap;
+    unsigned long *unsentmap = block->unsentmap;
     unsigned int host_ratio = block->page_size / TARGET_PAGE_SIZE;
-    unsigned long first = block->offset >> TARGET_PAGE_BITS;
-    unsigned long len = block->used_length >> TARGET_PAGE_BITS;
-    unsigned long last = first + (len - 1);
+    unsigned long pages = block->used_length >> TARGET_PAGE_BITS;
     unsigned long run_start;
 
     if (block->page_size == TARGET_PAGE_SIZE) {
@@ -1680,18 +1629,15 @@ static void postcopy_chunk_hostpages_pass(MigrationState *ms, bool unsent_pass,
         return;
     }
 
-    bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
-    unsentmap = atomic_rcu_read(&rs->ram_bitmap)->unsentmap;
-
     if (unsent_pass) {
         /* Find a sent page */
-        run_start = find_next_zero_bit(unsentmap, last + 1, first);
+        run_start = find_next_zero_bit(unsentmap, pages, 0);
     } else {
         /* Find a dirty page */
-        run_start = find_next_bit(bitmap, last + 1, first);
+        run_start = find_next_bit(bitmap, pages, 0);
     }
 
-    while (run_start <= last) {
+    while (run_start < pages) {
         bool do_fixup = false;
         unsigned long fixup_start_addr;
         unsigned long host_offset;
@@ -1711,9 +1657,9 @@ static void postcopy_chunk_hostpages_pass(MigrationState *ms, bool unsent_pass,
             /* Find the end of this run */
             unsigned long run_end;
             if (unsent_pass) {
-                run_end = find_next_bit(unsentmap, last + 1, run_start + 1);
+                run_end = find_next_bit(unsentmap, pages, run_start + 1);
             } else {
-                run_end = find_next_zero_bit(bitmap, last + 1, run_start + 1);
+                run_end = find_next_zero_bit(bitmap, pages, run_start + 1);
             }
             /*
              * If the end isn't at the start of a host page, then the
@@ -1770,11 +1716,10 @@ static void postcopy_chunk_hostpages_pass(MigrationState *ms, bool unsent_pass,
 
         if (unsent_pass) {
             /* Find the next sent page for the next iteration */
-            run_start = find_next_zero_bit(unsentmap, last + 1,
-                                           run_start);
+            run_start = find_next_zero_bit(unsentmap, pages, run_start);
         } else {
             /* Find the next dirty page for the next iteration */
-            run_start = find_next_bit(bitmap, last + 1, run_start);
+            run_start = find_next_bit(bitmap, pages, run_start);
         }
     }
 }
@@ -1791,34 +1736,22 @@ static void postcopy_chunk_hostpages_pass(MigrationState *ms, bool unsent_pass,
  * Returns zero on success
  *
  * @ms: current migration state
+ * @block: block we want to work with
  */
-static int postcopy_chunk_hostpages(MigrationState *ms)
+static int postcopy_chunk_hostpages(MigrationState *ms, RAMBlock *block)
 {
-    RAMState *rs = &ram_state;
-    struct RAMBlock *block;
-
-    /* Easiest way to make sure we don't resume in the middle of a host-page */
-    rs->last_seen_block = NULL;
-    rs->last_sent_block = NULL;
-    rs->last_page = 0;
-
-    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
-        unsigned long first = block->offset >> TARGET_PAGE_BITS;
-
-        PostcopyDiscardState *pds =
-                         postcopy_discard_send_init(ms, first, block->idstr);
-
-        /* First pass: Discard all partially sent host pages */
-        postcopy_chunk_hostpages_pass(ms, true, block, pds);
-        /*
-         * Second pass: Ensure that all partially dirty host pages are made
-         * fully dirty.
-         */
-        postcopy_chunk_hostpages_pass(ms, false, block, pds);
+    PostcopyDiscardState *pds =
+        postcopy_discard_send_init(ms, block->idstr);
 
-        postcopy_discard_send_finish(ms, pds);
-    } /* ram_list loop */
+    /* First pass: Discard all partially sent host pages */
+    postcopy_chunk_hostpages_pass(ms, true, block, pds);
+    /*
+     * Second pass: Ensure that all partially dirty host pages are made
+     * fully dirty.
+     */
+    postcopy_chunk_hostpages_pass(ms, false, block, pds);
 
+    postcopy_discard_send_finish(ms, pds);
     return 0;
 }
 
@@ -1840,43 +1773,49 @@ static int postcopy_chunk_hostpages(MigrationState *ms)
 int ram_postcopy_send_discard_bitmap(MigrationState *ms)
 {
     RAMState *rs = &ram_state;
+    RAMBlock *block;
     int ret;
-    unsigned long *bitmap, *unsentmap;
 
     rcu_read_lock();
 
     /* This should be our last sync, the src is now paused */
     migration_bitmap_sync(rs);
 
-    unsentmap = atomic_rcu_read(&rs->ram_bitmap)->unsentmap;
-    if (!unsentmap) {
-        /* We don't have a safe way to resize the sentmap, so
-         * if the bitmap was resized it will be NULL at this
-         * point.
-         */
-        error_report("migration ram resized during precopy phase");
-        rcu_read_unlock();
-        return -EINVAL;
-    }
-
-    /* Deal with TPS != HPS and huge pages */
-    ret = postcopy_chunk_hostpages(ms);
-    if (ret) {
-        rcu_read_unlock();
-        return ret;
-    }
-
-    /*
-     * Update the unsentmap to be unsentmap = unsentmap | dirty
-     */
-    bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
-    bitmap_or(unsentmap, unsentmap, bitmap, last_ram_page());
+    /* Easiest way to make sure we don't resume in the middle of a host-page */
+    rs->last_seen_block = NULL;
+    rs->last_sent_block = NULL;
+    rs->last_page = 0;
 
+    QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+        unsigned long pages = block->used_length >> TARGET_PAGE_BITS;
+        unsigned long *bitmap = block->bmap;
+        unsigned long *unsentmap = block->unsentmap;
+
+        if (!unsentmap) {
+            /* We don't have a safe way to resize the sentmap, so
+             * if the bitmap was resized it will be NULL at this
+             * point.
+             */
+            error_report("migration ram resized during precopy phase");
+            rcu_read_unlock();
+            return -EINVAL;
+        }
+        /* Deal with TPS != HPS and huge pages */
+        ret = postcopy_chunk_hostpages(ms, block);
+        if (ret) {
+            rcu_read_unlock();
+            return ret;
+        }
 
-    trace_ram_postcopy_send_discard_bitmap();
+        /*
+         * Update the unsentmap to be unsentmap = unsentmap | dirty
+         */
+        bitmap_or(unsentmap, unsentmap, bitmap, pages);
 #ifdef DEBUG_POSTCOPY
-    ram_debug_dump_bitmap(unsentmap, true);
+        ram_debug_dump_bitmap(unsentmap, true, pages);
 #endif
+    }
+    trace_ram_postcopy_send_discard_bitmap();
 
     ret = postcopy_each_ram_send_discard(ms);
     rcu_read_unlock();
@@ -1918,8 +1857,6 @@ err:
 
 static int ram_state_init(RAMState *rs)
 {
-    unsigned long ram_bitmap_pages;
-
     memset(rs, 0, sizeof(*rs));
     qemu_mutex_init(&rs->bitmap_mutex);
     qemu_mutex_init(&rs->src_page_req_mutex);
@@ -1961,16 +1898,19 @@ static int ram_state_init(RAMState *rs)
     rcu_read_lock();
     ram_state_reset(rs);
 
-    rs->ram_bitmap = g_new0(RAMBitmap, 1);
     /* Skip setting bitmap if there is no RAM */
     if (ram_bytes_total()) {
-        ram_bitmap_pages = last_ram_page();
-        rs->ram_bitmap->bmap = bitmap_new(ram_bitmap_pages);
-        bitmap_set(rs->ram_bitmap->bmap, 0, ram_bitmap_pages);
+        RAMBlock *block;
 
-        if (migrate_postcopy_ram()) {
-            rs->ram_bitmap->unsentmap = bitmap_new(ram_bitmap_pages);
-            bitmap_set(rs->ram_bitmap->unsentmap, 0, ram_bitmap_pages);
+        QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+            unsigned long pages = block->max_length >> TARGET_PAGE_BITS;
+
+            block->bmap = bitmap_new(pages);
+            bitmap_set(block->bmap, 0, pages);
+            if (migrate_postcopy_ram()) {
+                block->unsentmap = bitmap_new(pages);
+                bitmap_set(block->unsentmap, 0, pages);
+            }
         }
     }
 
@@ -2611,6 +2551,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
                 ret = -EINVAL;
                 break;
             }
+            trace_ram_load_loop(block->idstr, (uint64_t)addr, flags, host);
         }
 
         switch (flags & ~RAM_SAVE_FLAG_CONTINUE) {
index 03ae1bdeb4c9c587ff399d4f5513a7216bea7171..352a8f23b5d4f9414c789443a9a40f7711f7a71e 100644 (file)
 #include "hw/qdev.h"
 #include "hw/xen/xen.h"
 #include "net/net.h"
-#include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
 #include "qemu/timer.h"
-#include "audio/audio.h"
 #include "migration/migration.h"
-#include "migration/postcopy-ram.h"
+#include "postcopy-ram.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/error-report.h"
-#include "qemu/sockets.h"
 #include "qemu/queue.h"
 #include "sysemu/cpus.h"
 #include "exec/memory.h"
@@ -50,7 +47,6 @@
 #include "qemu/bitops.h"
 #include "qemu/iov.h"
 #include "block/snapshot.h"
-#include "block/qapi.h"
 #include "qemu/cutils.h"
 #include "io/channel-buffer.h"
 #include "io/channel-file.h"
@@ -1622,6 +1618,14 @@ static void loadvm_postcopy_handle_run_bh(void *opaque)
         error_report_err(local_err);
     }
 
+    /* If we get an error here, just don't restart the VM yet. */
+    blk_resume_after_migration(&local_err);
+    if (local_err) {
+        error_free(local_err);
+        local_err = NULL;
+        autostart = false;
+    }
+
     trace_loadvm_postcopy_handle_run_cpu_sync();
     cpu_synchronize_all_post_init();
 
@@ -2070,7 +2074,7 @@ int qemu_loadvm_state(QEMUFile *f)
     return ret;
 }
 
-int save_vmstate(Monitor *mon, const char *name)
+int save_vmstate(const char *name)
 {
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@@ -2084,8 +2088,8 @@ int save_vmstate(Monitor *mon, const char *name)
     AioContext *aio_context;
 
     if (!bdrv_all_can_snapshot(&bs)) {
-        monitor_printf(mon, "Device '%s' is writable but does not "
-                       "support snapshots.\n", bdrv_get_device_name(bs));
+        error_report("Device '%s' is writable but does not support snapshots",
+                     bdrv_get_device_name(bs));
         return ret;
     }
 
@@ -2102,7 +2106,7 @@ int save_vmstate(Monitor *mon, const char *name)
 
     bs = bdrv_all_find_vmstate_bs();
     if (bs == NULL) {
-        monitor_printf(mon, "No block device can accept snapshots\n");
+        error_report("No block device can accept snapshots");
         return ret;
     }
     aio_context = bdrv_get_aio_context(bs);
@@ -2111,7 +2115,7 @@ int save_vmstate(Monitor *mon, const char *name)
 
     ret = global_state_store();
     if (ret) {
-        monitor_printf(mon, "Error saving global state\n");
+        error_report("Error saving global state");
         return ret;
     }
     vm_stop(RUN_STATE_SAVE_VM);
@@ -2143,7 +2147,7 @@ int save_vmstate(Monitor *mon, const char *name)
     /* save the VM state */
     f = qemu_fopen_bdrv(bs, 1);
     if (!f) {
-        monitor_printf(mon, "Could not open VM state file\n");
+        error_report("Could not open VM state file");
         goto the_end;
     }
     ret = qemu_savevm_state(f, &local_err);
@@ -2156,8 +2160,8 @@ int save_vmstate(Monitor *mon, const char *name)
 
     ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs);
     if (ret < 0) {
-        monitor_printf(mon, "Error while creating snapshot on '%s'\n",
-                       bdrv_get_device_name(bs));
+        error_report("Error while creating snapshot on '%s'",
+                     bdrv_get_device_name(bs));
         goto the_end;
     }
 
@@ -2171,11 +2175,6 @@ int save_vmstate(Monitor *mon, const char *name)
     return ret;
 }
 
-void hmp_savevm(Monitor *mon, const QDict *qdict)
-{
-    save_vmstate(mon, qdict_get_try_str(qdict, "name"));
-}
-
 void qmp_xen_save_devices_state(const char *filename, Error **errp)
 {
     QEMUFile *f;
@@ -2245,7 +2244,7 @@ int load_vmstate(const char *name)
     MigrationIncomingState *mis = migration_incoming_get_current();
 
     if (!bdrv_all_can_snapshot(&bs)) {
-        error_report("Device '%s' is writable but does not support snapshots.",
+        error_report("Device '%s' is writable but does not support snapshots",
                      bdrv_get_device_name(bs));
         return -ENOTSUP;
     }
@@ -2309,162 +2308,6 @@ int load_vmstate(const char *name)
     return 0;
 }
 
-void hmp_delvm(Monitor *mon, const QDict *qdict)
-{
-    BlockDriverState *bs;
-    Error *err;
-    const char *name = qdict_get_str(qdict, "name");
-
-    if (bdrv_all_delete_snapshot(name, &bs, &err) < 0) {
-        error_reportf_err(err,
-                          "Error while deleting snapshot on device '%s': ",
-                          bdrv_get_device_name(bs));
-    }
-}
-
-void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
-{
-    BlockDriverState *bs, *bs1;
-    BdrvNextIterator it1;
-    QEMUSnapshotInfo *sn_tab, *sn;
-    bool no_snapshot = true;
-    int nb_sns, i;
-    int total;
-    int *global_snapshots;
-    AioContext *aio_context;
-
-    typedef struct SnapshotEntry {
-        QEMUSnapshotInfo sn;
-        QTAILQ_ENTRY(SnapshotEntry) next;
-    } SnapshotEntry;
-
-    typedef struct ImageEntry {
-        const char *imagename;
-        QTAILQ_ENTRY(ImageEntry) next;
-        QTAILQ_HEAD(, SnapshotEntry) snapshots;
-    } ImageEntry;
-
-    QTAILQ_HEAD(, ImageEntry) image_list =
-        QTAILQ_HEAD_INITIALIZER(image_list);
-
-    ImageEntry *image_entry, *next_ie;
-    SnapshotEntry *snapshot_entry;
-
-    bs = bdrv_all_find_vmstate_bs();
-    if (!bs) {
-        monitor_printf(mon, "No available block device supports snapshots\n");
-        return;
-    }
-    aio_context = bdrv_get_aio_context(bs);
-
-    aio_context_acquire(aio_context);
-    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
-    aio_context_release(aio_context);
-
-    if (nb_sns < 0) {
-        monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
-        return;
-    }
-
-    for (bs1 = bdrv_first(&it1); bs1; bs1 = bdrv_next(&it1)) {
-        int bs1_nb_sns = 0;
-        ImageEntry *ie;
-        SnapshotEntry *se;
-        AioContext *ctx = bdrv_get_aio_context(bs1);
-
-        aio_context_acquire(ctx);
-        if (bdrv_can_snapshot(bs1)) {
-            sn = NULL;
-            bs1_nb_sns = bdrv_snapshot_list(bs1, &sn);
-            if (bs1_nb_sns > 0) {
-                no_snapshot = false;
-                ie = g_new0(ImageEntry, 1);
-                ie->imagename = bdrv_get_device_name(bs1);
-                QTAILQ_INIT(&ie->snapshots);
-                QTAILQ_INSERT_TAIL(&image_list, ie, next);
-                for (i = 0; i < bs1_nb_sns; i++) {
-                    se = g_new0(SnapshotEntry, 1);
-                    se->sn = sn[i];
-                    QTAILQ_INSERT_TAIL(&ie->snapshots, se, next);
-                }
-            }
-            g_free(sn);
-        }
-        aio_context_release(ctx);
-    }
-
-    if (no_snapshot) {
-        monitor_printf(mon, "There is no snapshot available.\n");
-        return;
-    }
-
-    global_snapshots = g_new0(int, nb_sns);
-    total = 0;
-    for (i = 0; i < nb_sns; i++) {
-        SnapshotEntry *next_sn;
-        if (bdrv_all_find_snapshot(sn_tab[i].name, &bs1) == 0) {
-            global_snapshots[total] = i;
-            total++;
-            QTAILQ_FOREACH(image_entry, &image_list, next) {
-                QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots,
-                                    next, next_sn) {
-                    if (!strcmp(sn_tab[i].name, snapshot_entry->sn.name)) {
-                        QTAILQ_REMOVE(&image_entry->snapshots, snapshot_entry,
-                                      next);
-                        g_free(snapshot_entry);
-                    }
-                }
-            }
-        }
-    }
-
-    monitor_printf(mon, "List of snapshots present on all disks:\n");
-
-    if (total > 0) {
-        bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, NULL);
-        monitor_printf(mon, "\n");
-        for (i = 0; i < total; i++) {
-            sn = &sn_tab[global_snapshots[i]];
-            /* The ID is not guaranteed to be the same on all images, so
-             * overwrite it.
-             */
-            pstrcpy(sn->id_str, sizeof(sn->id_str), "--");
-            bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, sn);
-            monitor_printf(mon, "\n");
-        }
-    } else {
-        monitor_printf(mon, "None\n");
-    }
-
-    QTAILQ_FOREACH(image_entry, &image_list, next) {
-        if (QTAILQ_EMPTY(&image_entry->snapshots)) {
-            continue;
-        }
-        monitor_printf(mon,
-                       "\nList of partial (non-loadable) snapshots on '%s':\n",
-                       image_entry->imagename);
-        bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, NULL);
-        monitor_printf(mon, "\n");
-        QTAILQ_FOREACH(snapshot_entry, &image_entry->snapshots, next) {
-            bdrv_snapshot_dump((fprintf_function)monitor_printf, mon,
-                               &snapshot_entry->sn);
-            monitor_printf(mon, "\n");
-        }
-    }
-
-    QTAILQ_FOREACH_SAFE(image_entry, &image_list, next, next_ie) {
-        SnapshotEntry *next_sn;
-        QTAILQ_FOREACH_SAFE(snapshot_entry, &image_entry->snapshots, next,
-                            next_sn) {
-            g_free(snapshot_entry);
-        }
-        g_free(image_entry);
-    }
-    g_free(sn_tab);
-    g_free(global_snapshots);
-
-}
-
 void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
 {
     qemu_ram_set_idstr(mr->ram_block,
index 13966f1d260543a53a402194c1a27385632e7a29..dc88812048e43cb21302907794ed9855357d27c8 100644 (file)
@@ -79,7 +79,6 @@ static void socket_outgoing_migration(QIOTask *task,
 
     if (qio_task_propagate_error(task, &err)) {
         trace_migration_socket_outgoing_error(error_get_pretty(err));
-        data->s->to_dst_file = NULL;
         migrate_fd_error(data->s, err);
         error_free(err);
     } else {
index 45bec44ca4fac5eefbe875f1b15d8971045a47c4..a33ecb767e6fa3e719c655d2e4832aac06254733 100644 (file)
@@ -116,7 +116,6 @@ static void migration_tls_outgoing_handshake(QIOTask *task,
 
     if (qio_task_propagate_error(task, &err)) {
         trace_migration_tls_outgoing_handshake_error(error_get_pretty(err));
-        s->to_dst_file = NULL;
         migrate_fd_error(s, err);
         error_free(err);
     } else {
index b8f01a218c8560c3fd10b8f1bc737de526331784..5b8ccf301c5fb57b3080622c4fdfd4d5f31516a0 100644 (file)
@@ -69,8 +69,10 @@ migration_bitmap_sync_start(void) ""
 migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64
 migration_throttle(void) ""
 ram_discard_range(const char *rbname, uint64_t start, size_t len) "%s: start: %" PRIx64 " %zx"
+ram_load_loop(const char *rbname, uint64_t addr, int flags, void *host) "%s: addr: %" PRIx64 " flags: %x host: %p"
 ram_load_postcopy_loop(uint64_t addr, int flags) "@%" PRIx64 " %x"
 ram_postcopy_send_discard_bitmap(void) ""
+ram_save_page(const char *rbname, uint64_t offset, void *host) "%s: offset: %" PRIx64 " host: %p"
 ram_save_queue_pages(const char *rbname, size_t start, size_t len) "%s: start: %zx len: %zx"
 
 # migration/migration.c
index 62c9f81e8e0092d04a34a44ab6f85fe2119f7228..ce1102944b7e78dc32fb0217a81cc1b3bf37e85b 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -37,7 +37,6 @@
 #include "net/slirp.h"
 #include "sysemu/char.h"
 #include "ui/qemu-spice.h"
-#include "sysemu/sysemu.h"
 #include "sysemu/numa.h"
 #include "monitor/monitor.h"
 #include "qemu/config-file.h"
@@ -1954,18 +1953,6 @@ void qmp_closefd(const char *fdname, Error **errp)
     error_setg(errp, QERR_FD_NOT_FOUND, fdname);
 }
 
-static void hmp_loadvm(Monitor *mon, const QDict *qdict)
-{
-    int saved_vm_running  = runstate_is_running();
-    const char *name = qdict_get_str(qdict, "name");
-
-    vm_stop(RUN_STATE_RESTORE_VM);
-
-    if (load_vmstate(name) == 0 && saved_vm_running) {
-        vm_start();
-    }
-}
-
 int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
 {
     mon_fd_t *monfd;
index 2a4adfa654844040dbc84e90a9c2e0af56fdb9fa..0b01d49495c607b67d3f1b2359395534631deb88 100644 (file)
Binary files a/pc-bios/s390-ccw.img and b/pc-bios/s390-ccw.img differ
index 0339c247898c50629018e51c6a26102fe2b1ed38..79a46b67356ff4a61dd77ac514da9656a671f950 100644 (file)
@@ -9,7 +9,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
 
 .PHONY : all clean build-all
 
-OBJECTS = start.o main.o bootmap.o sclp-ascii.o virtio.o virtio-scsi.o
+OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o
 QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
 QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
 QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing
index b21c877b53570e0c2363d2e85770a166dbb9f212..523fa78c5fa7bec0106e13be4bb5ddeb5140ba45 100644 (file)
@@ -183,15 +183,21 @@ static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address)
 static void run_eckd_boot_script(block_number_t mbr_block_nr)
 {
     int i;
+    unsigned int loadparm = get_loadparm_index();
     block_number_t block_nr;
     uint64_t address;
-    ScsiMbr *scsi_mbr = (void *)sec;
+    ScsiMbr *bte = (void *)sec; /* Eckd bootmap table entry */
     BootMapScript *bms = (void *)sec;
 
+    debug_print_int("loadparm", loadparm);
+    IPL_assert(loadparm < 31, "loadparm value greater than"
+               " maximum number of boot entries allowed");
+
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(mbr_block_nr, sec, "Cannot read MBR");
 
-    block_nr = eckd_block_num((void *)&(scsi_mbr->blockptr));
+    block_nr = eckd_block_num((void *)&(bte->blockptr[loadparm]));
+    IPL_assert(block_nr != -1, "No Boot Map");
 
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(block_nr, sec, "Cannot read Boot Map Script");
@@ -444,7 +450,8 @@ static void ipl_scsi(void)
     uint8_t *ns, *ns_end;
     int program_table_entries = 0;
     const int pte_len = sizeof(ScsiBlockPtr);
-    ScsiBlockPtr *prog_table_entry;
+    ScsiBlockPtr *prog_table_entry = NULL;
+    unsigned int loadparm = get_loadparm_index();
 
     /* Grab the MBR */
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
@@ -458,15 +465,16 @@ static void ipl_scsi(void)
     debug_print_int("MBR Version", mbr->version_id);
     IPL_check(mbr->version_id == 1,
               "Unknown MBR layout version, assuming version 1");
-    debug_print_int("program table", mbr->blockptr.blockno);
-    IPL_assert(mbr->blockptr.blockno, "No Program Table");
+    debug_print_int("program table", mbr->blockptr[0].blockno);
+    IPL_assert(mbr->blockptr[0].blockno, "No Program Table");
 
     /* Parse the program table */
-    read_block(mbr->blockptr.blockno, sec,
+    read_block(mbr->blockptr[0].blockno, sec,
                "Error reading Program Table");
 
     IPL_assert(magic_match(sec, ZIPL_MAGIC), "No zIPL magic in PT");
 
+    debug_print_int("loadparm index", loadparm);
     ns_end = sec + virtio_get_block_size();
     for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns += pte_len) {
         prog_table_entry = (ScsiBlockPtr *)ns;
@@ -475,16 +483,15 @@ static void ipl_scsi(void)
         }
 
         program_table_entries++;
+        if (program_table_entries == loadparm + 1) {
+            break; /* selected entry found */
+        }
     }
 
     debug_print_int("program table entries", program_table_entries);
 
     IPL_assert(program_table_entries != 0, "Empty Program Table");
 
-    /* Run the default entry */
-
-    prog_table_entry = (ScsiBlockPtr *)(sec + pte_len);
-
     zipl_run(prog_table_entry); /* no return */
 }
 
@@ -648,6 +655,7 @@ static IsoBcSection *find_iso_bc_entry(void)
     IsoBcEntry *e = (IsoBcEntry *)sec;
     uint32_t offset = find_iso_bc();
     int i;
+    unsigned int loadparm = get_loadparm_index();
 
     if (!offset) {
         return NULL;
@@ -668,7 +676,11 @@ static IsoBcSection *find_iso_bc_entry(void)
     for (i = 1; i < ISO_BC_ENTRY_PER_SECTOR; i++) {
         if (e[i].id == ISO_BC_BOOTABLE_SECTION) {
             if (is_iso_bc_entry_compatible(&e[i].body.sect)) {
-                return &e[i].body.sect;
+                if (loadparm <= 1) {
+                    /* found, default, or unspecified */
+                    return &e[i].body.sect;
+                }
+                loadparm--;
             }
         }
     }
index bea168714bc7cc13ed0b6ae29de15f40c0cf9c04..7f367820f3b1b5bbad62196339a7d5336062bb1f 100644 (file)
@@ -70,7 +70,7 @@ typedef struct ScsiMbr {
     uint8_t magic[4];
     uint32_t version_id;
     uint8_t reserved[8];
-    ScsiBlockPtr blockptr;
+    ScsiBlockPtr blockptr[];
 } __attribute__ ((packed)) ScsiMbr;
 
 #define ZIPL_MAGIC              "zIPL"
@@ -264,28 +264,6 @@ typedef enum {
 
 /* utility code below */
 
-static const unsigned char ebc2asc[256] =
-      /* 0123456789abcdef0123456789abcdef */
-        "................................" /* 1F */
-        "................................" /* 3F */
-        " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
-        "-/.........,%_>?.........`:#@'=\""/* 7F */
-        ".abcdefghi.......jklmnopqr......" /* 9F */
-        "..stuvwxyz......................" /* BF */
-        ".ABCDEFGHI.......JKLMNOPQR......" /* DF */
-        "..STUVWXYZ......0123456789......";/* FF */
-
-static inline void ebcdic_to_ascii(const char *src,
-                                   char *dst,
-                                   unsigned int size)
-{
-    unsigned int i;
-    for (i = 0; i < size; i++) {
-        unsigned c = src[i];
-        dst[i] = ebc2asc[c];
-    }
-}
-
 static inline void print_volser(const void *volser)
 {
     char ascii[8];
index 0946766d8668c3c65b597aaa179c9941760b209a..1cacc1b46f54fff58ade792742e770e35ad57f88 100644 (file)
 char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
 static SubChannelId blk_schid = { .one = 1 };
 IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
+static char loadparm[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+const unsigned char ebc2asc[256] =
+      /* 0123456789abcdef0123456789abcdef */
+        "................................" /* 1F */
+        "................................" /* 3F */
+        " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
+        "-/.........,%_>?.........`:#@'=\""/* 7F */
+        ".abcdefghi.......jklmnopqr......" /* 9F */
+        "..stuvwxyz......................" /* BF */
+        ".ABCDEFGHI.......JKLMNOPQR......" /* DF */
+        "..STUVWXYZ......0123456789......";/* FF */
 
 /*
  * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
@@ -29,7 +41,6 @@ void write_subsystem_identification(void)
     *zeroes = 0;
 }
 
-
 void panic(const char *string)
 {
     sclp_print(string);
@@ -37,6 +48,26 @@ void panic(const char *string)
     while (1) { }
 }
 
+unsigned int get_loadparm_index(void)
+{
+    const char *lp = loadparm;
+    int i;
+    unsigned int idx = 0;
+
+    for (i = 0; i < 8; i++) {
+        char c = lp[i];
+
+        if (c < '0' || c > '9') {
+            break;
+        }
+
+        idx *= 10;
+        idx += c - '0';
+    }
+
+    return idx;
+}
+
 static bool find_dev(Schib *schib, int dev_no)
 {
     int i, r;
@@ -73,6 +104,7 @@ static void virtio_setup(void)
     int ssid;
     bool found = false;
     uint16_t dev_no;
+    char ldp[] = "LOADPARM=[________]\n";
     VDev *vdev = virtio_get_device();
 
     /*
@@ -82,6 +114,10 @@ static void virtio_setup(void)
      */
     enable_mss_facility();
 
+    sclp_get_loadparm_ascii(loadparm);
+    memcpy(ldp + 10, loadparm, 8);
+    sclp_print(ldp);
+
     if (store_iplb(&iplb)) {
         switch (iplb.pbt) {
         case S390_IPL_TYPE_CCW:
index ded67bcbc60ff9c3fabdf66bed53c0e822a90364..07d8cbcb202f087e857ea956895159443ba5ab4b 100644 (file)
@@ -62,10 +62,12 @@ void consume_sclp_int(void);
 void panic(const char *string);
 void write_subsystem_identification(void);
 extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
+unsigned int get_loadparm_index(void);
 
-/* sclp-ascii.c */
+/* sclp.c */
 void sclp_print(const char *string);
 void sclp_setup(void);
+void sclp_get_loadparm_ascii(char *loadparm);
 
 /* virtio.c */
 unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
@@ -189,4 +191,17 @@ static inline void IPL_check(bool term, const char *message)
     }
 }
 
+extern const unsigned char ebc2asc[256];
+static inline void ebcdic_to_ascii(const char *src,
+                                   char *dst,
+                                   unsigned int size)
+{
+    unsigned int i;
+
+    for (i = 0; i < size; i++) {
+        unsigned c = src[i];
+        dst[i] = ebc2asc[c];
+    }
+}
+
 #endif /* S390_CCW_H */
diff --git a/pc-bios/s390-ccw/sclp-ascii.c b/pc-bios/s390-ccw/sclp-ascii.c
deleted file mode 100644 (file)
index dc1c3e4..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SCLP ASCII access driver
- *
- * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or (at
- * your option) any later version. See the COPYING file in the top-level
- * directory.
- */
-
-#include "s390-ccw.h"
-#include "sclp.h"
-
-static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
-
-/* Perform service call. Return 0 on success, non-zero otherwise. */
-static int sclp_service_call(unsigned int command, void *sccb)
-{
-        int cc;
-
-        asm volatile(
-                "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
-                "       ipm     %0\n"
-                "       srl     %0,28"
-                : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
-                : "cc", "memory");
-        consume_sclp_int();
-        if (cc == 3)
-                return -EIO;
-        if (cc == 2)
-                return -EBUSY;
-        return 0;
-}
-
-static void sclp_set_write_mask(void)
-{
-    WriteEventMask *sccb = (void *)_sccb;
-
-    sccb->h.length = sizeof(WriteEventMask);
-    sccb->mask_length = sizeof(unsigned int);
-    sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
-    sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
-    sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
-    sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
-
-    sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
-}
-
-void sclp_setup(void)
-{
-    sclp_set_write_mask();
-}
-
-static int _strlen(const char *str)
-{
-    int i;
-    for (i = 0; *str; i++)
-        str++;
-    return i;
-}
-
-static void _memcpy(char *dest, const char *src, int len)
-{
-    int i;
-    for (i = 0; i < len; i++)
-        dest[i] = src[i];
-}
-
-void sclp_print(const char *str)
-{
-    int len = _strlen(str);
-    WriteEventData *sccb = (void *)_sccb;
-
-    sccb->h.length = sizeof(WriteEventData) + len;
-    sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
-    sccb->ebh.length = sizeof(EventBufferHeader) + len;
-    sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
-    sccb->ebh.flags = 0;
-    _memcpy(sccb->data, str, len);
-
-    sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
-}
diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c
new file mode 100644 (file)
index 0000000..a1639ba
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * SCLP ASCII access driver
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+#include "sclp.h"
+
+static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
+
+/* Perform service call. Return 0 on success, non-zero otherwise. */
+static int sclp_service_call(unsigned int command, void *sccb)
+{
+        int cc;
+
+        asm volatile(
+                "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
+                "       ipm     %0\n"
+                "       srl     %0,28"
+                : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
+                : "cc", "memory");
+        consume_sclp_int();
+        if (cc == 3)
+                return -EIO;
+        if (cc == 2)
+                return -EBUSY;
+        return 0;
+}
+
+static void sclp_set_write_mask(void)
+{
+    WriteEventMask *sccb = (void *)_sccb;
+
+    sccb->h.length = sizeof(WriteEventMask);
+    sccb->mask_length = sizeof(unsigned int);
+    sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
+    sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
+    sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+    sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+
+    sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
+}
+
+void sclp_setup(void)
+{
+    sclp_set_write_mask();
+}
+
+static int _strlen(const char *str)
+{
+    int i;
+    for (i = 0; *str; i++)
+        str++;
+    return i;
+}
+
+static void _memcpy(char *dest, const char *src, int len)
+{
+    int i;
+    for (i = 0; i < len; i++)
+        dest[i] = src[i];
+}
+
+void sclp_print(const char *str)
+{
+    int len = _strlen(str);
+    WriteEventData *sccb = (void *)_sccb;
+
+    sccb->h.length = sizeof(WriteEventData) + len;
+    sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
+    sccb->ebh.length = sizeof(EventBufferHeader) + len;
+    sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
+    sccb->ebh.flags = 0;
+    _memcpy(sccb->data, str, len);
+
+    sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
+}
+
+void sclp_get_loadparm_ascii(char *loadparm)
+{
+
+    ReadInfo *sccb = (void *)_sccb;
+
+    memset((char *)_sccb, 0, sizeof(ReadInfo));
+    sccb->h.length = sizeof(ReadInfo);
+    if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) {
+        ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8);
+    }
+}
index 3cbfb789307698a72c26c2fd2c410044e2e10c94..0dd987ff5dc4969c111c10295691cf9e9fe0bbf9 100644 (file)
@@ -55,6 +55,8 @@ typedef struct ReadInfo {
     SCCBHeader h;
     uint16_t rnmax;
     uint8_t rnsize;
+    uint8_t reserved[13];
+    uint8_t loadparm[8];
 } __attribute__((packed)) ReadInfo;
 
 typedef struct SCCB {
index 01b087fa163500243d2a783228ec7611fc2f0f38..5bb8cb79fb0e61d15f672c1c69fd259b6a8eee27 100644 (file)
 # @nodelay: set TCP_NODELAY socket option (default: false)
 # @telnet: enable telnet protocol on server
 #          sockets (default: false)
+# @tn3270: enable tn3270 protocol on server
+#          sockets (default: false) (Since: 2.10)
 # @reconnect: For a client socket, if a socket is disconnected,
 #          then attempt a reconnect after the given number of seconds.
 #          Setting this to zero disables this function. (default: 0)
                                      '*wait'      : 'bool',
                                      '*nodelay'   : 'bool',
                                      '*telnet'    : 'bool',
+                                     '*tn3270'    : 'bool',
                                      '*reconnect' : 'int' },
   'base': 'ChardevCommon' }
 
index 8ac78222afd59cbdf53648d6539a9220d94bcf72..bf4ce590199256ac824515a70d5669540747c48c 100644 (file)
@@ -22,9 +22,9 @@ STEXI
 ETEXI
 
 DEF("create", img_create,
-    "create [-q] [--object objectdef] [-f fmt] [-o options] filename [size]")
+    "create [-q] [--object objectdef] [-f fmt] [-b backing_file] [-F backing_fmt] [-o options] filename [size]")
 STEXI
-@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}]
+@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-o @var{options}] @var{filename} [@var{size}]
 ETEXI
 
 DEF("commit", img_commit,
@@ -40,9 +40,9 @@ STEXI
 ETEXI
 
 DEF("convert", img_convert,
-    "convert [--object objectdef] [--image-opts] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
+    "convert [--object objectdef] [--image-opts] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] filename [filename2 [...]] output_filename")
 STEXI
-@item convert [--object @var{objectdef}] [--image-opts] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
+@item convert [--object @var{objectdef}] [--image-opts] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] [-m @var{num_coroutines}] [-W] @var{filename} [@var{filename2} [...]] @var{output_filename}
 ETEXI
 
 DEF("dd", img_dd,
index bbe15741f1f5d27b457055c13c02c77e3c88f2b7..c7196362df8a05f3827ea96edcd355ae5276aad5 100644 (file)
@@ -1522,7 +1522,7 @@ typedef struct ImgConvertState {
     int min_sparse;
     size_t cluster_sectors;
     size_t buf_sectors;
-    int num_coroutines;
+    long num_coroutines;
     int running_coroutines;
     Coroutine *co[MAX_COROUTINES];
     int64_t wait_sector_num[MAX_COROUTINES];
@@ -1554,9 +1554,15 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
 
     if (s->sector_next_status <= sector_num) {
         BlockDriverState *file;
-        ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
-                                    sector_num - src_cur_offset,
-                                    n, &n, &file);
+        if (s->target_has_backing) {
+            ret = bdrv_get_block_status(blk_bs(s->src[src_cur]),
+                                        sector_num - src_cur_offset,
+                                        n, &n, &file);
+        } else {
+            ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL,
+                                              sector_num - src_cur_offset,
+                                              n, &n, &file);
+        }
         if (ret < 0) {
             return ret;
         }
@@ -1565,26 +1571,8 @@ static int convert_iteration_sectors(ImgConvertState *s, int64_t sector_num)
             s->status = BLK_ZERO;
         } else if (ret & BDRV_BLOCK_DATA) {
             s->status = BLK_DATA;
-        } else if (!s->target_has_backing) {
-            /* Without a target backing file we must copy over the contents of
-             * the backing file as well. */
-            /* Check block status of the backing file chain to avoid
-             * needlessly reading zeroes and limiting the iteration to the
-             * buffer size */
-            ret = bdrv_get_block_status_above(blk_bs(s->src[src_cur]), NULL,
-                                              sector_num - src_cur_offset,
-                                              n, &n, &file);
-            if (ret < 0) {
-                return ret;
-            }
-
-            if (ret & BDRV_BLOCK_ZERO) {
-                s->status = BLK_ZERO;
-            } else {
-                s->status = BLK_DATA;
-            }
         } else {
-            s->status = BLK_BACKING_FILE;
+            s->status = s->target_has_backing ? BLK_BACKING_FILE : BLK_DATA;
         }
 
         s->sector_next_status = sector_num + n;
@@ -1661,6 +1649,8 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
 
     while (nb_sectors > 0) {
         int n = nb_sectors;
+        BdrvRequestFlags flags = s->compressed ? BDRV_REQ_WRITE_COMPRESSED : 0;
+
         switch (status) {
         case BLK_BACKING_FILE:
             /* If we have a backing file, leave clusters unallocated that are
@@ -1670,43 +1660,24 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
             break;
 
         case BLK_DATA:
-            /* We must always write compressed clusters as a whole, so don't
-             * try to find zeroed parts in the buffer. We can only save the
-             * write if the buffer is completely zeroed and we're allowed to
-             * keep the target sparse. */
-            if (s->compressed) {
-                if (s->has_zero_init && s->min_sparse &&
-                    buffer_is_zero(buf, n * BDRV_SECTOR_SIZE))
-                {
-                    assert(!s->target_has_backing);
-                    break;
-                }
-
-                iov.iov_base = buf;
-                iov.iov_len = n << BDRV_SECTOR_BITS;
-                qemu_iovec_init_external(&qiov, &iov, 1);
-
-                ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
-                                     n << BDRV_SECTOR_BITS, &qiov,
-                                     BDRV_REQ_WRITE_COMPRESSED);
-                if (ret < 0) {
-                    return ret;
-                }
-                break;
-            }
-
-            /* If there is real non-zero data or we're told to keep the target
-             * fully allocated (-S 0), we must write it. Otherwise we can treat
-             * it as zero sectors. */
+            /* If we're told to keep the target fully allocated (-S 0) or there
+             * is real non-zero data, we must write it. Otherwise we can treat
+             * it as zero sectors.
+             * Compressed clusters need to be written as a whole, so in that
+             * case we can only save the write if the buffer is completely
+             * zeroed. */
             if (!s->min_sparse ||
-                is_allocated_sectors_min(buf, n, &n, s->min_sparse))
+                (!s->compressed &&
+                 is_allocated_sectors_min(buf, n, &n, s->min_sparse)) ||
+                (s->compressed &&
+                 !buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)))
             {
                 iov.iov_base = buf;
                 iov.iov_len = n << BDRV_SECTOR_BITS;
                 qemu_iovec_init_external(&qiov, &iov, 1);
 
                 ret = blk_co_pwritev(s->target, sector_num << BDRV_SECTOR_BITS,
-                                     n << BDRV_SECTOR_BITS, &qiov, 0);
+                                     n << BDRV_SECTOR_BITS, &qiov, flags);
                 if (ret < 0) {
                     return ret;
                 }
@@ -1716,6 +1687,7 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
 
         case BLK_ZERO:
             if (s->has_zero_init) {
+                assert(!s->target_has_backing);
                 break;
             }
             ret = blk_co_pwrite_zeroes(s->target,
@@ -1916,39 +1888,29 @@ static int convert_do_copy(ImgConvertState *s)
 
 static int img_convert(int argc, char **argv)
 {
-    int c, bs_n, bs_i, compress, cluster_sectors, skip_create;
-    int64_t ret = 0;
-    int progress = 0, flags, src_flags;
-    bool writethrough, src_writethrough;
-    const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
+    int c, bs_i, flags, src_flags = 0;
+    const char *fmt = NULL, *out_fmt = "raw", *cache = "unsafe",
+               *src_cache = BDRV_DEFAULT_CACHE, *out_baseimg = NULL,
+               *out_filename, *out_baseimg_param, *snapshot_name = NULL;
     BlockDriver *drv, *proto_drv;
-    BlockBackend **blk = NULL, *out_blk = NULL;
-    BlockDriverState **bs = NULL, *out_bs = NULL;
-    int64_t total_sectors;
-    int64_t *bs_sectors = NULL;
-    size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE;
     BlockDriverInfo bdi;
-    QemuOpts *opts = NULL;
+    BlockDriverState *out_bs;
+    QemuOpts *opts = NULL, *sn_opts = NULL;
     QemuOptsList *create_opts = NULL;
-    const char *out_baseimg_param;
     char *options = NULL;
-    const char *snapshot_name = NULL;
-    int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
-    bool quiet = false;
     Error *local_err = NULL;
-    QemuOpts *sn_opts = NULL;
-    ImgConvertState state;
-    bool image_opts = false;
-    bool wr_in_order = true;
-    long num_coroutines = 8;
+    bool writethrough, src_writethrough, quiet = false, image_opts = false,
+         skip_create = false, progress = false;
+    int64_t ret = -EINVAL;
+
+    ImgConvertState s = (ImgConvertState) {
+        /* Need at least 4k of zeros for sparse detection */
+        .min_sparse         = 8,
+        .buf_sectors        = IO_BUF_SIZE / BDRV_SECTOR_SIZE,
+        .wr_in_order        = true,
+        .num_coroutines     = 8,
+    };
 
-    fmt = NULL;
-    out_fmt = "raw";
-    cache = "unsafe";
-    src_cache = BDRV_DEFAULT_CACHE;
-    out_baseimg = NULL;
-    compress = 0;
-    skip_create = 0;
     for(;;) {
         static const struct option long_options[] = {
             {"help", no_argument, 0, 'h'},
@@ -1981,22 +1943,19 @@ static int img_convert(int argc, char **argv)
             out_baseimg = optarg;
             break;
         case 'c':
-            compress = 1;
+            s.compressed = true;
             break;
         case 'e':
             error_report("option -e is deprecated, please use \'-o "
                   "encryption\' instead!");
-            ret = -1;
             goto fail_getopt;
         case '6':
             error_report("option -6 is deprecated, please use \'-o "
                   "compat6\' instead!");
-            ret = -1;
             goto fail_getopt;
         case 'o':
             if (!is_valid_option_list(optarg)) {
                 error_report("Invalid option list: %s", optarg);
-                ret = -1;
                 goto fail_getopt;
             }
             if (!options) {
@@ -2017,7 +1976,6 @@ static int img_convert(int argc, char **argv)
                 if (!sn_opts) {
                     error_report("Failed in parsing snapshot param '%s'",
                                  optarg);
-                    ret = -1;
                     goto fail_getopt;
                 }
             } else {
@@ -2031,15 +1989,14 @@ static int img_convert(int argc, char **argv)
             sval = cvtnum(optarg);
             if (sval < 0) {
                 error_report("Invalid minimum zero buffer size for sparse output specified");
-                ret = -1;
                 goto fail_getopt;
             }
 
-            min_sparse = sval / BDRV_SECTOR_SIZE;
+            s.min_sparse = sval / BDRV_SECTOR_SIZE;
             break;
         }
         case 'p':
-            progress = 1;
+            progress = true;
             break;
         case 't':
             cache = optarg;
@@ -2051,27 +2008,28 @@ static int img_convert(int argc, char **argv)
             quiet = true;
             break;
         case 'n':
-            skip_create = 1;
+            skip_create = true;
             break;
         case 'm':
-            if (qemu_strtol(optarg, NULL, 0, &num_coroutines) ||
-                num_coroutines < 1 || num_coroutines > MAX_COROUTINES) {
+            if (qemu_strtol(optarg, NULL, 0, &s.num_coroutines) ||
+                s.num_coroutines < 1 || s.num_coroutines > MAX_COROUTINES) {
                 error_report("Invalid number of coroutines. Allowed number of"
                              " coroutines is between 1 and %d", MAX_COROUTINES);
-                ret = -1;
                 goto fail_getopt;
             }
             break;
         case 'W':
-            wr_in_order = false;
+            s.wr_in_order = false;
             break;
-        case OPTION_OBJECT:
-            opts = qemu_opts_parse_noisily(&qemu_object_opts,
-                                           optarg, true);
-            if (!opts) {
+        case OPTION_OBJECT: {
+            QemuOpts *object_opts;
+            object_opts = qemu_opts_parse_noisily(&qemu_object_opts,
+                                                  optarg, true);
+            if (!object_opts) {
                 goto fail_getopt;
             }
             break;
+        }
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -2084,83 +2042,73 @@ static int img_convert(int argc, char **argv)
         goto fail_getopt;
     }
 
-    if (!wr_in_order && compress) {
+    if (!s.wr_in_order && s.compressed) {
         error_report("Out of order write and compress are mutually exclusive");
-        ret = -1;
         goto fail_getopt;
     }
 
-    /* Initialize before goto out */
-    if (quiet) {
-        progress = 0;
-    }
-    qemu_progress_init(progress, 1.0);
-
-    bs_n = argc - optind - 1;
-    out_filename = bs_n >= 1 ? argv[argc - 1] : NULL;
+    s.src_num = argc - optind - 1;
+    out_filename = s.src_num >= 1 ? argv[argc - 1] : NULL;
 
     if (options && has_help_option(options)) {
         ret = print_block_option_help(out_filename, out_fmt);
-        goto out;
+        goto fail_getopt;
     }
 
-    if (bs_n < 1) {
-        error_exit("Must specify image file name");
+    if (s.src_num < 1) {
+        error_report("Must specify image file name");
+        goto fail_getopt;
     }
 
 
-    if (bs_n > 1 && out_baseimg) {
-        error_report("-B makes no sense when concatenating multiple input "
-                     "images");
-        ret = -1;
-        goto out;
-    }
-
-    src_flags = 0;
+    /* ret is still -EINVAL until here */
     ret = bdrv_parse_cache_mode(src_cache, &src_flags, &src_writethrough);
     if (ret < 0) {
         error_report("Invalid source cache option: %s", src_cache);
-        goto out;
+        goto fail_getopt;
     }
 
+    /* Initialize before goto out */
+    if (quiet) {
+        progress = false;
+    }
+    qemu_progress_init(progress, 1.0);
     qemu_progress_print(0, 100);
 
-    blk = g_new0(BlockBackend *, bs_n);
-    bs = g_new0(BlockDriverState *, bs_n);
-    bs_sectors = g_new(int64_t, bs_n);
+    s.src = g_new0(BlockBackend *, s.src_num);
+    s.src_sectors = g_new(int64_t, s.src_num);
 
-    total_sectors = 0;
-    for (bs_i = 0; bs_i < bs_n; bs_i++) {
-        blk[bs_i] = img_open(image_opts, argv[optind + bs_i],
-                             fmt, src_flags, src_writethrough, quiet);
-        if (!blk[bs_i]) {
+    for (bs_i = 0; bs_i < s.src_num; bs_i++) {
+        s.src[bs_i] = img_open(image_opts, argv[optind + bs_i],
+                               fmt, src_flags, src_writethrough, quiet);
+        if (!s.src[bs_i]) {
             ret = -1;
             goto out;
         }
-        bs[bs_i] = blk_bs(blk[bs_i]);
-        bs_sectors[bs_i] = blk_nb_sectors(blk[bs_i]);
-        if (bs_sectors[bs_i] < 0) {
+        s.src_sectors[bs_i] = blk_nb_sectors(s.src[bs_i]);
+        if (s.src_sectors[bs_i] < 0) {
             error_report("Could not get size of %s: %s",
-                         argv[optind + bs_i], strerror(-bs_sectors[bs_i]));
+                         argv[optind + bs_i], strerror(-s.src_sectors[bs_i]));
             ret = -1;
             goto out;
         }
-        total_sectors += bs_sectors[bs_i];
+        s.total_sectors += s.src_sectors[bs_i];
     }
 
     if (sn_opts) {
-        bdrv_snapshot_load_tmp(bs[0],
+        bdrv_snapshot_load_tmp(blk_bs(s.src[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) {
+        if (s.src_num > 1) {
             error_report("No support for concatenating multiple snapshot");
             ret = -1;
             goto out;
         }
 
-        bdrv_snapshot_load_tmp_by_id_or_name(bs[0], snapshot_name, &local_err);
+        bdrv_snapshot_load_tmp_by_id_or_name(blk_bs(s.src[0]), snapshot_name,
+                                             &local_err);
     }
     if (local_err) {
         error_reportf_err(local_err, "Failed to load snapshot: ");
@@ -2211,7 +2159,7 @@ static int img_convert(int argc, char **argv)
             }
         }
 
-        qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512,
+        qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s.total_sectors * 512,
                             &error_abort);
         ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL);
         if (ret < 0) {
@@ -2224,9 +2172,17 @@ static int img_convert(int argc, char **argv)
     if (out_baseimg_param) {
         out_baseimg = out_baseimg_param;
     }
+    s.target_has_backing = (bool) out_baseimg;
+
+    if (s.src_num > 1 && out_baseimg) {
+        error_report("Having a backing file for the target makes no sense when "
+                     "concatenating multiple input images");
+        ret = -1;
+        goto out;
+    }
 
     /* Check if compression is supported */
-    if (compress) {
+    if (s.compressed) {
         bool encryption =
             qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
         const char *preallocation =
@@ -2265,7 +2221,7 @@ static int img_convert(int argc, char **argv)
         }
     }
 
-    flags = min_sparse ? (BDRV_O_RDWR | BDRV_O_UNMAP) : BDRV_O_RDWR;
+    flags = s.min_sparse ? (BDRV_O_RDWR | BDRV_O_UNMAP) : BDRV_O_RDWR;
     ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
     if (ret < 0) {
         error_report("Invalid cache option: %s", cache);
@@ -2277,64 +2233,48 @@ static int img_convert(int argc, char **argv)
      * the bdrv_create() call which takes different params.
      * Not critical right now, so fix can wait...
      */
-    out_blk = img_open_file(out_filename, out_fmt, flags, writethrough, quiet);
-    if (!out_blk) {
+    s.target = img_open_file(out_filename, out_fmt, flags, writethrough, quiet);
+    if (!s.target) {
         ret = -1;
         goto out;
     }
-    out_bs = blk_bs(out_blk);
+    out_bs = blk_bs(s.target);
 
     /* increase bufsectors from the default 4096 (2M) if opt_transfer
      * 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 >> BDRV_SECTOR_BITS,
-                             out_bs->bl.pdiscard_alignment >>
-                             BDRV_SECTOR_BITS)));
+    s.buf_sectors = MIN(32768,
+                        MAX(s.buf_sectors,
+                            MAX(out_bs->bl.opt_transfer >> BDRV_SECTOR_BITS,
+                                out_bs->bl.pdiscard_alignment >>
+                                BDRV_SECTOR_BITS)));
 
     if (skip_create) {
-        int64_t output_sectors = blk_nb_sectors(out_blk);
+        int64_t output_sectors = blk_nb_sectors(s.target);
         if (output_sectors < 0) {
             error_report("unable to get output image length: %s",
                          strerror(-output_sectors));
             ret = -1;
             goto out;
-        } else if (output_sectors < total_sectors) {
+        } else if (output_sectors < s.total_sectors) {
             error_report("output file is smaller than input file");
             ret = -1;
             goto out;
         }
     }
 
-    cluster_sectors = 0;
     ret = bdrv_get_info(out_bs, &bdi);
     if (ret < 0) {
-        if (compress) {
+        if (s.compressed) {
             error_report("could not get block driver info");
             goto out;
         }
     } else {
-        compress = compress || bdi.needs_compressed_writes;
-        cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
-    }
-
-    state = (ImgConvertState) {
-        .src                = blk,
-        .src_sectors        = bs_sectors,
-        .src_num            = bs_n,
-        .total_sectors      = total_sectors,
-        .target             = out_blk,
-        .compressed         = compress,
-        .target_has_backing = (bool) out_baseimg,
-        .min_sparse         = min_sparse,
-        .cluster_sectors    = cluster_sectors,
-        .buf_sectors        = bufsectors,
-        .wr_in_order        = wr_in_order,
-        .num_coroutines     = num_coroutines,
-    };
-    ret = convert_do_copy(&state);
+        s.compressed = s.compressed || bdi.needs_compressed_writes;
+        s.cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
+    }
 
+    ret = convert_do_copy(&s);
 out:
     if (!ret) {
         qemu_progress_print(100, 0);
@@ -2343,22 +2283,18 @@ out:
     qemu_opts_del(opts);
     qemu_opts_free(create_opts);
     qemu_opts_del(sn_opts);
-    blk_unref(out_blk);
-    g_free(bs);
-    if (blk) {
-        for (bs_i = 0; bs_i < bs_n; bs_i++) {
-            blk_unref(blk[bs_i]);
+    blk_unref(s.target);
+    if (s.src) {
+        for (bs_i = 0; bs_i < s.src_num; bs_i++) {
+            blk_unref(s.src[bs_i]);
         }
-        g_free(blk);
+        g_free(s.src);
     }
-    g_free(bs_sectors);
+    g_free(s.src_sectors);
 fail_getopt:
     g_free(options);
 
-    if (ret) {
-        return 1;
-    }
-    return 0;
+    return !!ret;
 }
 
 
@@ -3500,20 +3436,11 @@ static int img_resize(int argc, char **argv)
         goto out;
     }
 
-    ret = blk_truncate(blk, total_size);
-    switch (ret) {
-    case 0:
+    ret = blk_truncate(blk, total_size, &err);
+    if (!ret) {
         qprintf(quiet, "Image resized.\n");
-        break;
-    case -ENOTSUP:
-        error_report("This image does not support resize");
-        break;
-    case -EACCES:
-        error_report("Image is read-only");
-        break;
-    default:
-        error_report("Error resizing image: %s", strerror(-ret));
-        break;
+    } else {
+        error_report_err(err);
     }
 out:
     blk_unref(blk);
index c81db3e81cd0f9a4ec356790682f3bda7694b37e..50a2364e80e41ac223c68c6f483abe6e87103794 100644 (file)
@@ -84,7 +84,8 @@ with or without a command shows help and lists the supported formats
 @item -p
 display progress bar (compare, convert and rebase commands only).
 If the @var{-p} option is not used for a command that supports it, the
-progress is reported when the process receives a @code{SIGUSR1} signal.
+progress is reported when the process receives a @code{SIGUSR1} or
+@code{SIGINFO} signal.
 @item -q
 Quiet mode - do not print any output (except errors). There's no progress bar
 in case both @var{-q} and @var{-p} options are used.
@@ -224,7 +225,7 @@ If @code{-r} is specified, exit codes representing the image state refer to the
 state after (the attempt at) repairing it. That is, a successful @code{-r all}
 will yield the exit code 0, independently of the image state before.
 
-@item create [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}]
+@item create [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-o @var{options}] @var{filename} [@var{size}]
 
 Create the new disk image @var{filename} of size @var{size} and format
 @var{fmt}. Depending on the file format, you can add one or more @var{options}
@@ -302,7 +303,7 @@ Error on reading data
 
 @end table
 
-@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-m @var{num_coroutines}] [-W] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
+@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-B @var{backing_file}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-m @var{num_coroutines}] [-W] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
 
 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}
index 312fc6d157f172d96f8b98d9bd78a4a6e5fd7f80..21af9e65b2d5892d1256369dee7b38c7564957d0 100644 (file)
@@ -1567,6 +1567,7 @@ static const cmdinfo_t flush_cmd = {
 
 static int truncate_f(BlockBackend *blk, int argc, char **argv)
 {
+    Error *local_err = NULL;
     int64_t offset;
     int ret;
 
@@ -1576,9 +1577,9 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
         return 0;
     }
 
-    ret = blk_truncate(blk, offset);
+    ret = blk_truncate(blk, offset, &local_err);
     if (ret < 0) {
-        printf("truncate: %s\n", strerror(-ret));
+        error_report_err(local_err);
         return 0;
     }
 
index 787b9c38da589d5fc57cb1ef8e11eac07044e247..f68829f3b049ce432ddd18b950254eab7044fe77 100644 (file)
@@ -803,8 +803,8 @@ STEXI
 Force hard disk 0 physical geometry (1 <= @var{c} <= 16383, 1 <=
 @var{h} <= 16, 1 <= @var{s} <= 63) and optionally force the BIOS
 translation mode (@var{t}=none, lba or auto). Usually QEMU can guess
-all those parameters. This option is useful for old MS-DOS disk
-images.
+all those parameters. This option is deprecated, please use
+@code{-device ide-hd,cyls=c,heads=h,secs=s,...} instead.
 ETEXI
 
 DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
index 65e2d375c27c5063b54cfae902c88ad920831a22..8cced4604f08bef81513d5693125695fea3be95d 100644 (file)
@@ -64,7 +64,7 @@ void replay_vmstate_init(void)
 {
     if (replay_snapshot) {
         if (replay_mode == REPLAY_MODE_RECORD) {
-            if (save_vmstate(cur_mon, replay_snapshot) != 0) {
+            if (save_vmstate(replay_snapshot) != 0) {
                 error_report("Could not create snapshot for icount record");
                 exit(1);
             }
index 7fd2b9a2167f37d672bcbbbe42f8a78db43a3723..1d6330cbccfa9ee08bbec03d3beab3a5d8788f53 100644 (file)
@@ -51,8 +51,8 @@ static void openrisc_cpu_reset(CPUState *s)
     cpu->env.lock_addr = -1;
     s->exception_index = -1;
 
-    cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
-    cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
+    cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP |
+                   UPR_PMP;
     cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
     cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
 
@@ -65,12 +65,6 @@ static void openrisc_cpu_reset(CPUState *s)
 #endif
 }
 
-static inline void set_feature(OpenRISCCPU *cpu, int feature)
-{
-    cpu->feature |= feature;
-    cpu->env.cpucfgr = cpu->feature;
-}
-
 static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
@@ -132,15 +126,15 @@ static void or1200_initfn(Object *obj)
 {
     OpenRISCCPU *cpu = OPENRISC_CPU(obj);
 
-    set_feature(cpu, OPENRISC_FEATURE_OB32S);
-    set_feature(cpu, OPENRISC_FEATURE_OF32S);
+    cpu->env.cpucfgr = CPUCFGR_NSGF | CPUCFGR_OB32S | CPUCFGR_OF32S |
+                       CPUCFGR_EVBARP;
 }
 
 static void openrisc_any_initfn(Object *obj)
 {
     OpenRISCCPU *cpu = OPENRISC_CPU(obj);
 
-    set_feature(cpu, OPENRISC_FEATURE_OB32S);
+    cpu->env.cpucfgr = CPUCFGR_NSGF | CPUCFGR_OB32S | CPUCFGR_EVBARP;
 }
 
 typedef struct OpenRISCCPUInfo {
index 418a0e6960c7236cf730e15cf616b92c6fbd2c9b..2721432c4fe44c5563e1f3dd53d38c327e67c269 100644 (file)
@@ -111,6 +111,11 @@ enum {
     CPUCFGR_OF32S = (1 << 7),
     CPUCFGR_OF64S = (1 << 8),
     CPUCFGR_OV64S = (1 << 9),
+    /* CPUCFGR_ND = (1 << 10), */
+    /* CPUCFGR_AVRP = (1 << 11), */
+    CPUCFGR_EVBARP = (1 << 12),
+    /* CPUCFGR_ISRP = (1 << 13), */
+    /* CPUCFGR_AECSRP = (1 << 14), */
 };
 
 /* DMMU configure register */
@@ -135,6 +140,15 @@ enum {
     IMMUCFGR_HTR = (1 << 11),
 };
 
+/* Power management register */
+enum {
+    PMR_SDF = (15 << 0),
+    PMR_DME = (1 << 4),
+    PMR_SME = (1 << 5),
+    PMR_DCGE = (1 << 6),
+    PMR_SUME = (1 << 7),
+};
+
 /* Float point control status register */
 enum {
     FPCSR_FPEE = 1,
@@ -191,17 +205,6 @@ enum {
     SR_SCE = (1 << 17),
 };
 
-/* OpenRISC Hardware Capabilities */
-enum {
-    OPENRISC_FEATURE_NSGF = (15 << 0),
-    OPENRISC_FEATURE_CGF = (1 << 4),
-    OPENRISC_FEATURE_OB32S = (1 << 5),
-    OPENRISC_FEATURE_OB64S = (1 << 6),
-    OPENRISC_FEATURE_OF32S = (1 << 7),
-    OPENRISC_FEATURE_OF64S = (1 << 8),
-    OPENRISC_FEATURE_OV64S = (1 << 9),
-};
-
 /* Tick Timer Mode Register */
 enum {
     TTMR_TP = (0xfffffff),
@@ -269,7 +272,8 @@ typedef struct CPUOpenRISCTLBContext {
 #endif
 
 typedef struct CPUOpenRISCState {
-    target_ulong gpr[32];     /* General registers */
+    target_ulong shadow_gpr[16][32]; /* Shadow registers */
+
     target_ulong pc;          /* Program counter */
     target_ulong ppc;         /* Prev PC */
     target_ulong jmp_pc;      /* Jump PC */
@@ -285,10 +289,11 @@ typedef struct CPUOpenRISCState {
     uint32_t sr;              /* Supervisor register, without SR_{F,CY,OV} */
     uint32_t vr;              /* Version register */
     uint32_t upr;             /* Unit presence register */
-    uint32_t cpucfgr;         /* CPU configure register */
     uint32_t dmmucfgr;        /* DMMU configure register */
     uint32_t immucfgr;        /* IMMU configure register */
     uint32_t esr;             /* Exception supervisor register */
+    uint32_t evbar;           /* Exception vector base address register */
+    uint32_t pmr;             /* Power Management Register */
     uint32_t fpcsr;           /* Float register */
     float_status fp_status;
 
@@ -303,6 +308,8 @@ typedef struct CPUOpenRISCState {
     CPU_COMMON
 
     /* Fields from here on are preserved across CPU reset. */
+    uint32_t cpucfgr;         /* CPU configure register */
+
 #ifndef CONFIG_USER_ONLY
     CPUOpenRISCTLBContext * tlb;
 
@@ -329,7 +336,6 @@ typedef struct OpenRISCCPU {
 
     CPUOpenRISCState env;
 
-    uint32_t feature;       /* CPU Capabilities */
 } OpenRISCCPU;
 
 static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
@@ -392,6 +398,16 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
 #define TB_FLAGS_R0_0  2
 #define TB_FLAGS_OVE   SR_OVE
 
+static inline uint32_t cpu_get_gpr(const CPUOpenRISCState *env, int i)
+{
+    return env->shadow_gpr[0][i];
+}
+
+static inline void cpu_set_gpr(CPUOpenRISCState *env, int i, uint32_t val)
+{
+    env->shadow_gpr[0][i] = val;
+}
+
 static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
                                         target_ulong *pc,
                                         target_ulong *cs_base, uint32_t *flags)
@@ -399,7 +415,7 @@ static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
     *pc = env->pc;
     *cs_base = 0;
     *flags = (env->dflag
-              | (env->gpr[0] == 0 ? TB_FLAGS_R0_0 : 0)
+              | (cpu_get_gpr(env, 0) == 0 ? TB_FLAGS_R0_0 : 0)
               | (env->sr & SR_OVE));
 }
 
index b18c7e9f05c14b8ce69a819d808ccc631f8ee868..f9af6507f3390edc3bd9f3a42735f99a69ca2f3d 100644 (file)
@@ -28,7 +28,7 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
     CPUOpenRISCState *env = &cpu->env;
 
     if (n < 32) {
-        return gdb_get_reg32(mem_buf, env->gpr[n]);
+        return gdb_get_reg32(mem_buf, cpu_get_gpr(env, n));
     } else {
         switch (n) {
         case 32:    /* PPC */
@@ -61,7 +61,7 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     tmp = ldl_p(mem_buf);
 
     if (n < 32) {
-        env->gpr[n] = tmp;
+        cpu_set_gpr(env, n, tmp);
     } else {
         switch (n) {
         case 32: /* PPC */
index a2eec6fb32928671e753e289421cd123c236228d..3959671c59bd2708a8ed15b55166bf55defe106b 100644 (file)
@@ -60,12 +60,21 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
     env->sr |= SR_SM;
     env->sr &= ~SR_IEE;
     env->sr &= ~SR_TEE;
+    env->pmr &= ~PMR_DME;
+    env->pmr &= ~PMR_SME;
     env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
     env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
     env->lock_addr = -1;
 
     if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
-        env->pc = (cs->exception_index << 8);
+        hwaddr vect_pc = cs->exception_index << 8;
+        if (env->cpucfgr & CPUCFGR_EVBARP) {
+            vect_pc |= env->evbar;
+        }
+        if (env->sr & SR_EPH) {
+            vect_pc |= 0xf0000000;
+        }
+        env->pc = vect_pc;
     } else {
         cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
     }
index 686eaa30c93a54209f93bc7b02268ebe994e7f46..a20cce705d3d551daaccd653d925373b995149d1 100644 (file)
 #include "hw/boards.h"
 #include "migration/cpu.h"
 
+static int env_post_load(void *opaque, int version_id)
+{
+    CPUOpenRISCState *env = opaque;
+
+    /* Restore MMU handlers */
+    if (env->sr & SR_DME) {
+        env->tlb->cpu_openrisc_map_address_data =
+            &cpu_openrisc_get_phys_data;
+    } else {
+        env->tlb->cpu_openrisc_map_address_data =
+            &cpu_openrisc_get_phys_nommu;
+    }
+
+    if (env->sr & SR_IME) {
+        env->tlb->cpu_openrisc_map_address_code =
+            &cpu_openrisc_get_phys_code;
+    } else {
+        env->tlb->cpu_openrisc_map_address_code =
+            &cpu_openrisc_get_phys_nommu;
+    }
+
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_tlb_entry = {
+    .name = "tlb_entry",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINTTL(mr, OpenRISCTLBEntry),
+        VMSTATE_UINTTL(tr, OpenRISCTLBEntry),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_cpu_tlb = {
+    .name = "cpu_tlb",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_2DARRAY(itlb, CPUOpenRISCTLBContext,
+                             ITLB_WAYS, ITLB_SIZE, 0,
+                             vmstate_tlb_entry, OpenRISCTLBEntry),
+        VMSTATE_STRUCT_2DARRAY(dtlb, CPUOpenRISCTLBContext,
+                             DTLB_WAYS, DTLB_SIZE, 0,
+                             vmstate_tlb_entry, OpenRISCTLBEntry),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+#define VMSTATE_CPU_TLB(_f, _s)                             \
+    VMSTATE_STRUCT_POINTER(_f, _s, vmstate_cpu_tlb, CPUOpenRISCTLBContext)
+
+
 static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
 {
     CPUOpenRISCState *env = opaque;
@@ -47,10 +104,11 @@ static const VMStateInfo vmstate_sr = {
 
 static const VMStateDescription vmstate_env = {
     .name = "env",
-    .version_id = 4,
-    .minimum_version_id = 4,
+    .version_id = 6,
+    .minimum_version_id = 6,
+    .post_load = env_post_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32),
+        VMSTATE_UINTTL_2DARRAY(shadow_gpr, CPUOpenRISCState, 16, 32),
         VMSTATE_UINTTL(pc, CPUOpenRISCState),
         VMSTATE_UINTTL(ppc, CPUOpenRISCState),
         VMSTATE_UINTTL(jmp_pc, CPUOpenRISCState),
@@ -79,9 +137,21 @@ static const VMStateDescription vmstate_env = {
         VMSTATE_UINT32(cpucfgr, CPUOpenRISCState),
         VMSTATE_UINT32(dmmucfgr, CPUOpenRISCState),
         VMSTATE_UINT32(immucfgr, CPUOpenRISCState),
+        VMSTATE_UINT32(evbar, CPUOpenRISCState),
+        VMSTATE_UINT32(pmr, CPUOpenRISCState),
         VMSTATE_UINT32(esr, CPUOpenRISCState),
         VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
         VMSTATE_UINT64(mac, CPUOpenRISCState),
+
+        VMSTATE_CPU_TLB(tlb, CPUOpenRISCState),
+
+        VMSTATE_TIMER_PTR(timer, CPUOpenRISCState),
+        VMSTATE_UINT32(ttmr, CPUOpenRISCState),
+        VMSTATE_UINT32(ttcr, CPUOpenRISCState),
+
+        VMSTATE_UINT32(picmr, CPUOpenRISCState),
+        VMSTATE_UINT32(picsr, CPUOpenRISCState),
+
         VMSTATE_END_OF_LIST()
     }
 };
index 56b11d3d68326e0df086612fca41b42f97bfbfa8..ce2a29dd1a63721b629828fb0dce2d9993e607bd 100644 (file)
@@ -124,7 +124,7 @@ static int cpu_openrisc_get_phys_addr(OpenRISCCPU *cpu,
 {
     int ret = TLBRET_MATCH;
 
-    if (rw == 2) {    /* ITLB */
+    if (rw == MMU_INST_FETCH) {    /* ITLB */
        *physical = 0;
         ret = cpu->env.tlb->cpu_openrisc_map_address_code(cpu, physical,
                                                           prot, address, rw);
@@ -221,12 +221,28 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
     hwaddr phys_addr;
     int prot;
+    int miss;
 
-    if (cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0)) {
-        return -1;
+    /* Check memory for any kind of address, since during debug the
+       gdb can ask for anything, check data tlb for address */
+    miss = cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr, 0);
+
+    /* Check instruction tlb */
+    if (miss) {
+        miss = cpu_openrisc_get_phys_addr(cpu, &phys_addr, &prot, addr,
+                                          MMU_INST_FETCH);
+    }
+
+    /* Last, fall back to a plain address */
+    if (miss) {
+        miss = cpu_openrisc_get_phys_nommu(cpu, &phys_addr, &prot, addr, 0);
     }
 
-    return phys_addr;
+    if (miss) {
+        return -1;
+    } else {
+        return phys_addr;
+    }
 }
 
 void cpu_openrisc_mmu_init(OpenRISCCPU *cpu)
index 60c31936562f03330a1548a51d87a11dfb4f5dfa..abdef5d6a51c3dc5f3efbb4716865c29e444efa9 100644 (file)
@@ -22,6 +22,7 @@
 #include "cpu.h"
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
+#include "exception.h"
 
 #define TO_SPR(group, number) (((group) << 11) + (number))
 
@@ -39,6 +40,10 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         env->vr = rb;
         break;
 
+    case TO_SPR(0, 11): /* EVBAR */
+        env->evbar = rb;
+        break;
+
     case TO_SPR(0, 16): /* NPC */
         cpu_restore_state(cs, GETPC());
         /* ??? Mirror or1ksim in not trashing delayed branch state
@@ -88,6 +93,11 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     case TO_SPR(0, 64): /* ESR */
         env->esr = rb;
         break;
+
+    case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */
+        idx = (spr - 1024);
+        env->shadow_gpr[idx / 32][idx % 32] = rb;
+
     case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
         idx = spr - TO_SPR(1, 512);
         if (!(rb & 1)) {
@@ -132,6 +142,15 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     case TO_SPR(5, 2):  /* MACHI */
         env->mac = deposit64(env->mac, 32, 32, rb);
         break;
+    case TO_SPR(8, 0):  /* PMR */
+        env->pmr = rb;
+        if (env->pmr & PMR_DME || env->pmr & PMR_SME) {
+            cpu_restore_state(cs, GETPC());
+            env->pc += 4;
+            cs->halted = 1;
+            raise_exception(cpu, EXCP_HALTED);
+        }
+        break;
     case TO_SPR(9, 0):  /* PICMR */
         env->picmr |= rb;
         break;
@@ -206,6 +225,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
     case TO_SPR(0, 4): /* IMMUCFGR */
         return env->immucfgr;
 
+    case TO_SPR(0, 11): /* EVBAR */
+        return env->evbar;
+
     case TO_SPR(0, 16): /* NPC (equals PC) */
         cpu_restore_state(cs, GETPC());
         return env->pc;
@@ -226,6 +248,16 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
     case TO_SPR(0, 64): /* ESR */
         return env->esr;
 
+    case TO_SPR(0, 128): /* COREID */
+        return 0;
+
+    case TO_SPR(0, 129): /* NUMCORES */
+        return 1;
+
+    case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */
+        idx = (spr - 1024);
+        return env->shadow_gpr[idx / 32][idx % 32];
+
     case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
         idx = spr - TO_SPR(1, 512);
         return env->tlb->dtlb[0][idx].mr;
@@ -265,6 +297,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
         return env->mac >> 32;
         break;
 
+    case TO_SPR(8, 0):  /* PMR */
+        return env->pmr;
+
     case TO_SPR(9, 0):  /* PICMR */
         return env->picmr;
 
index 7c4cbf205f37a9b3ea64ed1f76bae6c55271b88f..e49518e893e934e63423fe79d17f094ba27f92c5 100644 (file)
@@ -107,7 +107,8 @@ void openrisc_translate_init(void)
                                      "mac");
     for (i = 0; i < 32; i++) {
         cpu_R[i] = tcg_global_mem_new(cpu_env,
-                                      offsetof(CPUOpenRISCState, gpr[i]),
+                                      offsetof(CPUOpenRISCState,
+                                               shadow_gpr[0][i]),
                                       regnames[i]);
     }
     cpu_R0 = cpu_R[0];
@@ -1662,7 +1663,7 @@ void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
 
     cpu_fprintf(f, "PC=%08x\n", env->pc);
     for (i = 0; i < 32; ++i) {
-        cpu_fprintf(f, "R%02d=%08x%c", i, env->gpr[i],
+        cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
                     (i % 4) == 3 ? '\n' : ' ');
     }
 }
index f5a7f02b25f398a3beca430b0d60fef6006e6a0f..7fadfbace590bfba56bfd9ab3c3f5b5888fabc18 100755 (executable)
@@ -119,7 +119,7 @@ done
 
 
 echo
-echo === Refcout table growth tests ===
+echo === Refcount table growth tests ===
 echo
 CLUSTER_SIZE=512
 
index 59b8f74cd4aeac9d8b294cb530575c313bb167f4..86a50a2e13d4c8f7364ec0b37a3e2a430fd27d77 100644 (file)
@@ -462,7 +462,7 @@ Event: cluster_alloc; errno: 28; imm: off; once: off; write -b
 write failed: No space left on device
 No errors were found on the image.
 
-=== Refcout table growth tests ===
+=== Refcount table growth tests ===
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 
index b4aeebcc6105ab3722a50a5a25f081869a39bb82..ea2e166a4eeac4b8d92fe9e96f7fda359932068c 100644 (file)
@@ -470,7 +470,7 @@ Event: cluster_alloc; errno: 28; imm: off; once: off; write -b
 write failed: No space left on device
 No errors were found on the image.
 
-=== Refcout table growth tests ===
+=== Refcount table growth tests ===
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 
 
index acd2870bae0345bd02b14db80e0bf1bc09471ca1..7d54aeb003f9fa5018b00ae0018a3e6b53d2bb6d 100644 (file)
@@ -469,7 +469,7 @@ No errors were found on the image.
 block-backup
 
 Formatting 'TEST_DIR/t.IMGFMT.copy', fmt=IMGFMT size=4294968832 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block-\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block-j\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block-jo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block-job\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block-jobs\e[K
+(qemu) info block-jobs
 No active jobs
 === IO: pattern 195
 read 512/512 bytes at offset 3221194240
index 630cb7a114fb467f1c398fb2cdc35ace071a6f15..26c29deb514334049101a50b06b1aedfbf6d5a11 100755 (executable)
@@ -60,7 +60,8 @@ function do_run_qemu()
 
 function run_qemu()
 {
-    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_generated_node_ids
+    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu |
+        _filter_generated_node_ids | _filter_hmp
 }
 
 size=128M
@@ -231,6 +232,7 @@ echo === Leaving out required options ===
 echo
 
 run_qemu -drive driver=file
+run_qemu -drive driver=file,filename=
 run_qemu -drive driver=nbd
 run_qemu -drive driver=raw
 run_qemu -drive file.driver=file
index 7524c62025ad7471c5d11e40de90819958b589e5..4d3b1ff316b65ba92be2b67ea4442911552dfce2 100644 (file)
@@ -58,12 +58,12 @@ QEMU X.Y.Z monitor - type 'help' for more information
 
 Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+(qemu) info block
 drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
     Removable device: not locked, tray closed
     Cache mode:       writeback
     Backing file:     TEST_DIR/t.qcow2.orig (chain depth: 1)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,driver=raw,backing.file.filename=TEST_DIR/t.qcow2.orig
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=raw,backing.file.filename=TEST_DIR/t.qcow2.orig: Driver doesn't support backing files
@@ -79,11 +79,11 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.f
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: Parameter 'lazy-refcounts' expects 'on' or 'off'
@@ -103,7 +103,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy ref
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 
 === No medium ===
@@ -117,93 +117,93 @@ QEMU X.Y.Z monitor - type 'help' for more information
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 
 === Cache modes ===
 
 Testing: -drive driver=null-co,cache=none
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=directsync
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=writeback
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=writethrough
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=unsafe
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=invalid_value
 QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+(qemu) info block
 drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
     Removable device: not locked, tray closed
     Cache mode:       writeback
     Backing file:     TEST_DIR/t.qcow2.base (chain depth: 1)
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block file\e[K
+(qemu) info block file
 
 file: TEST_DIR/t.qcow2 (file)
     Cache mode:       writeback
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K
+(qemu) info block backing
 backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-file\e[K
+(qemu) info block backing-file
 
 backing-file: TEST_DIR/t.qcow2.base (file, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+(qemu) info block
 drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
     Removable device: not locked, tray closed
     Cache mode:       writethrough
     Backing file:     TEST_DIR/t.qcow2.base (chain depth: 1)
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block file\e[K
+(qemu) info block file
 
 file: TEST_DIR/t.qcow2 (file)
     Cache mode:       writeback
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K
+(qemu) info block backing
 backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-file\e[K
+(qemu) info block backing-file
 
 backing-file: TEST_DIR/t.qcow2.base (file, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+(qemu) info block
 drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
     Removable device: not locked, tray closed
     Cache mode:       writeback, ignore flushes
     Backing file:     TEST_DIR/t.qcow2.base (chain depth: 1)
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block file\e[K
+(qemu) info block file
 
 file: TEST_DIR/t.qcow2 (file)
     Cache mode:       writeback, ignore flushes
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K
+(qemu) info block backing
 backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-file\e[K
+(qemu) info block backing-file
 
 backing-file: TEST_DIR/t.qcow2.base (file, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0: invalid cache option
@@ -213,7 +213,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filenam
 
 Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 
 === Leaving out required options ===
@@ -221,6 +221,9 @@ QEMU X.Y.Z monitor - type 'help' for more information
 Testing: -drive driver=file
 QEMU_PROG: -drive driver=file: The 'file' block driver requires a file name
 
+Testing: -drive driver=file,filename=
+QEMU_PROG: -drive driver=file,filename=: The 'file' block driver requires a file name
+
 Testing: -drive driver=nbd
 QEMU_PROG: -drive driver=nbd: NBD server address missing
 
@@ -307,15 +310,15 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,throttling.bps-total=-5: bps/iops/max va
 
 Testing: -drive file=TEST_DIR/t.qcow2,bps=0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,bps=1
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,bps=1000000000000000
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,bps=1000000000000001
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=1000000000000001: bps/iops/max values must be within [0, 1000000000000000]
@@ -337,11 +340,11 @@ QEMU_PROG: -drive file.filename=foo:bar: Could not open 'foo:bar': No such file
 
 Testing: -hda file:TEST_DIR/t.qcow2
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=file:TEST_DIR/t.qcow2
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file.filename=file:TEST_DIR/t.qcow2
 QEMU_PROG: -drive file.filename=file:TEST_DIR/t.qcow2: Could not open 'file:TEST_DIR/t.qcow2': No such file or directory
@@ -353,78 +356,78 @@ wrote 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,if=none,id=drive0 -snapshot
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,if=none,id=drive0 -snapshot
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=file:TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 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,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 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=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x3\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x33 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) c\e[K\e[Dco\e[K\e[D\e[Dcom\e[K\e[D\e[D\e[Dcomm\e[K\e[D\e[D\e[D\e[Dcommi\e[K\e[D\e[D\e[D\e[D\e[Dcommit\e[K\e[D\e[D\e[D\e[D\e[D\e[Dcommit \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit drive0\e[K
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) commit drive0
+(qemu) quit
 
 read 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
index c6f4eef215239d4bb0372224da7f3632f7dc9c27..76d7205460f119e9169cd1107395db46711af82c 100644 (file)
@@ -58,12 +58,12 @@ QEMU X.Y.Z monitor - type 'help' for more information
 
 Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+(qemu) info block
 drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
     Removable device: not locked, tray closed
     Cache mode:       writeback
     Backing file:     TEST_DIR/t.qcow2.orig (chain depth: 1)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,driver=raw,backing.file.filename=TEST_DIR/t.qcow2.orig
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=raw,backing.file.filename=TEST_DIR/t.qcow2.orig: Driver doesn't support backing files
@@ -79,11 +79,11 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.f
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: Parameter 'lazy-refcounts' expects 'on' or 'off'
@@ -103,23 +103,23 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy ref
 
 Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 
 === No medium ===
 
 Testing: -drive if=floppy
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive if=ide,media=cdrom
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive if=scsi,media=cdrom
 QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -drive if=scsi,media=cdrom: warning: bus=0,unit=0 is deprecated with this machine type
-q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+quit
 
 Testing: -drive if=ide
 QEMU X.Y.Z monitor - type 'help' for more information
@@ -137,11 +137,11 @@ QEMU X.Y.Z monitor - type 'help' for more information
 
 Testing: -drive if=none,id=disk -device ide-cd,drive=disk
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive if=none,id=disk -device ide-drive,drive=disk
 QEMU X.Y.Z monitor - type 'help' for more information
@@ -166,16 +166,16 @@ QEMU X.Y.Z monitor - type 'help' for more information
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
 QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on: warning: bus=0,unit=0 is deprecated with this machine type
-q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
 QEMU X.Y.Z monitor - type 'help' for more information
@@ -185,19 +185,19 @@ QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
 Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
 QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on: warning: bus=0,unit=0 is deprecated with this machine type
-q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 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) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 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) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 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
@@ -211,97 +211,97 @@ QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
 
 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) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 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) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 
 === Cache modes ===
 
 Testing: -drive driver=null-co,cache=none
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=directsync
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=writeback
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=writethrough
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=unsafe
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive driver=null-co,cache=invalid_value
 QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+(qemu) info block
 drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
     Removable device: not locked, tray closed
     Cache mode:       writeback
     Backing file:     TEST_DIR/t.qcow2.base (chain depth: 1)
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block file\e[K
+(qemu) info block file
 
 file: TEST_DIR/t.qcow2 (file)
     Cache mode:       writeback
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K
+(qemu) info block backing
 backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-file\e[K
+(qemu) info block backing-file
 
 backing-file: TEST_DIR/t.qcow2.base (file, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+(qemu) info block
 drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
     Removable device: not locked, tray closed
     Cache mode:       writethrough
     Backing file:     TEST_DIR/t.qcow2.base (chain depth: 1)
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block file\e[K
+(qemu) info block file
 
 file: TEST_DIR/t.qcow2 (file)
     Cache mode:       writeback
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K
+(qemu) info block backing
 backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-file\e[K
+(qemu) info block backing-file
 
 backing-file: TEST_DIR/t.qcow2.base (file, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K
+(qemu) info block
 drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
     Removable device: not locked, tray closed
     Cache mode:       writeback, ignore flushes
     Backing file:     TEST_DIR/t.qcow2.base (chain depth: 1)
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block file\e[K
+(qemu) info block file
 
 file: TEST_DIR/t.qcow2 (file)
     Cache mode:       writeback, ignore flushes
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K
+(qemu) info block backing
 backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) i\e[K\e[Din\e[K\e[D\e[Dinf\e[K\e[D\e[D\e[Dinfo\e[K\e[D\e[D\e[D\e[Dinfo \e[K\e[D\e[D\e[D\e[D\e[Dinfo b\e[K\e[D\e[D\e[D\e[D\e[D\e[Dinfo bl\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo blo\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo bloc\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block b\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block ba\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block bac\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block back\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backin\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-f\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-fil\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dinfo block backing-file\e[K
+(qemu) info block backing-file
 
 backing-file: TEST_DIR/t.qcow2.base (file, read-only)
     Cache mode:       writeback, ignore flushes
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0: invalid cache option
@@ -311,7 +311,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filenam
 
 Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 
 === Leaving out required options ===
@@ -319,6 +319,9 @@ QEMU X.Y.Z monitor - type 'help' for more information
 Testing: -drive driver=file
 QEMU_PROG: -drive driver=file: The 'file' block driver requires a file name
 
+Testing: -drive driver=file,filename=
+QEMU_PROG: -drive driver=file,filename=: The 'file' block driver requires a file name
+
 Testing: -drive driver=nbd
 QEMU_PROG: -drive driver=nbd: NBD server address missing
 
@@ -405,15 +408,15 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,throttling.bps-total=-5: bps/iops/max va
 
 Testing: -drive file=TEST_DIR/t.qcow2,bps=0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,bps=1
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,bps=1000000000000000
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,bps=1000000000000001
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=1000000000000001: bps/iops/max values must be within [0, 1000000000000000]
@@ -435,11 +438,11 @@ QEMU_PROG: -drive file.filename=foo:bar: Could not open 'foo:bar': No such file
 
 Testing: -hda file:TEST_DIR/t.qcow2
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=file:TEST_DIR/t.qcow2
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file.filename=file:TEST_DIR/t.qcow2
 QEMU_PROG: -drive file.filename=file:TEST_DIR/t.qcow2: Could not open 'file:TEST_DIR/t.qcow2': No such file or directory
@@ -451,78 +454,78 @@ wrote 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,if=none,id=drive0 -snapshot
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,if=none,id=drive0 -snapshot
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=file:TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 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,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x2\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x22 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x22 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 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=on,if=none,id=drive0
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqe\e[K\e[D\e[Dqem\e[K\e[D\e[D\e[Dqemu\e[K\e[D\e[D\e[D\e[Dqemu-\e[K\e[D\e[D\e[D\e[D\e[Dqemu-i\e[K\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "w\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "wri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "writ\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x3\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0 \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0 4\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0 4k\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dqemu-io drive0 "write -P 0x33 0 4k"\e[K
+(qemu) qemu-io drive0 "write -P 0x33 0 4k"
 wrote 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) c\e[K\e[Dco\e[K\e[D\e[Dcom\e[K\e[D\e[D\e[Dcomm\e[K\e[D\e[D\e[D\e[Dcommi\e[K\e[D\e[D\e[D\e[D\e[Dcommit\e[K\e[D\e[D\e[D\e[D\e[D\e[Dcommit \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit d\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit dr\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit dri\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit driv\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit drive\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit drive0\e[K
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) commit drive0
+(qemu) quit
 
 read 4096/4096 bytes at offset 0
 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
index 364166d3b25a04d60f01cab7d32887067abd48cf..c2116a3088647246f413f46f04b3dd2e2bf70ffd 100755 (executable)
@@ -42,16 +42,18 @@ _supported_fmt qcow2
 _supported_proto generic
 _supported_os Linux
 
+# Intentionally create an unaligned image
 IMGOPTS="compat=1.1"
-IMG_SIZE=64M
+IMG_SIZE=$((64 * 1024 * 1024 + 512))
 
 echo
-echo "=== Testing snapshotting an image with zero clusters ==="
+echo "=== Testing cluster discards ==="
 echo
 _make_test_img $IMG_SIZE
-# Write some normal clusters, zero them (creating preallocated zero clusters)
-# and discard those
-$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "discard 0 256k" "$TEST_IMG" \
+# Write some normal clusters, zero some of them (creating preallocated
+# zero clusters) and discard everything. Everything should now read as 0.
+$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "write 64M 512" \
+        -c "discard 0 $IMG_SIZE" -c "read -P 0 0 $IMG_SIZE" "$TEST_IMG" \
          | _filter_qemu_io
 # Check the image (there shouldn't be any leaks)
 _check_test_img
index 7bc9a107d55f43c368326ddd68b34aa87eeb8575..7c1f31a1b19ed9747c2111a8cfc09c2a70eb15ab 100644 (file)
@@ -1,13 +1,17 @@
 QA output created by 066
 
-=== Testing snapshotting an image with zero clusters ===
+=== Testing cluster discards ===
 
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67109376
 wrote 262144/262144 bytes at offset 0
 256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 262144/262144 bytes at offset 0
 256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-discard 262144/262144 bytes at offset 0
-256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 67108864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+discard 67109376/67109376 bytes at offset 0
+64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 67109376/67109376 bytes at offset 0
+64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 No errors were found on the image.
 *** done
index 68f6e825d95051270de9f26727dd4a8f6128865f..9c1687d01d329d84a100255c44960d4851524bc2 100755 (executable)
@@ -62,11 +62,11 @@ esac
 # Give qemu some time to boot before saving the VM state
 bash -c 'sleep 1; echo -e "savevm 0\nquit"' |\
     $QEMU $platform_parm -nographic -monitor stdio -serial none -hda "$TEST_IMG" |\
-    _filter_qemu
+    _filter_qemu | _filter_hmp
 # Now try to continue from that VM state (this should just work)
 echo quit |\
     $QEMU $platform_parm -nographic -monitor stdio -serial none -hda "$TEST_IMG" -loadvm 0 |\
-    _filter_qemu
+    _filter_qemu | _filter_hmp
 
 # success, all done
 echo "*** done"
index 84f19b4ffdb32e12f8ab261f0dede7bcf14e010d..0fa5340c22a570728c4231d79fd0e243077055df 100644 (file)
@@ -4,8 +4,8 @@ QA output created by 068
 
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) s\e[K\e[Dsa\e[K\e[D\e[Dsav\e[K\e[D\e[D\e[Dsave\e[K\e[D\e[D\e[D\e[Dsavev\e[K\e[D\e[D\e[D\e[D\e[Dsavevm\e[K\e[D\e[D\e[D\e[D\e[D\e[Dsavevm \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dsavevm 0\e[K
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) savevm 0
+(qemu) quit
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 *** done
index 6161633a52f4f2878df5610627006cdcd9dd2bfb..3b496a3918aaa071b8663d3b38b71aa10b0282d6 100755 (executable)
@@ -81,7 +81,8 @@ for fmt in qcow qcow2 qed vdi vmdk vpc; do
 
     # This first test should fail: The image format was probed, we may not
     # write an image header at the start of the image
-    run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR"
+    run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" |
+        _filter_block_job_len
     $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
 
 
@@ -104,7 +105,8 @@ for sample_img in empty.bochs iotest-dirtylog-10G-4M.vhdx parallels-v1 \
     _make_test_img 64M
     bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src"
 
-    run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" | _filter_block_job_offset
+    run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" |
+        _filter_block_job_offset | _filter_block_job_len
     $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
 
     run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY"
index 55fe536d5652127ee3981a79b27e7dfd520961a2..dc02f9eefaea10b0284f3c65452d8da1891566d3 100644 (file)
@@ -10,7 +10,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -31,7 +31,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 512, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 512, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -52,7 +52,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 262144, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 262144, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -73,7 +73,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -94,7 +94,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -115,7 +115,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -135,7 +135,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -155,7 +155,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -175,7 +175,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -195,7 +195,7 @@ Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
index 98814de5d63ae2e80f2b6ff65caabf28fad19ae4..9317d801adc4672e2016a59cb70e03fa95775af7 100644 (file)
@@ -61,8 +61,8 @@ read 65536/65536 bytes at offset 4194304
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 read 65536/65536 bytes at offset 8388608
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-qemu-img: -B makes no sense when concatenating multiple input images
-qemu-img: -B makes no sense when concatenating multiple input images
+qemu-img: Having a backing file for the target makes no sense when concatenating multiple input images
+qemu-img: Having a backing file for the target makes no sense when concatenating multiple input images
 
 === Compression with misaligned allocations and image sizes ===
 
index ae95b5027aed8d367af6c11c8175f9d63cd7d0e0..93020c328ee8518cc971ccb6d71d891957a9cd58 100644 (file)
@@ -9,14 +9,14 @@ virtual size: 64M (67108864 bytes)
 === HMP commit ===
 
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) c\e[K\e[Dco\e[K\e[D\e[Dcom\e[K\e[D\e[D\e[Dcomm\e[K\e[D\e[D\e[D\e[Dcommi\e[K\e[D\e[D\e[D\e[D\e[Dcommit\e[K\e[D\e[D\e[D\e[D\e[D\e[Dcommit \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit t\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit te\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit tes\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit test\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit testd\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit testdi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit testdis\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit testdisk\e[K
+(qemu) commit testdisk
 (qemu) 
 image: TEST_DIR/t.IMGFMT
 file format: IMGFMT
 virtual size: 64M (67108864 bytes)
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.orig backing_fmt=raw
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) c\e[K\e[Dco\e[K\e[D\e[Dcom\e[K\e[D\e[D\e[Dcomm\e[K\e[D\e[D\e[D\e[Dcommi\e[K\e[D\e[D\e[D\e[D\e[Dcommit\e[K\e[D\e[D\e[D\e[D\e[D\e[Dcommit \e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit t\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit te\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit tes\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit test\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit testd\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit testdi\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit testdis\e[K\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[D\e[Dcommit testdisk\e[K
+(qemu) commit testdisk
 (qemu) 
 image: TEST_DIR/t.IMGFMT
 file format: IMGFMT
index 29c0606bd7a63f156be0e3c1c5682cc50a9994f7..9a5b713256773027928e64c603c11dd1c25dfc98 100755 (executable)
@@ -62,7 +62,7 @@ function do_run_qemu()
 
 function run_qemu()
 {
-    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu
+    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp
 }
 
 size=128M
index 600beca8fba9b374f9d20c3372f5a226d742aa51..3667e38def8aa4881474e5263578650282b010a9 100644 (file)
@@ -7,23 +7,23 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=none
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=directsync
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 
 Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value: invalid cache option
index 1eca0e899059a0c72b356e2910f627ec6c819cfc..e6c6bc4a4f42385b3d17d8d7aa6bea820aeb3249 100755 (executable)
@@ -43,7 +43,8 @@ _supported_proto generic
 _supported_os Linux
 
 _make_test_img 1M
-echo quit | $QEMU -nographic -hda "$TEST_IMG" -incoming 'exec:true' -snapshot -serial none -monitor stdio | _filter_qemu
+echo quit | $QEMU -nographic -hda "$TEST_IMG" -incoming 'exec:true' -snapshot -serial none -monitor stdio |
+    _filter_qemu | _filter_hmp
 
 # success, all done
 echo "*** done"
index 75b5c8ac36ebbac7ba75c024797b52f4c68fc3c5..9a90009e44e3c22b99e7ee41ce318deb7b2fbd72 100644 (file)
@@ -1,5 +1,5 @@
 QA output created by 145
 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
 QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) q\e[K\e[Dqu\e[K\e[D\e[Dqui\e[K\e[D\e[D\e[Dquit\e[K
+(qemu) quit
 *** done
diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181
new file mode 100755 (executable)
index 0000000..e969a2a
--- /dev/null
@@ -0,0 +1,119 @@
+#!/bin/bash
+#
+# Test postcopy live migration with shared storage
+#
+# Copyright (C) 2017 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=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1       # failure is the default!
+
+MIG_SOCKET="${TEST_DIR}/migrate"
+
+_cleanup()
+{
+    rm -f "${MIG_SOCKET}"
+       _cleanup_test_img
+    _cleanup_qemu
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt generic
+_supported_proto generic
+_supported_os Linux
+
+size=64M
+_make_test_img $size
+
+echo
+echo === Starting VMs ===
+echo
+
+qemu_comm_method="monitor"
+
+_launch_qemu \
+    -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk
+src=$QEMU_HANDLE
+
+_launch_qemu \
+    -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk \
+    -incoming "unix:${MIG_SOCKET}"
+dest=$QEMU_HANDLE
+
+echo
+echo === Write something on the source ===
+echo
+
+silent=
+_send_qemu_cmd $src 'qemu-io disk "write -P 0x55 0 64k"' "(qemu)"
+_send_qemu_cmd $src "" "ops/sec"
+_send_qemu_cmd $src 'qemu-io disk "read -P 0x55 0 64k"' "(qemu)"
+_send_qemu_cmd $src "" "ops/sec"
+
+echo
+echo === Do postcopy migration to destination ===
+echo
+
+# Slow down migration so much that it definitely won't finish before we can
+# switch to postcopy
+silent=yes
+_send_qemu_cmd $src 'migrate_set_speed 4k' "(qemu)"
+_send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)"
+_send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)"
+_send_qemu_cmd $src 'migrate_start_postcopy' "(qemu)"
+
+QEMU_COMM_TIMEOUT=1 qemu_cmd_repeat=10 silent=yes \
+    _send_qemu_cmd $src "info migrate" "completed\|failed"
+silent=yes _send_qemu_cmd $src "" "(qemu)"
+
+echo
+echo === Do some I/O on the destination ===
+echo
+
+# It is important that we use the BlockBackend of the guest device here instead
+# of the node name, which would create a new BlockBackend and not test whether
+# the guest has the necessary permissions to access the image now
+silent=
+_send_qemu_cmd $dest 'qemu-io disk "read -P 0x55 0 64k"' "(qemu)"
+_send_qemu_cmd $dest "" "ops/sec"
+_send_qemu_cmd $dest 'qemu-io disk "write -P 0x66 1M 64k"' "(qemu)"
+_send_qemu_cmd $dest "" "ops/sec"
+
+echo
+echo === Shut down and check image ===
+echo
+
+_send_qemu_cmd $src 'quit' ""
+_send_qemu_cmd $dest 'quit' ""
+wait=1 _cleanup_qemu
+
+_check_test_img
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/181.out b/tests/qemu-iotests/181.out
new file mode 100644 (file)
index 0000000..6534ba2
--- /dev/null
@@ -0,0 +1,38 @@
+QA output created by 181
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+
+=== Starting VMs ===
+
+
+=== Write something on the source ===
+
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qemu-io disk "write -P 0x55 0 64k"
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) 
+(qemu) qemu-io disk "read -P 0x55 0 64k"
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Do postcopy migration to destination ===
+
+
+=== Do some I/O on the destination ===
+
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qemu-io disk "read -P 0x55 0 64k"
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) 
+(qemu) qemu-io disk "write -P 0x66 1M 64k"
+wrote 65536/65536 bytes at offset 1048576
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Shut down and check image ===
+
+(qemu) quit
+(qemu) 
+(qemu) quit
+No errors were found on the image.
+*** done
index 9c6f9721e59938c57ec6671dce53660f56e729e6..f2a7199c4b8fe0a85878101b6a61e15f0f04c089 100644 (file)
@@ -86,7 +86,8 @@ s/ .*//p
     elif $xgroup
     then
         # arg after -x
-        [ ! -s $tmp.list ] && ls [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] >$tmp.list 2>/dev/null
+        # Populate $tmp.list with all tests
+        awk '/^[0-9]{3,}/ {print $1}' "${source_iotests}/group" > $tmp.list 2>/dev/null
         group_list=`sed -n <"$source_iotests/group" -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
 s/ .*//p
 }'`
@@ -138,7 +139,7 @@ common options
     -v                  verbose
     -d                  debug
 
-check options
+image format options
     -raw                test raw (default)
     -bochs              test bochs
     -cloop              test cloop
@@ -150,14 +151,18 @@ check options
     -vpc                test vpc
     -vhdx               test vhdx
     -vmdk               test vmdk
+    -luks               test luks
+
+image protocol options
     -file               test file (default)
     -rbd                test rbd
     -sheepdog           test sheepdog
     -nbd                test nbd
     -ssh                test ssh
     -nfs                test nfs
-    -luks               test luks
     -vxhs               test vxhs
+
+other options
     -xdiff              graphical mode diff
     -nocache            use O_DIRECT on backing file
     -misalign           misalign memory allocations
index c4b51b3509945660c5ac27c2e16c3d2bbb559a23..d1b45f544740126f0221f3ae347099e0eb88c9da 100644 (file)
@@ -75,18 +75,12 @@ _fatal()
     exit 1
 }
 
-export PERL_PROG="`set_prog_path perl`"
-[ "$PERL_PROG" = "" ] && _fatal "perl not found"
-
 export AWK_PROG="`set_prog_path awk`"
 [ "$AWK_PROG" = "" ] && _fatal "awk not found"
 
 export SED_PROG="`set_prog_path sed`"
 [ "$SED_PROG" = "" ] && _fatal "sed not found"
 
-export BC_PROG="`set_prog_path bc`"
-[ "$BC_PROG" = "" ] && _fatal "bc not found"
-
 export PS_ALL_FLAGS="-ef"
 
 if [ -z "$QEMU_PROG" ]; then
@@ -223,23 +217,5 @@ fi
 
 export SAMPLE_IMG_DIR
 
-_readlink()
-{
-    if [ $# -ne 1 ]; then
-        echo "Usage: _readlink filename" 1>&2
-        exit 1
-    fi
-
-    perl -e "\$in=\"$1\";" -e '
-    $lnk = readlink($in);
-    if ($lnk =~ m!^/.*!) {
-        print "$lnk\n";
-    }
-    else {
-        chomp($dir = `dirname $in`);
-        print "$dir/$lnk\n";
-    }'
-}
-
 # make sure this script returns success
 true
index c9a2d5c59598057e708b45b6a440501b2884ca20..f58548dc446044ab361bccf43d62d7260fe883fb 100644 (file)
@@ -86,12 +86,25 @@ _filter_qmp()
         -e '    QMP_VERSION'
 }
 
+# readline makes HMP command strings so long that git complains
+_filter_hmp()
+{
+    sed -e $'s/^\\((qemu) \\)\\?.*\e\\[D/\\1/g' \
+        -e $'s/\e\\[K//g'
+}
+
 # replace block job offset
 _filter_block_job_offset()
 {
     sed -e 's/, "offset": [0-9]\+,/, "offset": OFFSET,/'
 }
 
+# replace block job len
+_filter_block_job_len()
+{
+    sed -e 's/, "len": [0-9]\+,/, "len": LEN,/g'
+}
+
 # replace driver-specific options in the "Formatting..." line
 _filter_img_create()
 {
index 42787896af4f2c008327c99540375ba24f45a69d..7a78a0099959f93ad3d3386afec56345946ab617 100644 (file)
@@ -59,7 +59,7 @@ function _timed_wait_for()
     do
         if [ -z "${silent}" ]; then
             echo "${resp}" | _filter_testdir | _filter_qemu \
-                           | _filter_qemu_io | _filter_qmp
+                           | _filter_qemu_io | _filter_qmp | _filter_hmp
         fi
         grep -q "${*}" < <(echo ${resp})
         if [ $? -eq 0 ]; then
@@ -217,7 +217,7 @@ function _cleanup_qemu()
 
         if [ -n "${wait}" ]; then
             cat <&${QEMU_OUT[$i]} | _filter_testdir | _filter_qemu \
-                                  | _filter_qemu_io | _filter_qmp
+                                  | _filter_qemu_io | _filter_qmp | _filter_hmp
         fi
         rm -f "${QEMU_FIFO_IN}_${i}" "${QEMU_FIFO_OUT}_${i}"
         eval "exec ${QEMU_IN[$i]}<&-"   # close file descriptors
index 62529eed6e91dc745a12b1bc9bed4bdba379cbd9..9fd3130bde06927c5460f17689dae3ff07632259 100644 (file)
@@ -171,7 +171,9 @@ _make_test_img()
 
     # Start an NBD server on the image file, which is what we'll be talking to
     if [ $IMGPROTO = "nbd" ]; then
-        eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT  $TEST_IMG_FILE >/dev/null &"
+        # Pass a sufficiently high number to -e that should be enough for all
+        # tests
+        eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT -e 42  $TEST_IMG_FILE >/dev/null &"
         sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
     fi
 
index 43142ddfcf17b716e47ce4314568f71c7dd603b9..893962d41e9d1825b4b6d37c44a35dda307a7f73 100644 (file)
 174 auto
 175 auto quick
 176 rw auto backing
+181 rw auto migration
index ed88cda6d6692fdfcf2d8e6c88531e3e2d111d02..830f912f99f33c63ca9cb7cff68b16cae3623e17 100644 (file)
@@ -41,6 +41,8 @@ static QTAILQ_HEAD(QemuInputEventQueueHead, QemuInputEventQueue) kbd_queue =
     QTAILQ_HEAD_INITIALIZER(kbd_queue);
 static QEMUTimer *kbd_timer;
 static uint32_t kbd_default_delay_ms = 10;
+static uint32_t queue_count;
+static uint32_t queue_limit = 1024;
 
 QemuInputHandlerState *qemu_input_handler_register(DeviceState *dev,
                                                    QemuInputHandler *handler)
@@ -268,6 +270,7 @@ static void qemu_input_queue_process(void *opaque)
             break;
         }
         QTAILQ_REMOVE(queue, item, node);
+        queue_count--;
         g_free(item);
     }
 }
@@ -282,6 +285,7 @@ static void qemu_input_queue_delay(struct QemuInputEventQueueHead *queue,
     item->delay_ms = delay_ms;
     item->timer = timer;
     QTAILQ_INSERT_TAIL(queue, item, node);
+    queue_count++;
 
     if (start_timer) {
         timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
@@ -298,6 +302,7 @@ static void qemu_input_queue_event(struct QemuInputEventQueueHead *queue,
     item->src = src;
     item->evt = evt;
     QTAILQ_INSERT_TAIL(queue, item, node);
+    queue_count++;
 }
 
 static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
@@ -306,6 +311,7 @@ static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue)
 
     item->type = QEMU_INPUT_QUEUE_SYNC;
     QTAILQ_INSERT_TAIL(queue, item, node);
+    queue_count++;
 }
 
 void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt)
@@ -381,7 +387,7 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
         qemu_input_event_send(src, evt);
         qemu_input_event_sync();
         qapi_free_InputEvent(evt);
-    } else {
+    } else if (queue_count < queue_limit) {
         qemu_input_queue_event(&kbd_queue, src, evt);
         qemu_input_queue_sync(&kbd_queue);
     }
@@ -405,12 +411,18 @@ void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
 
 void qemu_input_event_send_key_delay(uint32_t delay_ms)
 {
+    if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
+        return;
+    }
+
     if (!kbd_timer) {
         kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process,
                                  &kbd_queue);
     }
-    qemu_input_queue_delay(&kbd_queue, kbd_timer,
-                           delay_ms ? delay_ms : kbd_default_delay_ms);
+    if (queue_count < queue_limit) {
+        qemu_input_queue_delay(&kbd_queue, kbd_timer,
+                               delay_ms ? delay_ms : kbd_default_delay_ms);
+    }
 }
 
 InputEvent *qemu_input_event_new_btn(InputButton btn, bool down)
index 5527100a01269ed0686411949d6fbe49b4581815..405dd1a1d771fcacb11d4098a02ce27e9cf827af 100644 (file)
@@ -227,6 +227,12 @@ static QemuOptsList machine_opts = {
             .name = "dea-key-wrap",
             .type = QEMU_OPT_BOOL,
             .help = "enable/disable DEA key wrapping using the CPACF wrapping key",
+        },{
+            .name = "loadparm",
+            .type = QEMU_OPT_STRING,
+            .help = "Up to 8 chars in set of [A-Za-z0-9. ](lower case chars"
+                    " converted to upper case) to pass to machine"
+                    " loader, boot manager, and guest kernel",
         },
         { /* End of list */ }
     }
index f745233763aa8417ebf7599e6c2ca50271d60db1..3c2223c1a21cd3173fe86cf96e44fce3e3bb9299 100644 (file)
@@ -88,6 +88,9 @@ static void progress_dummy_init(void)
     action.sa_handler = sigusr_print;
     action.sa_flags = 0;
     sigaction(SIGUSR1, &action, NULL);
+#ifdef SIGINFO
+    sigaction(SIGINFO, &action, NULL);
+#endif
 
     /*
      * SIGUSR1 is SIG_IPI and gets blocked in qemu_init_main_loop(). In the
diff --git a/vl.c b/vl.c
index 150e8ebf1728d5e5e0a1494454a1b596bcd3c2ee..560288fe0caf0cc349e7f69caf9f9356130af47b 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -3231,6 +3231,8 @@ int main(int argc, char **argv, char **envp)
                         }
                     }
                 }
+                error_report("'-hdachs' is deprecated, please use '-device"
+                             " ide-hd,cyls=c,heads=h,secs=s,...' instead");
                 break;
             case QEMU_OPTION_numa:
                 opts = qemu_opts_parse_noisily(qemu_find_opts("numa"),