diff options
-rw-r--r-- | block.c | 27 | ||||
-rw-r--r-- | block/sheepdog.c | 2 | ||||
-rw-r--r-- | blockdev.c | 6 | ||||
-rw-r--r-- | cpus.c | 20 | ||||
-rw-r--r-- | hmp-commands.hx | 20 | ||||
-rw-r--r-- | hmp.c | 28 | ||||
-rw-r--r-- | hmp.h | 1 | ||||
-rw-r--r-- | hw/ide/ahci.c | 8 | ||||
-rw-r--r-- | hw/ide/core.c | 9 | ||||
-rw-r--r-- | hw/ide/internal.h | 1 | ||||
-rw-r--r-- | include/block/block.h | 5 | ||||
-rw-r--r-- | include/sysemu/sysemu.h | 4 | ||||
-rw-r--r-- | migration.c | 17 | ||||
-rw-r--r-- | qapi-schema.json | 7 | ||||
-rw-r--r-- | qemu-img.c | 4 | ||||
-rw-r--r-- | qmp-commands.hx | 6 | ||||
-rw-r--r-- | stubs/vm-stop.c | 2 | ||||
-rwxr-xr-x | tests/qemu-iotests/051 | 12 | ||||
-rw-r--r-- | tests/qemu-iotests/051.out | 121 | ||||
-rwxr-xr-x | tests/qemu-iotests/055 | 36 | ||||
-rw-r--r-- | tests/qemu-iotests/common.filter | 2 |
21 files changed, 262 insertions, 76 deletions
@@ -417,7 +417,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options) { BlockDriver *drv; - drv = bdrv_find_protocol(filename); + drv = bdrv_find_protocol(filename, true); if (drv == NULL) { return -ENOENT; } @@ -482,7 +482,8 @@ static BlockDriver *find_hdev_driver(const char *filename) return drv; } -BlockDriver *bdrv_find_protocol(const char *filename) +BlockDriver *bdrv_find_protocol(const char *filename, + bool allow_protocol_prefix) { BlockDriver *drv1; char protocol[128]; @@ -503,9 +504,10 @@ BlockDriver *bdrv_find_protocol(const char *filename) return drv1; } - if (!path_has_protocol(filename)) { + if (!path_has_protocol(filename) || !allow_protocol_prefix) { return bdrv_find_format("file"); } + p = strchr(filename, ':'); assert(p != NULL); len = p - filename; @@ -784,6 +786,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, BlockDriverState *bs; BlockDriver *drv; const char *drvname; + bool allow_protocol_prefix = false; int ret; /* NULL means an empty set of options */ @@ -800,6 +803,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, filename = qdict_get_try_str(options, "filename"); } else if (filename && !qdict_haskey(options, "filename")) { qdict_put(options, "filename", qstring_from_str(filename)); + allow_protocol_prefix = true; } else { qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't specify 'file' and " "'filename' options at the same time"); @@ -813,7 +817,10 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR)); qdict_del(options, "driver"); } else if (filename) { - drv = bdrv_find_protocol(filename); + drv = bdrv_find_protocol(filename, allow_protocol_prefix); + if (!drv) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, "Unknown protocol"); + } } else { qerror_report(ERROR_CLASS_GENERIC_ERROR, "Must specify either driver or file"); @@ -2903,13 +2910,19 @@ int bdrv_get_flags(BlockDriverState *bs) return bs->open_flags; } -void bdrv_flush_all(void) +int bdrv_flush_all(void) { BlockDriverState *bs; + int result = 0; QTAILQ_FOREACH(bs, &bdrv_states, list) { - bdrv_flush(bs); + int ret = bdrv_flush(bs); + if (ret < 0 && !result) { + result = ret; + } } + + return result; } int bdrv_has_zero_init_1(BlockDriverState *bs) @@ -4452,7 +4465,7 @@ void bdrv_img_create(const char *filename, const char *fmt, return; } - proto_drv = bdrv_find_protocol(filename); + proto_drv = bdrv_find_protocol(filename, true); if (!proto_drv) { error_setg(errp, "Unknown protocol '%s'", filename); return; diff --git a/block/sheepdog.c b/block/sheepdog.c index b397b5b4d3..6a41ad9b3c 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1510,7 +1510,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) BlockDriver *drv; /* Currently, only Sheepdog backing image is supported. */ - drv = bdrv_find_protocol(backing_file); + drv = bdrv_find_protocol(backing_file, true); if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) { error_report("backing_file must be a sheepdog image"); ret = -EINVAL; diff --git a/blockdev.c b/blockdev.c index b3a57e0c1d..c5abd65182 100644 --- a/blockdev.c +++ b/blockdev.c @@ -936,6 +936,7 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp) qmp_drive_backup(backup->device, backup->target, backup->has_format, backup->format, + backup->sync, backup->has_mode, backup->mode, backup->has_speed, backup->speed, backup->has_on_source_error, backup->on_source_error, @@ -1421,6 +1422,7 @@ void qmp_block_commit(const char *device, void qmp_drive_backup(const char *device, const char *target, bool has_format, const char *format, + enum MirrorSyncMode sync, bool has_mode, enum NewImageMode mode, bool has_speed, int64_t speed, bool has_on_source_error, BlockdevOnError on_source_error, @@ -1435,6 +1437,10 @@ void qmp_drive_backup(const char *device, const char *target, int64_t size; int ret; + if (sync != MIRROR_SYNC_MODE_FULL) { + error_setg(errp, "only sync mode 'full' is currently supported"); + return; + } if (!has_speed) { speed = 0; } @@ -434,17 +434,21 @@ bool cpu_is_stopped(CPUState *cpu) return !runstate_is_running() || cpu->stopped; } -static void do_vm_stop(RunState state) +static int do_vm_stop(RunState state) { + int ret = 0; + if (runstate_is_running()) { cpu_disable_ticks(); pause_all_vcpus(); runstate_set(state); vm_state_notify(0, state); bdrv_drain_all(); - bdrv_flush_all(); + ret = bdrv_flush_all(); monitor_protocol_event(QEVENT_STOP, NULL); } + + return ret; } static bool cpu_can_run(CPUState *cpu) @@ -1070,7 +1074,7 @@ void cpu_stop_current(void) } } -void vm_stop(RunState state) +int vm_stop(RunState state) { if (qemu_in_vcpu_thread()) { qemu_system_vmstop_request(state); @@ -1079,19 +1083,21 @@ void vm_stop(RunState state) * vm_stop() has been requested. */ cpu_stop_current(); - return; + return 0; } - do_vm_stop(state); + + return do_vm_stop(state); } /* does a state transition even if the VM is already stopped, current state is forgotten forever */ -void vm_stop_force_state(RunState state) +int vm_stop_force_state(RunState state) { if (runstate_is_running()) { - vm_stop(state); + return vm_stop(state); } else { runstate_set(state); + return 0; } } diff --git a/hmp-commands.hx b/hmp-commands.hx index d1cdcfb71b..8c6b91a9c7 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1059,6 +1059,26 @@ using the specified target. ETEXI { + .name = "drive_backup", + .args_type = "reuse:-n,full:-f,device:B,target:s,format:s?", + .params = "[-n] [-f] device target [format]", + .help = "initiates a point-in-time\n\t\t\t" + "copy for a device. The device's contents are\n\t\t\t" + "copied to the new image file, excluding data that\n\t\t\t" + "is written after the command is started.\n\t\t\t" + "The -n flag requests QEMU to reuse the image found\n\t\t\t" + "in new-image-file, instead of recreating it from scratch.\n\t\t\t" + "The -f flag requests QEMU to copy the whole disk,\n\t\t\t" + "so that the result does not need a backing file.\n\t\t\t", + .mhandler.cmd = hmp_drive_backup, + }, +STEXI +@item drive_backup +@findex drive_backup +Start a point-in-time copy of a block device to a specificed target. +ETEXI + + { .name = "drive_add", .args_type = "pci_addr:s,opts:s", .params = "[[<domain>:]<bus>:]<slot>\n" @@ -907,6 +907,34 @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &errp); } +void hmp_drive_backup(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_str(qdict, "target"); + const char *format = qdict_get_try_str(qdict, "format"); + int reuse = qdict_get_try_bool(qdict, "reuse", 0); + int full = qdict_get_try_bool(qdict, "full", 0); + enum NewImageMode mode; + Error *errp = NULL; + + if (!filename) { + error_set(&errp, QERR_MISSING_PARAMETER, "target"); + hmp_handle_error(mon, &errp); + return; + } + + if (reuse) { + mode = NEW_IMAGE_MODE_EXISTING; + } else { + mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; + } + + qmp_drive_backup(device, filename, !!format, format, + full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, + true, mode, false, 0, false, 0, false, 0, &errp); + hmp_handle_error(mon, &errp); +} + void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) { const char *device = qdict_get_str(qdict, "device"); @@ -55,6 +55,7 @@ void hmp_balloon(Monitor *mon, const QDict *qdict); void hmp_block_resize(Monitor *mon, const QDict *qdict); void hmp_snapshot_blkdev(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_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 97eddec920..1d863b5784 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1107,9 +1107,14 @@ static int ahci_dma_add_status(IDEDMA *dma, int status) static int ahci_dma_set_inactive(IDEDMA *dma) { + return 0; +} + +static int ahci_async_cmd_done(IDEDMA *dma) +{ AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); - DPRINTF(ad->port_no, "dma done\n"); + DPRINTF(ad->port_no, "async cmd done\n"); /* update d2h status */ ahci_write_fis_d2h(ad, NULL); @@ -1144,6 +1149,7 @@ static const IDEDMAOps ahci_dma_ops = { .set_unit = ahci_dma_set_unit, .add_status = ahci_dma_add_status, .set_inactive = ahci_dma_set_inactive, + .async_cmd_done = ahci_async_cmd_done, .restart_cb = ahci_dma_restart_cb, .reset = ahci_dma_reset, }; diff --git a/hw/ide/core.c b/hw/ide/core.c index 03d1cfa7d2..a73af7252a 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -568,10 +568,18 @@ static void dma_buf_commit(IDEState *s) qemu_sglist_destroy(&s->sg); } +static void ide_async_cmd_done(IDEState *s) +{ + if (s->bus->dma->ops->async_cmd_done) { + s->bus->dma->ops->async_cmd_done(s->bus->dma); + } +} + void ide_set_inactive(IDEState *s) { s->bus->dma->aiocb = NULL; s->bus->dma->ops->set_inactive(s->bus->dma); + ide_async_cmd_done(s); } void ide_dma_error(IDEState *s) @@ -804,6 +812,7 @@ static void ide_flush_cb(void *opaque, int ret) bdrv_acct_done(s->bs, &s->acct); s->status = READY_STAT | SEEK_STAT; + ide_async_cmd_done(s); ide_set_irq(s->bus); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 03f14896d6..048a052143 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -433,6 +433,7 @@ struct IDEDMAOps { DMAIntFunc *set_unit; DMAIntFunc *add_status; DMAFunc *set_inactive; + DMAFunc *async_cmd_done; DMARestartFunc *restart_cb; DMAFunc *reset; }; diff --git a/include/block/block.h b/include/block/block.h index dd8eca1be1..b6b9014a9c 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -111,7 +111,8 @@ bool bdrv_io_limits_enabled(BlockDriverState *bs); void bdrv_init(void); void bdrv_init_with_whitelist(void); -BlockDriver *bdrv_find_protocol(const char *filename); +BlockDriver *bdrv_find_protocol(const char *filename, + bool allow_protocol_prefix); BlockDriver *bdrv_find_format(const char *format_name); BlockDriver *bdrv_find_whitelisted_format(const char *format_name, bool readonly); @@ -266,7 +267,7 @@ void bdrv_clear_incoming_migration_all(void); /* Ensure contents are flushed to disk. */ int bdrv_flush(BlockDriverState *bs); int coroutine_fn bdrv_co_flush(BlockDriverState *bs); -void bdrv_flush_all(void); +int bdrv_flush_all(void); void bdrv_close_all(void); void bdrv_drain_all(void); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index d85bdc0cac..3caeb66eb2 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -35,8 +35,8 @@ void vm_state_notify(int running, RunState state); #define VMRESET_REPORT true void vm_start(void); -void vm_stop(RunState state); -void vm_stop_force_state(RunState state); +int vm_stop(RunState state); +int vm_stop_force_state(RunState state); typedef enum WakeupReason { QEMU_WAKEUP_REASON_OTHER = 0, diff --git a/migration.c b/migration.c index 635a7e7a08..0681d8e5f1 100644 --- a/migration.c +++ b/migration.c @@ -527,15 +527,26 @@ static void *migration_thread(void *opaque) if (pending_size && pending_size >= max_size) { qemu_savevm_state_iterate(s->file); } else { + int ret; + DPRINTF("done iterating\n"); qemu_mutex_lock_iothread(); start_time = qemu_get_clock_ms(rt_clock); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); old_vm_running = runstate_is_running(); - vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); - qemu_file_set_rate_limit(s->file, INT_MAX); - qemu_savevm_state_complete(s->file); + + ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); + if (ret >= 0) { + qemu_file_set_rate_limit(s->file, INT_MAX); + qemu_savevm_state_complete(s->file); + } qemu_mutex_unlock_iothread(); + + if (ret < 0) { + migrate_finish_set_state(s, MIG_STATE_ERROR); + break; + } + if (!qemu_file_get_error(s->file)) { migrate_finish_set_state(s, MIG_STATE_COMPLETED); break; diff --git a/qapi-schema.json b/qapi-schema.json index b251d282cc..cf57783caf 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1634,6 +1634,10 @@ # @format: #optional the format of the new destination, default is to # probe if @mode is 'existing', else the format of the source # +# @sync: what parts of the disk image should be copied to the destination +# (all the disk, only the sectors allocated in the topmost image, or +# only new I/O). +# # @mode: #optional whether and how QEMU should create a new image, default is # 'absolute-paths'. # @@ -1655,7 +1659,8 @@ ## { 'type': 'DriveBackup', 'data': { 'device': 'str', 'target': 'str', '*format': 'str', - '*mode': 'NewImageMode', '*speed': 'int', + 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', + '*speed': 'int', '*on-source-error': 'BlockdevOnError', '*on-target-error': 'BlockdevOnError' } } diff --git a/qemu-img.c b/qemu-img.c index f8c97d34d1..c55ca5c557 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -240,7 +240,7 @@ static int print_block_option_help(const char *filename, const char *fmt) return 1; } - proto_drv = bdrv_find_protocol(filename); + proto_drv = bdrv_find_protocol(filename, true); if (!proto_drv) { error_report("Unknown protocol '%s'", filename); return 1; @@ -1261,7 +1261,7 @@ static int img_convert(int argc, char **argv) goto out; } - proto_drv = bdrv_find_protocol(out_filename); + proto_drv = bdrv_find_protocol(out_filename, true); if (!proto_drv) { error_report("Unknown protocol '%s'", out_filename); ret = -1; diff --git a/qmp-commands.hx b/qmp-commands.hx index 362f0e1ef8..e075df423a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -913,7 +913,7 @@ EQMP { .name = "drive-backup", - .args_type = "device:B,target:s,speed:i?,mode:s?,format:s?," + .args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?," "on-source-error:s?,on-target-error:s?", .mhandler.cmd_new = qmp_marshal_input_drive_backup, }, @@ -939,6 +939,10 @@ Arguments: - "format": the format of the new destination, default is to probe if 'mode' is 'existing', else the format of the source (json-string, optional) +- "sync": what parts of the disk image should be copied to the destination; + possibilities include "full" for all the disk, "top" for only the sectors + allocated in the topmost image, or "none" to only replicate new I/O + (MirrorSyncMode). - "mode": whether and how QEMU should create a new image (NewImageMode, optional, default 'absolute-paths') - "speed": the maximum speed, in bytes per second (json-int, optional) diff --git a/stubs/vm-stop.c b/stubs/vm-stop.c index 45689354f6..f82c897dfe 100644 --- a/stubs/vm-stop.c +++ b/stubs/vm-stop.c @@ -1,7 +1,7 @@ #include "qemu-common.h" #include "sysemu/sysemu.h" -void vm_stop(RunState state) +int vm_stop(RunState state) { abort(); } diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 8039e23ab3..1cf8bf79b6 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -149,6 +149,18 @@ echo run_qemu -drive file=$TEST_IMG,file.driver=file run_qemu -drive file=$TEST_IMG,file.driver=qcow2 +echo +echo === Parsing protocol from file name === +echo + +# Protocol strings are supposed to be parsed from traditional option strings, +# but not when using driver-specific options. We can distinguish them by the +# error message for non-existing files. + +run_qemu -hda foo:bar +run_qemu -drive file=foo:bar +run_qemu -drive file.filename=foo:bar + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 3d1ac7b7da..95ff245f40 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -23,10 +23,12 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not === Enable and disable lazy refcounting on the command line, plus some invalid values === Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
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' @@ -49,112 +51,152 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: Lazy ref QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
=== No medium === Testing: -drive if=floppy -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=ide,media=cdrom -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=scsi,media=cdrom -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=ide -QEMU_PROG: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: Device needs media, but drive is empty +QEMU_PROG: Device initialization failed. QEMU_PROG: Initialization of device ide-hd failed Testing: -drive if=virtio -QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty +QEMU_PROG: -drive if=virtio: Device initialization failed. +QEMU_PROG: -drive if=virtio: Device initialization failed. QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized Testing: -drive if=scsi -QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty +QEMU_PROG: -drive if=scsi: Device initialization failed. +QEMU_PROG: Device initialization failed. QEMU_PROG: Initialization of device lsi53c895a failed Testing: -drive if=none,id=disk -device ide-cd,drive=disk -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=none,id=disk -device ide-drive,drive=disk -QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized Testing: -drive if=none,id=disk -device ide-hd,drive=disk -QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk -QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed. QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk -QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed. QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized === Read-only === Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: readonly not supported by this bus type Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk -QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive +QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk -QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive +QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
=== Cache modes === Testing: -drive media=cdrom,cache=none -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=directsync -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=writeback -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=writethrough -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=unsafe -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=invalid_value QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option @@ -163,10 +205,25 @@ QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option === Specifying the protocol layer === Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file -q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
+QEMU 1.5.50 monitor - type 'help' for more information
+(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: Can't use 'qcow2' as a block driver for the protocol level QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Invalid argument + +=== Parsing protocol from file name === + +Testing: -hda foo:bar +QEMU_PROG: -hda foo:bar: Unknown protocol +QEMU_PROG: -hda foo:bar: could not open disk image foo:bar: No such file or directory + +Testing: -drive file=foo:bar +QEMU_PROG: -drive file=foo:bar: Unknown protocol +QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: No such file or directory + +Testing: -drive file.filename=foo:bar +QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: No such file or directory + *** done diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 index 887c959a3d..c66f8dbd7d 100755 --- a/tests/qemu-iotests/055 +++ b/tests/qemu-iotests/055 @@ -54,7 +54,7 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'return', {}) event = self.cancel_and_wait() @@ -64,7 +64,7 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'return', {}) result = self.vm.qmp('block-job-pause', device='drive0') @@ -89,17 +89,17 @@ class TestSingleDrive(iotests.QMPTestCase): def test_medium_not_found(self): result = self.vm.qmp('drive-backup', device='ide1-cd0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'error/class', 'GenericError') def test_image_not_found(self): result = self.vm.qmp('drive-backup', device='drive0', - mode='existing', target=target_img) + target=target_img, sync='full', mode='existing') self.assert_qmp(result, 'error/class', 'GenericError') def test_device_not_found(self): result = self.vm.qmp('drive-backup', device='nonexistent', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'error/class', 'DeviceNotFound') class TestSetSpeed(iotests.QMPTestCase): @@ -119,7 +119,7 @@ class TestSetSpeed(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'return', {}) # Default speed is 0 @@ -140,7 +140,7 @@ class TestSetSpeed(iotests.QMPTestCase): # Check setting speed in drive-backup works result = self.vm.qmp('drive-backup', device='drive0', - target=target_img, speed=4*1024*1024) + target=target_img, sync='full', speed=4*1024*1024) self.assert_qmp(result, 'return', {}) result = self.vm.qmp('query-block-jobs') @@ -154,13 +154,13 @@ class TestSetSpeed(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img, speed=-1) + target=target_img, sync='full', speed=-1) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'return', {}) result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) @@ -196,7 +196,8 @@ class TestSingleTransaction(iotests.QMPTestCase): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'drive0', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'return', {}) @@ -210,7 +211,8 @@ class TestSingleTransaction(iotests.QMPTestCase): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'drive0', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'return', {}) @@ -239,7 +241,8 @@ class TestSingleTransaction(iotests.QMPTestCase): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'ide1-cd0', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') @@ -249,7 +252,8 @@ class TestSingleTransaction(iotests.QMPTestCase): 'type': 'drive-backup', 'data': { 'device': 'drive0', 'mode': 'existing', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') @@ -259,7 +263,8 @@ class TestSingleTransaction(iotests.QMPTestCase): 'type': 'drive-backup', 'data': { 'device': 'nonexistent', 'mode': 'existing', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'DeviceNotFound') @@ -269,7 +274,8 @@ class TestSingleTransaction(iotests.QMPTestCase): 'type': 'drive-backup', 'data': { 'device': 'nonexistent', 'mode': 'existing', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, }, { 'type': 'Abort', 'data': {}, diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index dcf6391ea2..9dbcae8d8c 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -155,7 +155,7 @@ _filter_qemu_io() # replace occurrences of QEMU_PROG with "qemu" _filter_qemu() { - sed -e "s#^$(basename $QEMU_PROG):#QEMU_PROG:#" + sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" } # make sure this script returns success |