diff options
-rw-r--r-- | block/mirror.c | 4 | ||||
-rw-r--r-- | hw/core/qdev-properties-system.c | 11 | ||||
-rw-r--r-- | hw/i386/pc.c | 2 | ||||
-rw-r--r-- | hw/ide/ahci.c | 4 | ||||
-rw-r--r-- | hw/ide/core.c | 1 | ||||
-rw-r--r-- | hw/input/virtio-input.c | 11 | ||||
-rw-r--r-- | hw/mips/cps.c | 2 | ||||
-rw-r--r-- | hw/nvram/fw_cfg.c | 2 | ||||
-rw-r--r-- | hw/ppc/spapr_cpu_core.c | 2 | ||||
-rw-r--r-- | hw/s390x/s390-pci-bus.c | 2 | ||||
-rw-r--r-- | hw/sparc/leon3.c | 6 | ||||
-rw-r--r-- | hw/usb/bus.c | 7 | ||||
-rw-r--r-- | hw/usb/desc.c | 1 | ||||
-rw-r--r-- | hw/vfio/platform.c | 2 | ||||
-rw-r--r-- | kvm-all.c | 2 | ||||
-rw-r--r-- | migration/qjson.c | 1 | ||||
-rw-r--r-- | numa.c | 15 | ||||
-rw-r--r-- | qemu-char.c | 58 | ||||
-rw-r--r-- | qemu-img.c | 4 | ||||
-rwxr-xr-x | scripts/checkpatch.pl | 5 | ||||
-rw-r--r-- | scripts/coccinelle/err-bad-newline.cocci | 29 | ||||
-rw-r--r-- | slirp/slirp.c | 8 | ||||
-rw-r--r-- | target-i386/kvm.c | 2 | ||||
-rw-r--r-- | tests/Makefile.include | 2 | ||||
-rwxr-xr-x | tests/qemu-iotests/109 | 2 | ||||
-rw-r--r-- | tests/qemu-iotests/109.out | 8 | ||||
-rw-r--r-- | tests/qemu-iotests/common.filter | 6 | ||||
-rw-r--r-- | tests/test-blockjob.c | 147 | ||||
-rw-r--r-- | ui/vnc.c | 2 |
29 files changed, 297 insertions, 51 deletions
diff --git a/block/mirror.c b/block/mirror.c index d6034f5b70..e0b3f4180f 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -419,6 +419,10 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) mirror_wait_for_io(s); } + if (s->ret < 0) { + return 0; + } + mirror_clip_sectors(s, sector_num, &io_sectors); switch (mirror_method) { case MIRROR_METHOD_COPY: diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 2ba2504ea0..e55afe6bf2 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -126,7 +126,16 @@ static void release_drive(Object *obj, const char *name, void *opaque) static char *print_drive(void *ptr) { - return g_strdup(blk_name(ptr)); + const char *name; + + name = blk_name(ptr); + if (!*name) { + BlockDriverState *bs = blk_bs(ptr); + if (bs) { + name = bdrv_get_node_name(bs); + } + } + return g_strdup(name); } static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 47593b741a..022dd1b205 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -381,7 +381,7 @@ ISADevice *pc_find_fdc0(void) error_report("warning: multiple floppy disk controllers with " "iobase=0x3f0 have been found"); error_printf("the one being picked for CMOS setup might not reflect " - "your intent"); + "your intent\n"); } return state.floppy; diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index bcb9ff9e1b..f3438ad78a 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -919,6 +919,7 @@ static void ncq_err(NCQTransferState *ncq_tfs) ide_state->error = ABRT_ERR; ide_state->status = READY_STAT | ERR_STAT; ncq_tfs->drive->port_regs.scr_err |= (1 << ncq_tfs->tag); + qemu_sglist_destroy(&ncq_tfs->sglist); ncq_tfs->used = 0; } @@ -1025,7 +1026,6 @@ static void execute_ncq_command(NCQTransferState *ncq_tfs) default: DPRINTF(port, "error: unsupported NCQ command (0x%02x) received\n", ncq_tfs->cmd); - qemu_sglist_destroy(&ncq_tfs->sglist); ncq_err(ncq_tfs); } } @@ -1092,7 +1092,6 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, error_report("ahci: PRDT length for NCQ command (0x%zx) " "is smaller than the requested size (0x%zx)", ncq_tfs->sglist.size, size); - qemu_sglist_destroy(&ncq_tfs->sglist); ncq_err(ncq_tfs); ahci_trigger_irq(ad->hba, ad, PORT_IRQ_OVERFLOW); return; @@ -1478,6 +1477,7 @@ void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) ad->port.dma->ops = &ahci_dma_ops; ide_register_restart_cb(&ad->port); } + g_free(irqs); } void ahci_uninit(AHCIState *s) diff --git a/hw/ide/core.c b/hw/ide/core.c index d117b7c202..45b6df132c 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -824,6 +824,7 @@ static void ide_dma_cb(void *opaque, int ret) if (ret < 0) { if (ide_handle_rw_error(s, -ret, ide_dma_cmd_to_retry(s->dma_cmd))) { s->bus->dma->aiocb = NULL; + dma_buf_commit(s, 0); return; } } diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c index a87fd6862e..ccdf7308a5 100644 --- a/hw/input/virtio-input.c +++ b/hw/input/virtio-input.c @@ -270,6 +270,16 @@ static void virtio_input_device_realize(DeviceState *dev, Error **errp) vinput->sts = virtio_add_queue(vdev, 64, virtio_input_handle_sts); } +static void virtio_input_finalize(Object *obj) +{ + VirtIOInput *vinput = VIRTIO_INPUT(obj); + VirtIOInputConfig *cfg, *next; + + QTAILQ_FOREACH_SAFE(cfg, &vinput->cfg_list, node, next) { + QTAILQ_REMOVE(&vinput->cfg_list, cfg, node); + g_free(cfg); + } +} static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) { VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev); @@ -318,6 +328,7 @@ static const TypeInfo virtio_input_info = { .class_size = sizeof(VirtIOInputClass), .class_init = virtio_input_class_init, .abstract = true, + .instance_finalize = virtio_input_finalize, }; /* ----------------------------------------------------------------- */ diff --git a/hw/mips/cps.c b/hw/mips/cps.c index 77c621797a..4ef337d5c4 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -73,7 +73,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) for (i = 0; i < s->num_vp; i++) { cpu = cpu_mips_init(s->cpu_model); if (cpu == NULL) { - error_setg(errp, "%s: CPU initialization failed\n", __func__); + error_setg(errp, "%s: CPU initialization failed", __func__); return; } diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index f10d5ec9c8..6a68e594d5 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -744,7 +744,7 @@ static int get_fw_cfg_order(FWCfgState *s, const char *name) } /* Stick unknown stuff at the end. */ - error_report("warning: Unknown firmware file in legacy mode: %s\n", name); + error_report("warning: Unknown firmware file in legacy mode: %s", name); return FW_CFG_ORDER_OVERRIDE_LAST; } diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 704803ac23..716f7c44cd 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -231,7 +231,7 @@ void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, } if (cc->core_id % smp_threads) { - error_setg(&local_err, "invalid core id %d\n", cc->core_id); + error_setg(&local_err, "invalid core id %d", cc->core_id); goto out; } diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 47ca853bd2..9c1c04e590 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -712,7 +712,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, pci_dev = PCI_DEVICE(dev); for (i = 0 ; i < PCI_SLOT_MAX; i++) { - if (s->pbdev[i]->pdev == pci_dev) { + if (s->pbdev[i] && s->pbdev[i]->pdev == pci_dev) { pbdev = s->pbdev[i]; break; } diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index dbae41f3a4..6e16478413 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -171,7 +171,11 @@ static void leon3_generic_hw_init(MachineState *machine) } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - bios_size = get_image_size(filename); + if (filename) { + bios_size = get_image_size(filename); + } else { + bios_size = -1; + } if (bios_size > prom_size) { fprintf(stderr, "qemu: could not load prom '%s': file too big\n", diff --git a/hw/usb/bus.c b/hw/usb/bus.c index c28ccb8a96..25913ad488 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -279,6 +279,13 @@ static void usb_qdev_realize(DeviceState *qdev, Error **errp) static void usb_qdev_unrealize(DeviceState *qdev, Error **errp) { USBDevice *dev = USB_DEVICE(qdev); + USBDescString *s, *next; + + QLIST_FOREACH_SAFE(s, &dev->strings, next, next) { + QLIST_REMOVE(s, next); + g_free(s->str); + g_free(s); + } if (dev->attached) { usb_device_detach(dev); diff --git a/hw/usb/desc.c b/hw/usb/desc.c index adb026e43b..5e0e1d157e 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -574,6 +574,7 @@ void usb_desc_create_serial(USBDevice *dev) } dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path); usb_desc_set_string(dev, index, serial); + g_free(path); } const char *usb_desc_get_string(USBDevice *dev, uint8_t index) diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c index 1798a00a3f..a559e7b659 100644 --- a/hw/vfio/platform.c +++ b/hw/vfio/platform.c @@ -496,7 +496,7 @@ static int vfio_populate_device(VFIODevice *vbasedev) irq.index = i; ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq); if (ret) { - error_printf("vfio: error getting device %s irq info", + error_report("vfio: error getting device %s irq info", vbasedev->name); goto irq_err; } else { @@ -2143,7 +2143,7 @@ void kvm_device_access(int fd, int group, uint64_t attr, if (err < 0) { error_report("KVM_%s_DEVICE_ATTR failed: %s", write ? "SET" : "GET", strerror(-err)); - error_printf("Group %d attr 0x%016" PRIx64, group, attr); + error_printf("Group %d attr 0x%016" PRIx64 "\n", group, attr); abort(); } } diff --git a/migration/qjson.c b/migration/qjson.c index 5cae55af07..f345904919 100644 --- a/migration/qjson.c +++ b/migration/qjson.c @@ -109,5 +109,6 @@ void qjson_finish(QJSON *json) void qjson_destroy(QJSON *json) { + QDECREF(json->str); g_free(json); } @@ -223,14 +223,14 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) } if (err) { - goto error; + goto end; } switch (object->type) { case NUMA_OPTIONS_KIND_NODE: numa_node_parse(object->u.node.data, opts, &err); if (err) { - goto error; + goto end; } nb_numa_nodes++; break; @@ -238,13 +238,14 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp) abort(); } - return 0; - -error: - error_report_err(err); +end: qapi_free_NumaOptions(object); + if (err) { + error_report_err(err); + return -1; + } - return -1; + return 0; } static char *enumerate_cpus(unsigned long *cpus, int max_cpus) diff --git a/qemu-char.c b/qemu-char.c index 27f2dbbbb5..8a0ab05a7b 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -786,6 +786,13 @@ static GSource *mux_chr_add_watch(CharDriverState *s, GIOCondition cond) return d->drv->chr_add_watch(d->drv, cond); } +static void mux_chr_close(struct CharDriverState *chr) +{ + MuxDriver *d = chr->opaque; + + g_free(d); +} + static CharDriverState *qemu_chr_open_mux(const char *id, ChardevBackend *backend, ChardevReturn *ret, Error **errp) @@ -810,6 +817,7 @@ static CharDriverState *qemu_chr_open_mux(const char *id, chr->opaque = d; d->drv = drv; d->focus = -1; + chr->chr_close = mux_chr_close; chr->chr_write = mux_chr_write; chr->chr_update_read_handler = mux_chr_update_read_handler; chr->chr_accept_input = mux_chr_accept_input; @@ -2763,6 +2771,7 @@ static int tcp_set_msgfds(CharDriverState *chr, int *fds, int num) /* clear old pending fd array */ g_free(s->write_msgfds); s->write_msgfds = NULL; + s->write_msgfds_num = 0; if (!s->connected || !qio_channel_has_feature(s->ioc, @@ -2843,19 +2852,24 @@ static GSource *tcp_chr_add_watch(CharDriverState *chr, GIOCondition cond) return qio_channel_create_watch(s->ioc, cond); } -static void tcp_chr_disconnect(CharDriverState *chr) +static void tcp_chr_free_connection(CharDriverState *chr) { TCPCharDriver *s = chr->opaque; + int i; if (!s->connected) { return; } - s->connected = 0; - if (s->listen_ioc) { - s->listen_tag = qio_channel_add_watch( - QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL); + if (s->read_msgfds_num) { + for (i = 0; i < s->read_msgfds_num; i++) { + close(s->read_msgfds[i]); + } + g_free(s->read_msgfds); + s->read_msgfds = NULL; + s->read_msgfds_num = 0; } + tcp_set_msgfds(chr, NULL, 0); remove_fd_in_watch(chr); object_unref(OBJECT(s->sioc)); @@ -2863,6 +2877,24 @@ static void tcp_chr_disconnect(CharDriverState *chr) object_unref(OBJECT(s->ioc)); s->ioc = NULL; g_free(chr->filename); + chr->filename = NULL; + s->connected = 0; +} + +static void tcp_chr_disconnect(CharDriverState *chr) +{ + TCPCharDriver *s = chr->opaque; + + if (!s->connected) { + return; + } + + tcp_chr_free_connection(chr); + + if (s->listen_ioc) { + s->listen_tag = qio_channel_add_watch( + QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL); + } chr->filename = SocketAddress_to_str("disconnected:", s->addr, s->is_listen, s->is_telnet); qemu_chr_be_event(chr, CHR_EVENT_CLOSED); @@ -3177,17 +3209,14 @@ int qemu_chr_wait_connected(CharDriverState *chr, Error **errp) static void tcp_chr_close(CharDriverState *chr) { TCPCharDriver *s = chr->opaque; - int i; + + tcp_chr_free_connection(chr); if (s->reconnect_timer) { g_source_remove(s->reconnect_timer); s->reconnect_timer = 0; } qapi_free_SocketAddress(s->addr); - remove_fd_in_watch(chr); - if (s->ioc) { - object_unref(OBJECT(s->ioc)); - } if (s->listen_tag) { g_source_remove(s->listen_tag); s->listen_tag = 0; @@ -3195,18 +3224,9 @@ static void tcp_chr_close(CharDriverState *chr) if (s->listen_ioc) { object_unref(OBJECT(s->listen_ioc)); } - if (s->read_msgfds_num) { - for (i = 0; i < s->read_msgfds_num; i++) { - close(s->read_msgfds[i]); - } - g_free(s->read_msgfds); - } if (s->tls_creds) { object_unref(OBJECT(s->tls_creds)); } - if (s->write_msgfds_num) { - g_free(s->write_msgfds); - } g_free(s); qemu_chr_be_event(chr, CHR_EVENT_CLOSED); } diff --git a/qemu-img.c b/qemu-img.c index 2e40e1fc84..d2865a589e 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -3490,7 +3490,7 @@ typedef struct BenchData { static void bench_undrained_flush_cb(void *opaque, int ret) { if (ret < 0) { - error_report("Failed flush request: %s\n", strerror(-ret)); + error_report("Failed flush request: %s", strerror(-ret)); exit(EXIT_FAILURE); } } @@ -3501,7 +3501,7 @@ static void bench_cb(void *opaque, int ret) BlockAIOCB *acb; if (ret < 0) { - error_report("Failed request: %s\n", strerror(-ret)); + error_report("Failed request: %s", strerror(-ret)); exit(EXIT_FAILURE); } diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index b7cb4ab478..9297087212 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2514,11 +2514,14 @@ sub process { my $qemu_error_funcs = qr{error_setg| error_setg_errno| error_setg_win32| + error_setg_file_open| error_set| + error_prepend| + error_reportf_err| error_vreport| error_report}x; - if ($rawline =~ /\b(?:$qemu_error_funcs)\s*\(\s*\".*\\n/) { + if ($rawline =~ /\b(?:$qemu_error_funcs)\s*\(.*\".*\\n/) { WARN("Error messages should not contain newlines\n" . $herecurr); } diff --git a/scripts/coccinelle/err-bad-newline.cocci b/scripts/coccinelle/err-bad-newline.cocci new file mode 100644 index 0000000000..1316cc86a6 --- /dev/null +++ b/scripts/coccinelle/err-bad-newline.cocci @@ -0,0 +1,29 @@ +// Error messages should not contain newlines. This script finds +// messages that do. Fixing them is manual. +@r@ +expression errp, eno, cls, fmt; +position p; +@@ +( +error_report(fmt, ...)@p +| +error_setg(errp, fmt, ...)@p +| +error_setg_errno(errp, eno, fmt, ...)@p +| +error_setg_win32(errp, eno, cls, fmt, ...)@p +| +error_prepend(errp, fmt, ...)@p +| +error_setg_file_open(errp, eno, cls, fmt, ...)@p +| +error_reportf_err(errp, fmt, ...)@p +| +error_set(errp, cls, fmt, ...)@p +) +@script:python@ +fmt << r.fmt; +p << r.p; +@@ +if "\\n" in str(fmt): + print "%s:%s:%s:%s" % (p[0].file, p[0].line, p[0].column, fmt) diff --git a/slirp/slirp.c b/slirp/slirp.c index 7eb183d0e9..47a1652952 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -1197,8 +1197,8 @@ static void slirp_socket_save(QEMUFile *f, struct socket *so) qemu_put_be16(f, so->so_fport); break; default: - error_report( - "so_ffamily unknown, unable to save so_faddr and so_fport\n"); + error_report("so_ffamily unknown, unable to save so_faddr and" + " so_fport"); } qemu_put_be16(f, so->so_lfamily); switch (so->so_lfamily) { @@ -1207,8 +1207,8 @@ static void slirp_socket_save(QEMUFile *f, struct socket *so) qemu_put_be16(f, so->so_lport); break; default: - error_report( - "so_ffamily unknown, unable to save so_laddr and so_lport\n"); + error_report("so_ffamily unknown, unable to save so_laddr and" + " so_lport"); } qemu_put_byte(f, so->so_iptos); qemu_put_byte(f, so->so_emu); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 9697e16fdd..0b2016a77a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -3250,7 +3250,7 @@ int kvm_arch_irqchip_create(MachineState *ms, KVMState *s) if (machine_kernel_irqchip_split(ms)) { ret = kvm_vm_enable_cap(s, KVM_CAP_SPLIT_IRQCHIP, 0, 24); if (ret) { - error_report("Could not enable split irqchip mode: %s\n", + error_report("Could not enable split irqchip mode: %s", strerror(-ret)); exit(1); } else { diff --git a/tests/Makefile.include b/tests/Makefile.include index ebecfa445c..14be4915b9 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -52,6 +52,7 @@ gcov-files-test-thread-pool-y = thread-pool.c gcov-files-test-hbitmap-y = util/hbitmap.c check-unit-y += tests/test-hbitmap$(EXESUF) gcov-files-test-hbitmap-y = blockjob.c +check-unit-y += tests/test-blockjob$(EXESUF) check-unit-y += tests/test-blockjob-txn$(EXESUF) check-unit-y += tests/test-x86-cpuid$(EXESUF) # all code tested by test-x86-cpuid is inside topology.h @@ -449,6 +450,7 @@ tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y) tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y) tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o $(test-util-obj-y) tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y) +tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y) tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y) tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y) tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109 index adf98892f0..280ed27aa9 100755 --- a/tests/qemu-iotests/109 +++ b/tests/qemu-iotests/109 @@ -100,7 +100,7 @@ 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" + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" | _filter_block_job_offset $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" diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out index 7c797ed31c..e5d70d75f1 100644 --- a/tests/qemu-iotests/109.out +++ b/tests/qemu-iotests/109.out @@ -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": 2560, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "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": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "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": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "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": 2048, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "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) diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 7853dbbfdc..3ab6e4d764 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -77,6 +77,12 @@ _filter_qmp() -e ' QMP_VERSION' } +# replace block job offset +_filter_block_job_offset() +{ + sed -e 's/, "offset": [0-9]\+,/, "offset": OFFSET,/' +} + # replace driver-specific options in the "Formatting..." line _filter_img_create() { diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c new file mode 100644 index 0000000000..5b0e934a0c --- /dev/null +++ b/tests/test-blockjob.c @@ -0,0 +1,147 @@ +/* + * Blockjob tests + * + * Copyright Igalia, S.L. 2016 + * + * Authors: + * Alberto Garcia <berto@igalia.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/main-loop.h" +#include "block/blockjob.h" +#include "sysemu/block-backend.h" + +static const BlockJobDriver test_block_job_driver = { + .instance_size = sizeof(BlockJob), +}; + +static void block_job_cb(void *opaque, int ret) +{ +} + +static BlockJob *do_test_id(BlockBackend *blk, const char *id, + bool should_succeed) +{ + BlockJob *job; + Error *errp = NULL; + + job = block_job_create(id, &test_block_job_driver, blk_bs(blk), 0, + block_job_cb, NULL, &errp); + if (should_succeed) { + g_assert_null(errp); + g_assert_nonnull(job); + if (id) { + g_assert_cmpstr(job->id, ==, id); + } else { + g_assert_cmpstr(job->id, ==, blk_name(blk)); + } + } else { + g_assert_nonnull(errp); + g_assert_null(job); + error_free(errp); + } + + return job; +} + +/* This creates a BlockBackend (optionally with a name) with a + * BlockDriverState inserted. */ +static BlockBackend *create_blk(const char *name) +{ + BlockBackend *blk = blk_new(); + BlockDriverState *bs = bdrv_new(); + + blk_insert_bs(blk, bs); + bdrv_unref(bs); + + if (name) { + Error *errp = NULL; + monitor_add_blk(blk, name, &errp); + g_assert_null(errp); + } + + return blk; +} + +/* This destroys the backend */ +static void destroy_blk(BlockBackend *blk) +{ + if (blk_name(blk)[0] != '\0') { + monitor_remove_blk(blk); + } + + blk_remove_bs(blk); + blk_unref(blk); +} + +static void test_job_ids(void) +{ + BlockBackend *blk[3]; + BlockJob *job[3]; + + blk[0] = create_blk(NULL); + blk[1] = create_blk("drive1"); + blk[2] = create_blk("drive2"); + + /* No job ID provided and the block backend has no name */ + job[0] = do_test_id(blk[0], NULL, false); + + /* These are all invalid job IDs */ + job[0] = do_test_id(blk[0], "0id", false); + job[0] = do_test_id(blk[0], "", false); + job[0] = do_test_id(blk[0], " ", false); + job[0] = do_test_id(blk[0], "123", false); + job[0] = do_test_id(blk[0], "_id", false); + job[0] = do_test_id(blk[0], "-id", false); + job[0] = do_test_id(blk[0], ".id", false); + job[0] = do_test_id(blk[0], "#id", false); + + /* This one is valid */ + job[0] = do_test_id(blk[0], "id0", true); + + /* We cannot have two jobs in the same BDS */ + do_test_id(blk[0], "id1", false); + + /* Duplicate job IDs are not allowed */ + job[1] = do_test_id(blk[1], "id0", false); + + /* But once job[0] finishes we can reuse its ID */ + block_job_unref(job[0]); + job[1] = do_test_id(blk[1], "id0", true); + + /* No job ID specified, defaults to the backend name ('drive1') */ + block_job_unref(job[1]); + job[1] = do_test_id(blk[1], NULL, true); + + /* Duplicate job ID */ + job[2] = do_test_id(blk[2], "drive1", false); + + /* The ID of job[2] would default to 'drive2' but it is already in use */ + job[0] = do_test_id(blk[0], "drive2", true); + job[2] = do_test_id(blk[2], NULL, false); + + /* This one is valid */ + job[2] = do_test_id(blk[2], "id_2", true); + + block_job_unref(job[0]); + block_job_unref(job[1]); + block_job_unref(job[2]); + + destroy_blk(blk[0]); + destroy_blk(blk[1]); + destroy_blk(blk[2]); +} + +int main(int argc, char **argv) +{ + qemu_init_main_loop(&error_abort); + + g_test_init(&argc, &argv, NULL); + g_test_add_func("/blockjob/ids", test_job_ids); + return g_test_run(); +} @@ -3201,7 +3201,7 @@ int vnc_display_password(const char *id, const char *password) } if (vs->auth == VNC_AUTH_NONE) { error_printf_unless_qmp("If you want use passwords please enable " - "password auth using '-vnc ${dpy},password'."); + "password auth using '-vnc ${dpy},password'.\n"); return -EINVAL; } |