diff options
66 files changed, 884 insertions, 583 deletions
diff --git a/.travis.yml b/.travis.yml index 376b7d6dfa..638fba4799 100644 --- a/.travis.yml +++ b/.travis.yml @@ -247,7 +247,7 @@ matrix: - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default" language: python python: - - "3.4" + - "3.5" - env: diff --git a/MAINTAINERS b/MAINTAINERS index 387879aebc..8571327881 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1872,12 +1872,12 @@ M: John Snow <jsnow@redhat.com> R: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> L: qemu-block@nongnu.org S: Supported -F: util/hbitmap.c -F: block/dirty-bitmap.c F: include/qemu/hbitmap.h F: include/block/dirty-bitmap.h -F: qcow2-bitmap.c +F: block/dirty-bitmap.c +F: block/qcow2-bitmap.c F: migration/block-dirty-bitmap.c +F: util/hbitmap.c F: tests/test-hbitmap.c F: docs/interop/bitmaps.rst T: git https://github.com/jnsnow/qemu.git bitmaps diff --git a/block.c b/block.c index 473eb6eeaa..1b6f7c86e8 100644 --- a/block.c +++ b/block.c @@ -5335,10 +5335,6 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, return; } - if (!(bs->open_flags & BDRV_O_INACTIVE)) { - return; - } - QLIST_FOREACH(child, &bs->children, next) { bdrv_co_invalidate_cache(child->bs, &local_err); if (local_err) { @@ -5360,34 +5356,36 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, * just keep the extended permissions for the next time that an activation * of the image is tried. */ - bs->open_flags &= ~BDRV_O_INACTIVE; - bdrv_get_cumulative_perm(bs, &perm, &shared_perm); - ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, &local_err); - if (ret < 0) { - bs->open_flags |= BDRV_O_INACTIVE; - error_propagate(errp, local_err); - return; - } - bdrv_set_perm(bs, perm, shared_perm); - - if (bs->drv->bdrv_co_invalidate_cache) { - bs->drv->bdrv_co_invalidate_cache(bs, &local_err); - if (local_err) { + if (bs->open_flags & BDRV_O_INACTIVE) { + bs->open_flags &= ~BDRV_O_INACTIVE; + bdrv_get_cumulative_perm(bs, &perm, &shared_perm); + ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, &local_err); + if (ret < 0) { bs->open_flags |= BDRV_O_INACTIVE; error_propagate(errp, local_err); return; } - } + bdrv_set_perm(bs, perm, shared_perm); - FOR_EACH_DIRTY_BITMAP(bs, bm) { - bdrv_dirty_bitmap_skip_store(bm, false); - } + if (bs->drv->bdrv_co_invalidate_cache) { + bs->drv->bdrv_co_invalidate_cache(bs, &local_err); + if (local_err) { + bs->open_flags |= BDRV_O_INACTIVE; + error_propagate(errp, local_err); + return; + } + } - ret = refresh_total_sectors(bs, bs->total_sectors); - if (ret < 0) { - bs->open_flags |= BDRV_O_INACTIVE; - error_setg_errno(errp, -ret, "Could not refresh total sector count"); - return; + FOR_EACH_DIRTY_BITMAP(bs, bm) { + bdrv_dirty_bitmap_skip_store(bm, false); + } + + ret = refresh_total_sectors(bs, bs->total_sectors); + if (ret < 0) { + bs->open_flags |= BDRV_O_INACTIVE; + error_setg_errno(errp, -ret, "Could not refresh total sector count"); + return; + } } QLIST_FOREACH(parent, &bs->parents, next_parent) { @@ -5751,12 +5749,11 @@ void bdrv_img_create(const char *filename, const char *fmt, return; } + /* Create parameter list */ create_opts = qemu_opts_append(create_opts, drv->create_opts); create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); - /* Create parameter list with default values */ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size, &error_abort); /* Parse -o options */ if (options) { @@ -5766,6 +5763,13 @@ void bdrv_img_create(const char *filename, const char *fmt, } } + if (!qemu_opt_get(opts, BLOCK_OPT_SIZE)) { + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size, &error_abort); + } else if (img_size != UINT64_C(-1)) { + error_setg(errp, "The image size must be specified only once"); + goto out; + } + if (base_filename) { qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename, &local_err); if (local_err) { diff --git a/block/qcow2.c b/block/qcow2.c index 7c18721741..7fbaac8457 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -367,7 +367,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, return -EINVAL; } - if (bitmaps_ext.bitmap_directory_offset & (s->cluster_size - 1)) { + if (offset_into_cluster(s, bitmaps_ext.bitmap_directory_offset)) { error_setg(errp, "bitmaps_ext: " "invalid bitmap directory offset"); return -EINVAL; @@ -1705,14 +1705,14 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, if (!(bdrv_get_flags(bs) & BDRV_O_INACTIVE)) { /* It's case 1, 2 or 3.2. Or 3.1 which is BUG in management layer. */ bool header_updated = qcow2_load_dirty_bitmaps(bs, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } update_header = update_header && !header_updated; } - if (local_err != NULL) { - error_propagate(errp, local_err); - ret = -EINVAL; - goto fail; - } if (update_header) { ret = qcow2_update_header(bs); @@ -1722,7 +1722,8 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, } } - bs->supported_zero_flags = header.version >= 3 ? BDRV_REQ_MAY_UNMAP : 0; + bs->supported_zero_flags = header.version >= 3 ? + BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0; /* Repair image if dirty */ if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only && @@ -1958,9 +1959,8 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, { BDRVQcow2State *s = bs->opaque; uint64_t cluster_offset; - int index_in_cluster, ret; unsigned int bytes; - int status = 0; + int ret, status = 0; qemu_co_mutex_lock(&s->lock); @@ -1981,8 +1981,7 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, if ((ret == QCOW2_CLUSTER_NORMAL || ret == QCOW2_CLUSTER_ZERO_ALLOC) && !s->crypto) { - index_in_cluster = offset & (s->cluster_size - 1); - *map = cluster_offset | index_in_cluster; + *map = cluster_offset | offset_into_cluster(s, offset); *file = s->data_file->bs; status |= BDRV_BLOCK_OFFSET_VALID; } diff --git a/blockjob.c b/blockjob.c index c6e20e2fcd..5d63b1e89d 100644 --- a/blockjob.c +++ b/blockjob.c @@ -261,7 +261,8 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) return; } if (speed < 0) { - error_setg(errp, QERR_INVALID_PARAMETER, "speed"); + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "speed", + "a non-negative value"); return; } diff --git a/configure b/configure index 940bf9e87a..747d3b4120 100755 --- a/configure +++ b/configure @@ -903,9 +903,9 @@ fi : ${install=${INSTALL-install}} # We prefer python 3.x. A bare 'python' is traditionally # python 2.x, but some distros have it as python 3.x, so -# we check that before python2 +# we check that too python= -for binary in "${PYTHON-python3}" python python2 +for binary in "${PYTHON-python3}" python do if has "$binary" then @@ -1842,8 +1842,8 @@ fi # Note that if the Python conditional here evaluates True we will exit # with status 1 which is a shell 'false' value. -if ! $python -c 'import sys; sys.exit(sys.version_info < (2,7))'; then - error_exit "Cannot use '$python', Python 2 >= 2.7 or Python 3 is required." \ +if ! $python -c 'import sys; sys.exit(sys.version_info < (3,5))'; then + error_exit "Cannot use '$python', Python >= 3.5 is required." \ "Use --python=/path/to/python to specify a supported Python." fi @@ -6594,15 +6594,6 @@ if test "$supported_os" = "no"; then echo "us upstream at qemu-devel@nongnu.org." fi -# Note that if the Python conditional here evaluates True we will exit -# with status 1 which is a shell 'false' value. -if ! $python -c 'import sys; sys.exit(sys.version_info < (3,0))'; then - echo - echo "warning: Python 2 support is deprecated" >&2 - echo "warning: Python 3 will be required for building future versions of QEMU" >&2 - python2="y" -fi - config_host_mak="config-host.mak" echo "# Automatically generated by configure - do not modify" >config-all-disas.mak @@ -7447,7 +7438,6 @@ echo "INSTALL_DATA=$install -c -m 0644" >> $config_host_mak echo "INSTALL_PROG=$install -c -m 0755" >> $config_host_mak echo "INSTALL_LIB=$install -c -m 0644" >> $config_host_mak echo "PYTHON=$python" >> $config_host_mak -echo "PYTHON2=$python2" >> $config_host_mak echo "CC=$cc" >> $config_host_mak if $iasl -h > /dev/null 2>&1; then echo "IASL=$iasl" >> $config_host_mak diff --git a/contrib/vhost-user-gpu/50-qemu-gpu.json.in b/contrib/vhost-user-gpu/50-qemu-gpu.json.in index 658b545864..f5edd097f8 100644 --- a/contrib/vhost-user-gpu/50-qemu-gpu.json.in +++ b/contrib/vhost-user-gpu/50-qemu-gpu.json.in @@ -1,5 +1,5 @@ { "description": "QEMU vhost-user-gpu", "type": "gpu", - "binary": "@libexecdir@/vhost-user-gpu", + "binary": "@libexecdir@/vhost-user-gpu" } diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst index 1b367e22e1..9b537a75e6 100644 --- a/docs/arm-cpu-features.rst +++ b/docs/arm-cpu-features.rst @@ -41,9 +41,9 @@ CPU type is possible with the `query-cpu-model-expansion` QMP command. Below are some examples where `scripts/qmp/qmp-shell` (see the top comment block in the script for usage) is used to issue the QMP commands. -(1) Determine which CPU features are available for the `max` CPU type - (Note, we started QEMU with qemu-system-aarch64, so `max` is - implementing the ARMv8-A reference manual in this case):: +1. Determine which CPU features are available for the `max` CPU type + (Note, we started QEMU with qemu-system-aarch64, so `max` is + implementing the ARMv8-A reference manual in this case):: (QEMU) query-cpu-model-expansion type=full model={"name":"max"} { "return": { diff --git a/docs/virtio-net-failover.rst b/docs/virtio-net-failover.rst index 22f64c7bc8..6002dc5d96 100644 --- a/docs/virtio-net-failover.rst +++ b/docs/virtio-net-failover.rst @@ -1,6 +1,6 @@ -======================== +====================================== QEMU virtio-net standby (net_failover) -======================== +====================================== This document explains the setup and usage of virtio-net standby feature which is used to create a net_failover pair of devices. diff --git a/docs/virtio-pmem.rst b/docs/virtio-pmem.rst index e77881b26f..4bf5d00443 100644 --- a/docs/virtio-pmem.rst +++ b/docs/virtio-pmem.rst @@ -27,17 +27,18 @@ virtio pmem usage ----------------- A virtio pmem device backed by a memory-backend-file can be created on - the QEMU command line as in the following example: + the QEMU command line as in the following example:: - -object memory-backend-file,id=mem1,share,mem-path=./virtio_pmem.img,size=4G - -device virtio-pmem-pci,memdev=mem1,id=nv1 + -object memory-backend-file,id=mem1,share,mem-path=./virtio_pmem.img,size=4G + -device virtio-pmem-pci,memdev=mem1,id=nv1 - where: - - "object memory-backend-file,id=mem1,share,mem-path=<image>, size=<image size>" - creates a backend file with the specified size. + where: - - "device virtio-pmem-pci,id=nvdimm1,memdev=mem1" creates a virtio pmem - pci device whose storage is provided by above memory backend device. + - "object memory-backend-file,id=mem1,share,mem-path=<image>, size=<image size>" + creates a backend file with the specified size. + + - "device virtio-pmem-pci,id=nvdimm1,memdev=mem1" creates a virtio pmem + pci device whose storage is provided by above memory backend device. Multiple virtio pmem devices can be created if multiple pairs of "-object" and "-device" are provided. @@ -50,7 +51,7 @@ memory backing has to be added via 'object_add'; afterwards, the virtio pmem device can be added via 'device_add'. For example, the following commands add another 4GB virtio pmem device to -the guest: +the guest:: (qemu) object_add memory-backend-file,id=mem2,share=on,mem-path=virtio_pmem2.img,size=4G (qemu) device_add virtio-pmem-pci,id=virtio_pmem2,memdev=mem2 diff --git a/hmp-commands.hx b/hmp-commands.hx index cfcc044ce4..dc23185de4 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1875,9 +1875,11 @@ ETEXI { .name = "qemu-io", - .args_type = "device:B,command:s", - .params = "[device] \"[command]\"", - .help = "run a qemu-io command on a block device", + .args_type = "qdev:-d,device:B,command:s", + .params = "[-d] [device] \"[command]\"", + .help = "run a qemu-io command on a block device\n\t\t\t" + "-d: [device] is a device ID rather than a " + "drive ID or node name", .cmd = hmp_qemu_io, }, diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index be88005dab..89e4b00950 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -250,6 +250,9 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(&s->cpu[i]), aspeed_calc_affinity(i), "mp-affinity", &error_abort); + object_property_set_int(OBJECT(&s->cpu[i]), 1125000000, "cntfrq", + &error_abort); + /* * TODO: the secondary CPUs are started and a boot helper * is needed when using -kernel diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 5853bdee5c..9b5bcb5634 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -789,7 +789,6 @@ static void sbsa_ref_class_init(ObjectClass *oc, void *data) mc->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids; mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props; mc->get_default_cpu_node_id = sbsa_ref_get_default_cpu_node_id; - mc->numa_mem_supported = true; } static const TypeInfo sbsa_ref_info = { diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index d190181ef1..4112394129 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -99,7 +99,7 @@ REG32(GERROR_IRQ_CFG2, 0x74) #define A_STRTAB_BASE 0x80 /* 64b */ -#define SMMU_BASE_ADDR_MASK 0xffffffffffe0 +#define SMMU_BASE_ADDR_MASK 0xfffffffffffc0 REG32(STRTAB_BASE_CFG, 0x88) FIELD(STRTAB_BASE_CFG, FMT, 16, 2) @@ -461,8 +461,8 @@ typedef struct SMMUEventInfo { } while (0) #define EVT_SET_ADDR2(x, addr) \ do { \ - (x)->word[7] = deposit32((x)->word[7], 3, 29, addr >> 16); \ - (x)->word[7] = deposit32((x)->word[7], 0, 16, addr & 0xffff);\ + (x)->word[7] = (uint32_t)(addr >> 32); \ + (x)->word[6] = (uint32_t)(addr & 0xffffffff); \ } while (0) void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event); diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index e2fbb8357e..8b5f157dc7 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -172,7 +172,7 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info) case SMMU_EVT_F_STE_FETCH: EVT_SET_SSID(&evt, info->u.f_ste_fetch.ssid); EVT_SET_SSV(&evt, info->u.f_ste_fetch.ssv); - EVT_SET_ADDR(&evt, info->u.f_ste_fetch.addr); + EVT_SET_ADDR2(&evt, info->u.f_ste_fetch.addr); break; case SMMU_EVT_C_BAD_STE: EVT_SET_SSID(&evt, info->u.c_bad_ste.ssid); @@ -376,21 +376,32 @@ bad_ste: static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) { - dma_addr_t addr; + dma_addr_t addr, strtab_base; + uint32_t log2size; + int strtab_size_shift; int ret; trace_smmuv3_find_ste(sid, s->features, s->sid_split); - /* Check SID range */ - if (sid > (1 << SMMU_IDR1_SIDSIZE)) { + log2size = FIELD_EX32(s->strtab_base_cfg, STRTAB_BASE_CFG, LOG2SIZE); + /* + * Check SID range against both guest-configured and implementation limits + */ + if (sid >= (1 << MIN(log2size, SMMU_IDR1_SIDSIZE))) { event->type = SMMU_EVT_C_BAD_STREAMID; return -EINVAL; } if (s->features & SMMU_FEATURE_2LVL_STE) { int l1_ste_offset, l2_ste_offset, max_l2_ste, span; - dma_addr_t strtab_base, l1ptr, l2ptr; + dma_addr_t l1ptr, l2ptr; STEDesc l1std; - strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK; + /* + * Align strtab base address to table size. For this purpose, assume it + * is not bounded by SMMU_IDR1_SIDSIZE. + */ + strtab_size_shift = MAX(5, (int)log2size - s->sid_split - 1 + 3); + strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK & + ~MAKE_64BIT_MASK(0, strtab_size_shift); l1_ste_offset = sid >> s->sid_split; l2_ste_offset = sid & ((1 << s->sid_split) - 1); l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std)); @@ -429,7 +440,10 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, } addr = l2ptr + l2_ste_offset * sizeof(*ste); } else { - addr = s->strtab_base + sid * sizeof(*ste); + strtab_size_shift = log2size + 5; + strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK & + ~MAKE_64BIT_MASK(0, strtab_size_shift); + addr = strtab_base + sid * sizeof(*ste); } if (smmu_get_ste(s, addr, ste, event)) { diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 119906a5fe..1b52e8159c 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -67,7 +67,7 @@ static void notify_guest_bh(void *opaque) memset(s->batch_notify_vqs, 0, sizeof(bitmap)); for (j = 0; j < nvqs; j += BITS_PER_LONG) { - unsigned long bits = bitmap[j]; + unsigned long bits = bitmap[j / BITS_PER_LONG]; while (bits != 0) { unsigned i = j + ctzl(bits); diff --git a/hw/core/machine.c b/hw/core/machine.c index 56137e9bf0..73bf1f8572 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -843,7 +843,7 @@ static void machine_initfn(Object *obj) NULL); } - if (mc->numa_mem_supported) { + if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) { ms->numa_state = g_new0(NumaState, 1); } @@ -966,7 +966,7 @@ void machine_run_board_init(MachineState *machine) { MachineClass *machine_class = MACHINE_GET_CLASS(machine); - if (machine_class->numa_mem_supported) { + if (machine->numa_state) { numa_complete_configuration(machine); if (machine->numa_state->num_nodes) { machine_numa_finish_cpu_init(machine); diff --git a/hw/core/numa.c b/hw/core/numa.c index e3332a984f..19f082de12 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -83,10 +83,6 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, return; } - if (!mc->cpu_index_to_instance_props || !mc->get_default_cpu_node_id) { - error_setg(errp, "NUMA is not supported by this machine-type"); - return; - } for (cpus = node->cpus; cpus; cpus = cpus->next) { CpuInstanceProperties props; if (cpus->value >= max_cpus) { @@ -178,9 +174,8 @@ void parse_numa_distance(MachineState *ms, NumaDistOptions *dist, Error **errp) void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) { Error *err = NULL; - MachineClass *mc = MACHINE_GET_CLASS(ms); - if (!mc->numa_mem_supported) { + if (!ms->numa_state) { error_setg(errp, "NUMA is not supported by this machine-type"); goto end; } diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c index dc1bd1641d..215db9a231 100644 --- a/hw/display/bochs-display.c +++ b/hw/display/bochs-display.c @@ -252,6 +252,8 @@ static void bochs_display_update(void *opaque) dpy_gfx_update(s->con, 0, ys, mode.width, y - ys); } + + g_free(snap); } } diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index c5dea307b6..d0e0af893a 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -2467,23 +2467,31 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict) { BlockBackend *blk; BlockBackend *local_blk = NULL; + bool qdev = qdict_get_try_bool(qdict, "qdev", false); const char* device = qdict_get_str(qdict, "device"); const char* command = qdict_get_str(qdict, "command"); Error *err = NULL; int ret; - blk = blk_by_name(device); - if (!blk) { - BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); - if (bs) { - blk = local_blk = blk_new(bdrv_get_aio_context(bs), - 0, BLK_PERM_ALL); - ret = blk_insert_bs(blk, bs, &err); - if (ret < 0) { + if (qdev) { + blk = blk_by_qdev_id(device, &err); + if (!blk) { + goto fail; + } + } else { + blk = blk_by_name(device); + if (!blk) { + BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); + if (bs) { + blk = local_blk = blk_new(bdrv_get_aio_context(bs), + 0, BLK_PERM_ALL); + ret = blk_insert_bs(blk, bs, &err); + if (ret < 0) { + goto fail; + } + } else { goto fail; } - } else { - goto fail; } } diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin index 40e7e67a9b..4af7f7d5a9 100644 --- a/pc-bios/bios-256k.bin +++ b/pc-bios/bios-256k.bin Binary files differdiff --git a/pc-bios/bios.bin b/pc-bios/bios.bin index 97b1e239aa..67874c31b8 100644 --- a/pc-bios/bios.bin +++ b/pc-bios/bios.bin Binary files differdiff --git a/pc-bios/vgabios-ati.bin b/pc-bios/vgabios-ati.bin index b5314fb66c..6202cf73e2 100644 --- a/pc-bios/vgabios-ati.bin +++ b/pc-bios/vgabios-ati.bin Binary files differdiff --git a/pc-bios/vgabios-bochs-display.bin b/pc-bios/vgabios-bochs-display.bin index 5033cc8433..b675f86bc6 100644 --- a/pc-bios/vgabios-bochs-display.bin +++ b/pc-bios/vgabios-bochs-display.bin Binary files differdiff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin index 4a3643903f..63fde14fea 100644 --- a/pc-bios/vgabios-cirrus.bin +++ b/pc-bios/vgabios-cirrus.bin Binary files differdiff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin index f6811bcc8b..80168826e2 100644 --- a/pc-bios/vgabios-qxl.bin +++ b/pc-bios/vgabios-qxl.bin Binary files differdiff --git a/pc-bios/vgabios-ramfb.bin b/pc-bios/vgabios-ramfb.bin index 79986b26cf..1dc413dcd2 100644 --- a/pc-bios/vgabios-ramfb.bin +++ b/pc-bios/vgabios-ramfb.bin Binary files differdiff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin index d709ec60a0..f92b9a664d 100644 --- a/pc-bios/vgabios-stdvga.bin +++ b/pc-bios/vgabios-stdvga.bin Binary files differdiff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin index b99faf4ccc..b0d2f70670 100644 --- a/pc-bios/vgabios-virtio.bin +++ b/pc-bios/vgabios-virtio.bin Binary files differdiff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin index 8c92ab76f7..1c2776e8cf 100644 --- a/pc-bios/vgabios-vmware.bin +++ b/pc-bios/vgabios-vmware.bin Binary files differdiff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin index aeae0364ad..c5aad8f3a9 100644 --- a/pc-bios/vgabios.bin +++ b/pc-bios/vgabios.bin Binary files differdiff --git a/qapi/block-core.json b/qapi/block-core.json index 0cf68fea14..fcb52ec24f 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2963,9 +2963,13 @@ # # Driver specific block device options for the NVMe backend. # -# @device: controller address of the NVMe device. +# @device: PCI controller address of the NVMe device in +# format hhhh:bb:ss.f (host:bus:slot.function) # @namespace: namespace number of the device, starting from 1. # +# Note that the PCI @device must have been unbound from any host +# kernel driver before instructing QEMU to add the blockdev. +# # Since: 2.12 ## { 'struct': 'BlockdevOptionsNVMe', diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi index 97ba3cb88c..0968d37c74 100644 --- a/qemu-deprecated.texi +++ b/qemu-deprecated.texi @@ -284,6 +284,17 @@ spec you can use the ``-cpu rv64gcsu,priv_spec=v1.9.1`` command line argument. @section Device options +@subsection Emulated device options + +@subsubsection -device virtio-blk,scsi=on|off (since 5.0.0) + +The virtio-blk SCSI passthrough feature is a legacy VIRTIO feature. VIRTIO 1.0 +and later do not support it because the virtio-scsi device was introduced for +full SCSI support. Use virtio-scsi instead when SCSI passthrough is required. + +Note this also applies to ``-device virtio-blk-pci,scsi=on|off'', which is an +alias. + @subsection Block device options @subsubsection "backing": "" (since 2.12.0) @@ -373,6 +384,14 @@ guarantees must resolve the CPU model aliases using te ``alias-of'' field returned by the ``query-cpu-definitions'' QMP command. +While those guarantees are kept, the return value of +``query-cpu-definitions'' will have existing CPU model aliases +point to a version that doesn't break runnability guarantees +(specifically, version 1 of those CPU models). In future QEMU +versions, aliases will point to newer CPU model versions +depending on the machine type, so management software must +resolve CPU model aliases before starting a virtual machine. + @node Recently removed features @appendix Recently removed features diff --git a/qemu-img.c b/qemu-img.c index 95a24b9762..6233b8ca56 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2680,7 +2680,10 @@ static ImageInfoList *collect_image_info_list(bool image_opts, blk_unref(blk); + /* Clear parameters that only apply to the topmost image */ filename = fmt = NULL; + image_opts = false; + if (chain) { if (info->has_full_backing_filename) { filename = info->full_backing_filename; diff --git a/roms/config.seabios-128k b/roms/config.seabios-128k index a17502ca0f..c43912bf9d 100644 --- a/roms/config.seabios-128k +++ b/roms/config.seabios-128k @@ -15,3 +15,4 @@ CONFIG_PVSCSI=n CONFIG_NVME=n CONFIG_USE_SMM=n CONFIG_VGAHOOKS=n +CONFIG_HOST_BIOS_GEOMETRY=n diff --git a/roms/seabios b/roms/seabios -Subproject c9ba5276e3217ac6a1ec772dbebf568ba3a8a55 +Subproject f21b5a4aeb020f2a5e2c6503f906a9349dd2f06 diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c index b064513d44..b75f813b40 100644 --- a/target/arm/arm-powerctl.c +++ b/target/arm/arm-powerctl.c @@ -127,6 +127,9 @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state, target_cpu->env.regs[0] = info->context_id; } + /* CP15 update requires rebuilding hflags */ + arm_rebuild_hflags(&target_cpu->env); + /* Start the new CPU at the requested address */ cpu_set_pc(target_cpu_state, info->entry); diff --git a/target/arm/cpu.c b/target/arm/cpu.c index dd51adac05..d62fd5fdc6 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -976,6 +976,10 @@ static void arm_cpu_initfn(Object *obj) } } +static Property arm_cpu_gt_cntfrq_property = + DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz, + NANOSECONDS_PER_SECOND / GTIMER_SCALE); + static Property arm_cpu_reset_cbar_property = DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0); @@ -1055,6 +1059,30 @@ static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name, visit_type_uint32(v, name, &cpu->init_svtor, errp); } +unsigned int gt_cntfrq_period_ns(ARMCPU *cpu) +{ + /* + * The exact approach to calculating guest ticks is: + * + * muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), cpu->gt_cntfrq_hz, + * NANOSECONDS_PER_SECOND); + * + * We don't do that. Rather we intentionally use integer division + * truncation below and in the caller for the conversion of host monotonic + * time to guest ticks to provide the exact inverse for the semantics of + * the QEMUTimer scale factor. QEMUTimer's scale facter is an integer, so + * it loses precision when representing frequencies where + * `(NANOSECONDS_PER_SECOND % cpu->gt_cntfrq) > 0` holds. Failing to + * provide an exact inverse leads to scheduling timers with negative + * periods, which in turn leads to sticky behaviour in the guest. + * + * Finally, CNTFRQ is effectively capped at 1GHz to ensure our scale factor + * cannot become zero. + */ + return NANOSECONDS_PER_SECOND > cpu->gt_cntfrq_hz ? + NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1; +} + void arm_cpu_post_init(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); @@ -1172,6 +1200,11 @@ void arm_cpu_post_init(Object *obj) qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property, &error_abort); + + if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) { + qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property, + &error_abort); + } } static void arm_cpu_finalizefn(Object *obj) @@ -1251,14 +1284,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } } - cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, - arm_gt_ptimer_cb, cpu); - cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, - arm_gt_vtimer_cb, cpu); - cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, - arm_gt_htimer_cb, cpu); - cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, - arm_gt_stimer_cb, cpu); + + { + uint64_t scale; + + if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) { + if (!cpu->gt_cntfrq_hz) { + error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz", + cpu->gt_cntfrq_hz); + return; + } + scale = gt_cntfrq_period_ns(cpu); + } else { + scale = GTIMER_SCALE; + } + + cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale, + arm_gt_ptimer_cb, cpu); + cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale, + arm_gt_vtimer_cb, cpu); + cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, scale, + arm_gt_htimer_cb, cpu); + cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale, + arm_gt_stimer_cb, cpu); + } #endif cpu_exec_realizefn(cs, &local_err); diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 5f70e9e043..40f2c45e17 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -932,8 +932,13 @@ struct ARMCPU { */ DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ); DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ); + + /* Generic timer counter frequency, in Hz */ + uint64_t gt_cntfrq_hz; }; +unsigned int gt_cntfrq_period_ns(ARMCPU *cpu); + void arm_cpu_post_init(Object *obj); uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz); diff --git a/target/arm/helper.c b/target/arm/helper.c index 5074b5f69c..b6bec42f48 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -2449,7 +2449,9 @@ static CPAccessResult gt_stimer_access(CPUARMState *env, static uint64_t gt_get_countervalue(CPUARMState *env) { - return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE; + ARMCPU *cpu = env_archcpu(env); + + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu); } static void gt_recalc_timer(ARMCPU *cpu, int timeridx) @@ -2485,10 +2487,11 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx) * set the timer for as far in the future as possible. When the * timer expires we will reset the timer for any remaining period. */ - if (nexttick > INT64_MAX / GTIMER_SCALE) { - nexttick = INT64_MAX / GTIMER_SCALE; + if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) { + timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX); + } else { + timer_mod(cpu->gt_timer[timeridx], nexttick); } - timer_mod(cpu->gt_timer[timeridx], nexttick); trace_arm_gt_recalc(timeridx, irqstate, nexttick); } else { /* Timer disabled: ISTATUS and timer output always clear */ @@ -2720,6 +2723,13 @@ void arm_gt_stimer_cb(void *opaque) gt_recalc_timer(cpu, GTIMER_SEC); } +static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque) +{ + ARMCPU *cpu = env_archcpu(env); + + cpu->env.cp15.c14_cntfrq = cpu->gt_cntfrq_hz; +} + static const ARMCPRegInfo generic_timer_cp_reginfo[] = { /* Note that CNTFRQ is purely reads-as-written for the benefit * of software; writing it doesn't actually change the timer frequency. @@ -2734,7 +2744,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0, .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access, .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq), - .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE, + .resetfn = arm_gt_cntfrq_reset, }, /* overall control: mostly access permissions */ { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH, @@ -2913,11 +2923,13 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) { + ARMCPU *cpu = env_archcpu(env); + /* Currently we have no support for QEMUTimer in linux-user so we * can't call gt_get_countervalue(env), instead we directly * call the lower level functions. */ - return cpu_get_clock() / GTIMER_SCALE; + return cpu_get_clock() / gt_cntfrq_period_ns(cpu); } static const ARMCPRegInfo generic_timer_cp_reginfo[] = { @@ -11500,6 +11512,20 @@ void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el) env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx); } +static inline void assert_hflags_rebuild_correctly(CPUARMState *env) +{ +#ifdef CONFIG_DEBUG_TCG + uint32_t env_flags_current = env->hflags; + uint32_t env_flags_rebuilt = rebuild_hflags_internal(env); + + if (unlikely(env_flags_current != env_flags_rebuilt)) { + fprintf(stderr, "TCG hflags mismatch (current:0x%08x rebuilt:0x%08x)\n", + env_flags_current, env_flags_rebuilt); + abort(); + } +#endif +} + void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { @@ -11507,9 +11533,7 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, uint32_t pstate_for_ss; *cs_base = 0; -#ifdef CONFIG_DEBUG_TCG - assert(flags == rebuild_hflags_internal(env)); -#endif + assert_hflags_rebuild_correctly(env); if (FIELD_EX32(flags, TBFLAG_ANY, AARCH64_STATE)) { *pc = env->pc; diff --git a/target/i386/cpu.c b/target/i386/cpu.c index e1eb9f4739..31556b7ec4 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -3981,7 +3981,13 @@ static PropValue tcg_default_props[] = { }; -X86CPUVersion default_cpu_version = CPU_VERSION_LATEST; +/* + * We resolve CPU model aliases using -v1 when using "-machine + * none", but this is just for compatibility while libvirt isn't + * adapted to resolve CPU model versions before creating VMs. + * See "Runnability guarantee of CPU models" at * qemu-deprecated.texi. + */ +X86CPUVersion default_cpu_version = 1; void x86_cpu_set_default_version(X86CPUVersion version) { diff --git a/tests/Makefile.include b/tests/Makefile.include index 31b86674e5..9146e1bdee 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -1157,7 +1157,6 @@ TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results AVOCADO_SHOW=app AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGET_DIRS))) -ifneq ($(PYTHON2),y) $(TESTS_VENV_DIR): $(TESTS_VENV_REQ) $(call quiet-command, \ $(PYTHON) -m venv --system-site-packages $@, \ @@ -1166,10 +1165,6 @@ $(TESTS_VENV_DIR): $(TESTS_VENV_REQ) $(TESTS_VENV_DIR)/bin/python -m pip -q install -r $(TESTS_VENV_REQ), \ PIP, $(TESTS_VENV_REQ)) $(call quiet-command, touch $@) -else -$(TESTS_VENV_DIR): - $(error "venv directory for tests requires Python 3") -endif $(TESTS_RESULTS_DIR): $(call quiet-command, mkdir -p $@, \ diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index f3766f2a81..be35bde06f 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -943,7 +943,7 @@ class TestSetSpeed(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('block-stream', device='drive0', speed=-1) - self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'") + self.assert_qmp(result, 'error/desc', "Parameter 'speed' expects a non-negative value") self.assert_no_active_block_jobs() @@ -952,7 +952,7 @@ class TestSetSpeed(iotests.QMPTestCase): self.assert_qmp(result, 'return', {}) result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) - self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'") + self.assert_qmp(result, 'error/desc', "Parameter 'speed' expects a non-negative value") self.cancel_and_wait(resume=True) diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049 index c100d30ed0..051a1c79e0 100755 --- a/tests/qemu-iotests/049 +++ b/tests/qemu-iotests/049 @@ -78,6 +78,11 @@ for s in $sizes; do test_qemu_img create -f $IMGFMT -o size=$s "$TEST_IMG" done +echo "== 4. Specify size twice (-o and traditional parameter) ==" +echo + +test_qemu_img create -f $IMGFMT -o size=10M "$TEST_IMG" 20M + echo "== Check correct interpretation of suffixes for cluster size ==" echo sizes="1024 1024b 1k 1K 1M " diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out index 6b505408dd..affa55b341 100644 --- a/tests/qemu-iotests/049.out +++ b/tests/qemu-iotests/049.out @@ -121,6 +121,11 @@ qemu-img: TEST_DIR/t.qcow2: Parameter 'size' expects a non-negative number below Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta- and exabytes, respectively. +== 4. Specify size twice (-o and traditional parameter) == + +qemu-img create -f qcow2 -o size=10M TEST_DIR/t.qcow2 20M +qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once + == Check correct interpretation of suffixes for cluster size == qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 53bcdbc911..a13bce2fd0 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -41,6 +41,7 @@ _supported_proto file # A compat=0.10 image is created in this test which does not support anything # other than refcount_bits=16 _unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' +_require_drivers nbd do_run_qemu() { diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206 index 5bb738bf23..9f16a7df8d 100755 --- a/tests/qemu-iotests/206 +++ b/tests/qemu-iotests/206 @@ -25,16 +25,6 @@ from iotests import imgfmt iotests.verify_image_format(supported_fmts=['qcow2']) -def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', - filters=[iotests.filter_qmp_testfiles], - job_id='job0', options=options) - - if 'return' in result: - assert result['return'] == {} - vm.run_job('job0') - iotests.log("") - with iotests.FilePath('t.qcow2') as disk_path, \ iotests.FilePath('t.qcow2.base') as backing_path, \ iotests.VM() as vm: @@ -50,18 +40,18 @@ with iotests.FilePath('t.qcow2') as disk_path, \ size = 128 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) vm.qmp_log('blockdev-add', filters=[iotests.filter_qmp_testfiles], driver='file', filename=disk_path, node_name='imgfile') - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'imgfile', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) vm.shutdown() iotests.img_info_log(disk_path) @@ -76,23 +66,23 @@ with iotests.FilePath('t.qcow2') as disk_path, \ size = 64 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0, - 'preallocation': 'off', - 'nocow': False }) - - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'version': 'v3', - 'cluster-size': 65536, - 'preallocation': 'off', - 'lazy-refcounts': False, - 'refcount-bits': 16 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0, + 'preallocation': 'off', + 'nocow': False }) + + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'version': 'v3', + 'cluster-size': 65536, + 'preallocation': 'off', + 'lazy-refcounts': False, + 'refcount-bits': 16 }) vm.shutdown() iotests.img_info_log(disk_path) @@ -107,23 +97,23 @@ with iotests.FilePath('t.qcow2') as disk_path, \ size = 32 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0, - 'preallocation': 'falloc', - 'nocow': True }) - - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'version': 'v3', - 'cluster-size': 2097152, - 'preallocation': 'metadata', - 'lazy-refcounts': True, - 'refcount-bits': 1 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0, + 'preallocation': 'falloc', + 'nocow': True }) + + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'version': 'v3', + 'cluster-size': 2097152, + 'preallocation': 'metadata', + 'lazy-refcounts': True, + 'refcount-bits': 1 }) vm.shutdown() iotests.img_info_log(disk_path) @@ -135,20 +125,20 @@ with iotests.FilePath('t.qcow2') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) - - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'backing-file': backing_path, - 'backing-fmt': 'qcow2', - 'version': 'v2', - 'cluster-size': 512 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'backing-file': backing_path, + 'backing-fmt': 'qcow2', + 'version': 'v2', + 'cluster-size': 512 }) vm.shutdown() iotests.img_info_log(disk_path) @@ -160,22 +150,22 @@ with iotests.FilePath('t.qcow2') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'encrypt': { - 'format': 'luks', - 'key-secret': 'keysec0', - 'cipher-alg': 'twofish-128', - 'cipher-mode': 'ctr', - 'ivgen-alg': 'plain64', - 'ivgen-hash-alg': 'md5', - 'hash-alg': 'sha1', - 'iter-time': 10, - }}) + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'encrypt': { + 'format': 'luks', + 'key-secret': 'keysec0', + 'cipher-alg': 'twofish-128', + 'cipher-mode': 'ctr', + 'ivgen-alg': 'plain64', + 'ivgen-hash-alg': 'md5', + 'hash-alg': 'sha1', + 'iter-time': 10, + }}) vm.shutdown() iotests.img_info_log(disk_path) @@ -187,9 +177,9 @@ with iotests.FilePath('t.qcow2') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': "this doesn't exist", - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) vm.shutdown() # @@ -211,9 +201,9 @@ with iotests.FilePath('t.qcow2') as disk_path, \ vm.launch() for size in [ 1234, 18446744073709551104, 9223372036854775808, 9223372036854775296 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': size }) vm.shutdown() # @@ -222,20 +212,20 @@ with iotests.FilePath('t.qcow2') as disk_path, \ iotests.log("=== Invalid version ===") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'version': 'v1' }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'version': 'v2', - 'lazy-refcounts': True }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'version': 'v2', - 'refcount-bits': 8 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'version': 'v1' }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'version': 'v2', + 'lazy-refcounts': True }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'version': 'v2', + 'refcount-bits': 8 }) vm.shutdown() # @@ -244,15 +234,15 @@ with iotests.FilePath('t.qcow2') as disk_path, \ iotests.log("=== Invalid backing file options ===") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'backing-file': '/dev/null', - 'preallocation': 'full' }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'backing-fmt': imgfmt }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'backing-file': '/dev/null', + 'preallocation': 'full' }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'backing-fmt': imgfmt }) vm.shutdown() # @@ -262,14 +252,14 @@ with iotests.FilePath('t.qcow2') as disk_path, \ vm.launch() for csize in [ 1234, 128, 4194304, 0 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'cluster-size': csize }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 281474976710656, - 'cluster-size': 512 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'cluster-size': csize }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 281474976710656, + 'cluster-size': 512 }) vm.shutdown() # @@ -279,8 +269,8 @@ with iotests.FilePath('t.qcow2') as disk_path, \ vm.launch() for refcount_bits in [ 128, 0, 7 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'refcount-bits': refcount_bits }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'refcount-bits': refcount_bits }) vm.shutdown() diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 index ec8c1d06f0..812ab34e47 100755 --- a/tests/qemu-iotests/207 +++ b/tests/qemu-iotests/207 @@ -35,13 +35,7 @@ def filter_hash(qmsg): return iotests.filter_qmp(qmsg, _filter) def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options, - filters=[iotests.filter_qmp_testfiles, filter_hash]) - - if 'return' in result: - assert result['return'] == {} - vm.run_job('job0') - iotests.log("") + vm.blockdev_create(options, filters=[iotests.filter_qmp_testfiles, filter_hash]) with iotests.FilePath('t.img') as disk_path, \ iotests.VM() as vm: diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210 index 565e3b7b9b..4ca0fe26ef 100755 --- a/tests/qemu-iotests/210 +++ b/tests/qemu-iotests/210 @@ -26,15 +26,6 @@ from iotests import imgfmt iotests.verify_image_format(supported_fmts=['luks']) iotests.verify_protocol(supported=['file']) -def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options, - filters=[iotests.filter_qmp_testfiles]) - - if 'return' in result: - assert result['return'] == {} - vm.run_job('job0') - iotests.log("") - with iotests.FilePath('t.luks') as disk_path, \ iotests.VM() as vm: @@ -49,18 +40,18 @@ with iotests.FilePath('t.luks') as disk_path, \ size = 128 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'imgfile', - 'key-secret': 'keysec0', - 'size': size, - 'iter-time': 10 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'imgfile', + 'key-secret': 'keysec0', + 'size': size, + 'iter-time': 10 }) vm.shutdown() # TODO Proper support for images to be used with imgopts and/or protocols @@ -79,22 +70,22 @@ with iotests.FilePath('t.luks') as disk_path, \ size = 64 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'key-secret': 'keysec0', - 'cipher-alg': 'twofish-128', - 'cipher-mode': 'ctr', - 'ivgen-alg': 'plain64', - 'ivgen-hash-alg': 'md5', - 'hash-alg': 'sha1', - 'iter-time': 10 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'key-secret': 'keysec0', + 'cipher-alg': 'twofish-128', + 'cipher-mode': 'ctr', + 'ivgen-alg': 'plain64', + 'ivgen-hash-alg': 'md5', + 'hash-alg': 'sha1', + 'iter-time': 10 }) vm.shutdown() # TODO Proper support for images to be used with imgopts and/or protocols @@ -113,9 +104,9 @@ with iotests.FilePath('t.luks') as disk_path, \ size = 64 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': "this doesn't exist", - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) vm.shutdown() # @@ -126,11 +117,11 @@ with iotests.FilePath('t.luks') as disk_path, \ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'key-secret': 'keysec0', - 'size': 0, - 'iter-time': 10 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'key-secret': 'keysec0', + 'size': 0, + 'iter-time': 10 }) vm.shutdown() # TODO Proper support for images to be used with imgopts and/or protocols @@ -157,10 +148,10 @@ with iotests.FilePath('t.luks') as disk_path, \ vm.launch() for size in [ 18446744073709551104, 9223372036854775808, 9223372036854775296 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'key-secret': 'keysec0', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'key-secret': 'keysec0', + 'size': size }) vm.shutdown() # diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211 index 6afc894f76..8834ebfe85 100755 --- a/tests/qemu-iotests/211 +++ b/tests/qemu-iotests/211 @@ -27,15 +27,9 @@ iotests.verify_image_format(supported_fmts=['vdi']) iotests.verify_protocol(supported=['file']) def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options, - filters=[iotests.filter_qmp_testfiles]) - - if 'return' in result: - assert result['return'] == {} - error = vm.run_job('job0') - if error and 'Could not allocate bmap' in error: - iotests.notrun('Insufficient memory') - iotests.log("") + error = vm.blockdev_create(options) + if error and 'Could not allocate bmap' in error: + iotests.notrun('Insufficient memory') with iotests.FilePath('t.vdi') as disk_path, \ iotests.VM() as vm: diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212 index 42b74f208b..8f3ccc7b15 100755 --- a/tests/qemu-iotests/212 +++ b/tests/qemu-iotests/212 @@ -26,15 +26,6 @@ from iotests import imgfmt iotests.verify_image_format(supported_fmts=['parallels']) iotests.verify_protocol(supported=['file']) -def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options, - filters=[iotests.filter_qmp_testfiles]) - - if 'return' in result: - assert result['return'] == {} - vm.run_job('job0') - iotests.log("") - with iotests.FilePath('t.parallels') as disk_path, \ iotests.VM() as vm: @@ -47,16 +38,16 @@ with iotests.FilePath('t.parallels') as disk_path, \ size = 128 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'imgfile', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) vm.shutdown() iotests.img_info_log(disk_path) @@ -71,16 +62,16 @@ with iotests.FilePath('t.parallels') as disk_path, \ size = 64 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'cluster-size': 1048576 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'cluster-size': 1048576 }) vm.shutdown() iotests.img_info_log(disk_path) @@ -95,16 +86,16 @@ with iotests.FilePath('t.parallels') as disk_path, \ size = 32 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'cluster-size': 65536 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'cluster-size': 65536 }) vm.shutdown() iotests.img_info_log(disk_path) @@ -116,9 +107,9 @@ with iotests.FilePath('t.parallels') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': "this doesn't exist", - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) vm.shutdown() # @@ -129,9 +120,9 @@ with iotests.FilePath('t.parallels') as disk_path, \ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 0 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 0 }) vm.shutdown() iotests.img_info_log(disk_path) @@ -143,9 +134,9 @@ with iotests.FilePath('t.parallels') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 4503599627369984}) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 4503599627369984}) vm.shutdown() iotests.img_info_log(disk_path) @@ -171,9 +162,9 @@ with iotests.FilePath('t.parallels') as disk_path, \ vm.launch() for size in [ 1234, 18446744073709551104, 9223372036854775808, 9223372036854775296, 4503599627370497 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': size }) vm.shutdown() # @@ -185,12 +176,12 @@ with iotests.FilePath('t.parallels') as disk_path, \ vm.launch() for csize in [ 1234, 128, 4294967296, 9223372036854775808, 18446744073709551104, 0 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'cluster-size': csize }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 281474976710656, - 'cluster-size': 512 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'cluster-size': csize }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 281474976710656, + 'cluster-size': 512 }) vm.shutdown() diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213 index 5604f3cebb..3fc8dc6eaa 100755 --- a/tests/qemu-iotests/213 +++ b/tests/qemu-iotests/213 @@ -26,15 +26,6 @@ from iotests import imgfmt iotests.verify_image_format(supported_fmts=['vhdx']) iotests.verify_protocol(supported=['file']) -def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options, - filters=[iotests.filter_qmp_testfiles]) - - if 'return' in result: - assert result['return'] == {} - vm.run_job('job0') - iotests.log("") - with iotests.FilePath('t.vhdx') as disk_path, \ iotests.VM() as vm: @@ -47,16 +38,16 @@ with iotests.FilePath('t.vhdx') as disk_path, \ size = 128 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'imgfile', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) vm.shutdown() iotests.img_info_log(disk_path) @@ -71,19 +62,19 @@ with iotests.FilePath('t.vhdx') as disk_path, \ size = 64 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'log-size': 1048576, - 'block-size': 8388608, - 'subformat': 'dynamic', - 'block-state-zero': True }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'log-size': 1048576, + 'block-size': 8388608, + 'subformat': 'dynamic', + 'block-state-zero': True }) vm.shutdown() iotests.img_info_log(disk_path) @@ -98,19 +89,19 @@ with iotests.FilePath('t.vhdx') as disk_path, \ size = 32 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'log-size': 8388608, - 'block-size': 268435456, - 'subformat': 'fixed', - 'block-state-zero': False }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'log-size': 8388608, + 'block-size': 268435456, + 'subformat': 'fixed', + 'block-state-zero': False }) vm.shutdown() iotests.img_info_log(disk_path) @@ -122,9 +113,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': "this doesn't exist", - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) vm.shutdown() # @@ -135,9 +126,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 0 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 0 }) vm.shutdown() iotests.img_info_log(disk_path) @@ -149,9 +140,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 70368744177664 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 70368744177664 }) vm.shutdown() iotests.img_info_log(disk_path) @@ -176,9 +167,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \ vm.launch() for size in [ 18446744073709551104, 9223372036854775808, 9223372036854775296, 70368744177665 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': size }) vm.shutdown() # @@ -189,10 +180,10 @@ with iotests.FilePath('t.vhdx') as disk_path, \ vm.launch() for bsize in [ 1234567, 128, 3145728, 536870912, 0 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'block-size': bsize }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'block-size': bsize }) vm.shutdown() # @@ -203,8 +194,8 @@ with iotests.FilePath('t.vhdx') as disk_path, \ vm.launch() for lsize in [ 1234567, 128, 4294967296, 0 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 67108864, - 'log-size': lsize }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'log-size': lsize }) vm.shutdown() diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237 index 06897f8c87..a2242a4736 100755 --- a/tests/qemu-iotests/237 +++ b/tests/qemu-iotests/237 @@ -26,15 +26,6 @@ from iotests import imgfmt iotests.verify_image_format(supported_fmts=['vmdk']) -def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options, - filters=[iotests.filter_qmp_testfiles]) - - if 'return' in result: - assert result['return'] == {} - vm.run_job('job0') - iotests.log("") - with iotests.FilePath('t.vmdk') as disk_path, \ iotests.FilePath('t.vmdk.1') as extent1_path, \ iotests.FilePath('t.vmdk.2') as extent2_path, \ @@ -50,16 +41,16 @@ with iotests.FilePath('t.vmdk') as disk_path, \ size = 5 * 1024 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=disk_path, node_name='imgfile', filters=[iotests.filter_qmp_testfiles]) - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'imgfile', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) vm.shutdown() iotests.img_info_log(disk_path) @@ -74,21 +65,21 @@ with iotests.FilePath('t.vmdk') as disk_path, \ size = 64 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) - - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'extents': [], - 'subformat': 'monolithicSparse', - 'adapter-type': 'ide', - 'hwversion': '4', - 'zeroed-grain': False }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'extents': [], + 'subformat': 'monolithicSparse', + 'adapter-type': 'ide', + 'hwversion': '4', + 'zeroed-grain': False }) vm.shutdown() iotests.img_info_log(disk_path) @@ -103,20 +94,20 @@ with iotests.FilePath('t.vmdk') as disk_path, \ size = 32 * 1024 * 1024 vm.launch() - blockdev_create(vm, { 'driver': 'file', - 'filename': disk_path, - 'size': 0 }) - - blockdev_create(vm, { 'driver': imgfmt, - 'file': { - 'driver': 'file', - 'filename': disk_path, - }, - 'size': size, - 'extents': [], - 'subformat': 'monolithicSparse', - 'adapter-type': 'buslogic', - 'zeroed-grain': True }) + vm.blockdev_create({ 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.blockdev_create({ 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'extents': [], + 'subformat': 'monolithicSparse', + 'adapter-type': 'buslogic', + 'zeroed-grain': True }) vm.shutdown() iotests.img_info_log(disk_path) @@ -128,9 +119,9 @@ with iotests.FilePath('t.vmdk') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': "this doesn't exist", - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) vm.shutdown() # @@ -148,10 +139,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \ vm.launch() for adapter_type in [ 'ide', 'buslogic', 'lsilogic', 'legacyESX' ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': size, - 'adapter-type': adapter_type }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'adapter-type': adapter_type }) vm.shutdown() # Invalid @@ -160,10 +151,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \ vm.launch() for adapter_type in [ 'foo', 'IDE', 'legacyesx', 1 ]: - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': size, - 'adapter-type': adapter_type }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'adapter-type': adapter_type }) vm.shutdown() # @@ -185,10 +176,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': size, - 'subformat': 'monolithicFlat' }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': 'monolithicFlat' }) vm.shutdown() # Correct extent @@ -196,11 +187,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': size, - 'subformat': 'monolithicFlat', - 'extents': ['ext1'] }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': 'monolithicFlat', + 'extents': ['ext1'] }) vm.shutdown() # Extra extent @@ -208,11 +199,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \ iotests.log("") vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': 512, - 'subformat': 'monolithicFlat', - 'extents': ['ext1', 'ext2', 'ext3'] }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': 512, + 'subformat': 'monolithicFlat', + 'extents': ['ext1', 'ext2', 'ext3'] }) vm.shutdown() # Split formats @@ -228,11 +219,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \ extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ] vm.launch() - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'node0', - 'size': size, - 'subformat': subfmt, - 'extents': extents }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': subfmt, + 'extents': extents }) vm.shutdown() iotests.img_info_log(disk_path) diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255 index 3632d507d0..0ba03d9e61 100755 --- a/tests/qemu-iotests/255 +++ b/tests/qemu-iotests/255 @@ -25,16 +25,6 @@ from iotests import imgfmt iotests.verify_image_format(supported_fmts=['qcow2']) -def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', - filters=[iotests.filter_qmp_testfiles], - job_id='job0', options=options) - - if 'return' in result: - assert result['return'] == {} - vm.run_job('job0') - iotests.log("") - iotests.log('Finishing a commit job with background reads') iotests.log('============================================') iotests.log('') diff --git a/tests/qemu-iotests/266 b/tests/qemu-iotests/266 index 5b35cd67e4..c353cf88ee 100755 --- a/tests/qemu-iotests/266 +++ b/tests/qemu-iotests/266 @@ -22,15 +22,6 @@ import iotests from iotests import imgfmt -def blockdev_create(vm, options): - result = vm.qmp_log('blockdev-create', job_id='job0', options=options, - filters=[iotests.filter_qmp_testfiles]) - - if 'return' in result: - assert result['return'] == {} - vm.run_job('job0') - - # Successful image creation (defaults) def implicit_defaults(vm, file_path): iotests.log("=== Successful image creation (defaults) ===") @@ -40,9 +31,9 @@ def implicit_defaults(vm, file_path): # (Close to 64 MB) size = 8 * 964 * 17 * 512 - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'protocol-node', - 'size': size }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'protocol-node', + 'size': size }) # Successful image creation (explicit defaults) @@ -54,11 +45,11 @@ def explicit_defaults(vm, file_path): # (Close to 128 MB) size = 16 * 964 * 17 * 512 - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'protocol-node', - 'size': size, - 'subformat': 'dynamic', - 'force-size': False }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'protocol-node', + 'size': size, + 'subformat': 'dynamic', + 'force-size': False }) # Successful image creation (non-default options) @@ -69,11 +60,11 @@ def non_defaults(vm, file_path): # Not representable in CHS (fine with force-size=True) size = 1048576 - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'protocol-node', - 'size': size, - 'subformat': 'fixed', - 'force-size': True }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'protocol-node', + 'size': size, + 'subformat': 'fixed', + 'force-size': True }) # Size not representable in CHS with force-size=False @@ -84,10 +75,10 @@ def non_chs_size_without_force(vm, file_path): # Not representable in CHS (will not work with force-size=False) size = 1048576 - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'protocol-node', - 'size': size, - 'force-size': False }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'protocol-node', + 'size': size, + 'force-size': False }) # Zero size @@ -95,9 +86,9 @@ def zero_size(vm, file_path): iotests.log("=== Zero size===") iotests.log("") - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'protocol-node', - 'size': 0 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'protocol-node', + 'size': 0 }) # Maximum CHS size @@ -105,9 +96,9 @@ def maximum_chs_size(vm, file_path): iotests.log("=== Maximum CHS size===") iotests.log("") - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'protocol-node', - 'size': 16 * 65535 * 255 * 512 }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'protocol-node', + 'size': 16 * 65535 * 255 * 512 }) # Actual maximum size @@ -115,10 +106,10 @@ def maximum_size(vm, file_path): iotests.log("=== Actual maximum size===") iotests.log("") - blockdev_create(vm, { 'driver': imgfmt, - 'file': 'protocol-node', - 'size': 0xff000000 * 512, - 'force-size': True }) + vm.blockdev_create({ 'driver': imgfmt, + 'file': 'protocol-node', + 'size': 0xff000000 * 512, + 'force-size': True }) def main(): @@ -132,9 +123,9 @@ def main(): vm.launch() iotests.log('--- Creating empty file ---') - blockdev_create(vm, { 'driver': 'file', - 'filename': file_path, - 'size': 0 }) + vm.blockdev_create({ 'driver': 'file', + 'filename': file_path, + 'size': 0 }) vm.qmp_log('blockdev-add', driver='file', filename=file_path, node_name='protocol-node', diff --git a/tests/qemu-iotests/266.out b/tests/qemu-iotests/266.out index b11953e81f..5a7d7d01aa 100644 --- a/tests/qemu-iotests/266.out +++ b/tests/qemu-iotests/266.out @@ -3,6 +3,7 @@ {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}} {"return": {}} @@ -13,6 +14,7 @@ {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + image: TEST_IMG file format: IMGFMT virtual size: 64 MiB (67125248 bytes) @@ -23,6 +25,7 @@ cluster_size: 2097152 {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}} {"return": {}} @@ -33,6 +36,7 @@ cluster_size: 2097152 {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + image: TEST_IMG file format: IMGFMT virtual size: 128 MiB (134250496 bytes) @@ -43,6 +47,7 @@ cluster_size: 2097152 {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}} {"return": {}} @@ -53,6 +58,7 @@ cluster_size: 2097152 {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + image: TEST_IMG file format: IMGFMT virtual size: 1 MiB (1048576 bytes) @@ -62,6 +68,7 @@ virtual size: 1 MiB (1048576 bytes) {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}} {"return": {}} @@ -73,6 +80,7 @@ Job failed: The requested image size cannot be represented in CHS geometry {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + qemu-img: Could not open 'TEST_IMG': File too small for a VHD header --- Creating empty file --- @@ -80,6 +88,7 @@ qemu-img: Could not open 'TEST_IMG': File too small for a VHD header {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}} {"return": {}} @@ -90,6 +99,7 @@ qemu-img: Could not open 'TEST_IMG': File too small for a VHD header {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + image: TEST_IMG file format: IMGFMT virtual size: 0 B (0 bytes) @@ -100,6 +110,7 @@ cluster_size: 2097152 {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}} {"return": {}} @@ -110,6 +121,7 @@ cluster_size: 2097152 {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + image: TEST_IMG file format: IMGFMT virtual size: 127 GiB (136899993600 bytes) @@ -120,6 +132,7 @@ cluster_size: 2097152 {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}} {"return": {}} @@ -130,6 +143,7 @@ cluster_size: 2097152 {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} + image: TEST_IMG file format: IMGFMT virtual size: 1.99 TiB (2190433320960 bytes) diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267 index 170e173c0a..b823668e29 100755 --- a/tests/qemu-iotests/267 +++ b/tests/qemu-iotests/267 @@ -40,6 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file _supported_os Linux +_require_drivers copy-on-read # Internal snapshots are (currently) impossible with refcount_bits=1 _unsupported_imgopts 'refcount_bits=1[^0-9]' diff --git a/tests/qemu-iotests/273 b/tests/qemu-iotests/273 index 98a672516d..d598c47d9b 100755 --- a/tests/qemu-iotests/273 +++ b/tests/qemu-iotests/273 @@ -48,7 +48,8 @@ do_run_qemu() run_qemu() { do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp | - _filter_generated_node_ids | _filter_imgfmt | _filter_actual_image_size + _filter_generated_node_ids | _filter_imgfmt | + _filter_actual_image_size | _filter_img_info } TEST_IMG="$TEST_IMG.base" _make_test_img 64M diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out index c410fee5c4..684b8d6f77 100644 --- a/tests/qemu-iotests/273.out +++ b/tests/qemu-iotests/273.out @@ -38,15 +38,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev "cluster-size": 65536, "format": "IMGFMT", "actual-size": SIZE, - "format-specific": { - "type": "IMGFMT", - "data": { - "compat": "1.1", - "lazy-refcounts": false, - "refcount-bits": 16, - "corrupt": false - } - }, "full-backing-filename": "TEST_DIR/t.IMGFMT.base", "backing-filename": "TEST_DIR/t.IMGFMT.base", "dirty-flag": false @@ -57,15 +48,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev "cluster-size": 65536, "format": "IMGFMT", "actual-size": SIZE, - "format-specific": { - "type": "IMGFMT", - "data": { - "compat": "1.1", - "lazy-refcounts": false, - "refcount-bits": 16, - "corrupt": false - } - }, "full-backing-filename": "TEST_DIR/t.IMGFMT.mid", "backing-filename": "TEST_DIR/t.IMGFMT.mid", "dirty-flag": false @@ -136,15 +118,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev "cluster-size": 65536, "format": "IMGFMT", "actual-size": SIZE, - "format-specific": { - "type": "IMGFMT", - "data": { - "compat": "1.1", - "lazy-refcounts": false, - "refcount-bits": 16, - "corrupt": false - } - }, "full-backing-filename": "TEST_DIR/t.IMGFMT.base", "backing-filename": "TEST_DIR/t.IMGFMT.base", "dirty-flag": false diff --git a/tests/qemu-iotests/279 b/tests/qemu-iotests/279 new file mode 100755 index 0000000000..6682376808 --- /dev/null +++ b/tests/qemu-iotests/279 @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# +# Test qemu-img --backing-chain --image-opts +# +# Copyright (C) 2019 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/>. +# + +seq=$(basename "$0") +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + rm -f "$TEST_IMG.mid" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +# Backing files are required... +_supported_fmt qcow qcow2 vmdk qed +_supported_proto file +_supported_os Linux + +TEST_IMG="$TEST_IMG.base" _make_test_img 64M +TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.mid" + +echo +echo '== qemu-img info --backing-chain ==' +_img_info --backing-chain | _filter_img_info + +echo +echo '== qemu-img info --backing-chain --image-opts ==' +TEST_IMG="driver=qcow2,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts | _filter_img_info + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/279.out b/tests/qemu-iotests/279.out new file mode 100644 index 0000000000..f4dc6c69cb --- /dev/null +++ b/tests/qemu-iotests/279.out @@ -0,0 +1,35 @@ +QA output created by 279 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid + +== qemu-img info --backing-chain == +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 64 MiB (67108864 bytes) +backing file: TEST_DIR/t.IMGFMT.mid + +image: TEST_DIR/t.IMGFMT.mid +file format: IMGFMT +virtual size: 64 MiB (67108864 bytes) +backing file: TEST_DIR/t.IMGFMT.base + +image: TEST_DIR/t.IMGFMT.base +file format: IMGFMT +virtual size: 64 MiB (67108864 bytes) + +== qemu-img info --backing-chain --image-opts == +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 64 MiB (67108864 bytes) +backing file: TEST_DIR/t.IMGFMT.mid + +image: TEST_DIR/t.IMGFMT.mid +file format: IMGFMT +virtual size: 64 MiB (67108864 bytes) +backing file: TEST_DIR/t.IMGFMT.base + +image: TEST_DIR/t.IMGFMT.base +file format: IMGFMT +virtual size: 64 MiB (67108864 bytes) +*** done diff --git a/tests/qemu-iotests/280 b/tests/qemu-iotests/280 new file mode 100755 index 0000000000..0b1fa8e1d8 --- /dev/null +++ b/tests/qemu-iotests/280 @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 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: Kevin Wolf <kwolf@redhat.com> +# +# Test migration to file for taking an external snapshot with VM state. + +import iotests +import os + +iotests.verify_image_format(supported_fmts=['qcow2']) +iotests.verify_protocol(supported=['file']) +iotests.verify_platform(['linux']) + +with iotests.FilePath('base') as base_path , \ + iotests.FilePath('top') as top_path, \ + iotests.VM() as vm: + + iotests.qemu_img_log('create', '-f', iotests.imgfmt, base_path, '64M') + + iotests.log('=== Launch VM ===') + vm.add_object('iothread,id=iothread0') + vm.add_blockdev('file,filename=%s,node-name=base-file' % (base_path)) + vm.add_blockdev('%s,file=base-file,node-name=base-fmt' % (iotests.imgfmt)) + vm.add_device('virtio-blk,drive=base-fmt,iothread=iothread0,id=vda') + vm.launch() + + vm.enable_migration_events('VM') + + iotests.log('\n=== Migrate to file ===') + vm.qmp_log('migrate', uri='exec:cat > /dev/null') + + with iotests.Timeout(3, 'Migration does not complete'): + vm.wait_migration() + + iotests.log('\nVM is now stopped:') + iotests.log(vm.qmp('query-migrate')['return']['status']) + vm.qmp_log('query-status') + + iotests.log('\n=== Create a snapshot of the disk image ===') + vm.blockdev_create({ + 'driver': 'file', + 'filename': top_path, + 'size': 0, + }) + vm.qmp_log('blockdev-add', node_name='top-file', + driver='file', filename=top_path, + filters=[iotests.filter_qmp_testfiles]) + + vm.blockdev_create({ + 'driver': iotests.imgfmt, + 'file': 'top-file', + 'size': 1024 * 1024, + }) + vm.qmp_log('blockdev-add', node_name='top-fmt', + driver=iotests.imgfmt, file='top-file') + + vm.qmp_log('blockdev-snapshot', node='base-fmt', overlay='top-fmt') + + iotests.log('\n=== Resume the VM and simulate a write request ===') + vm.qmp_log('cont') + iotests.log(vm.hmp_qemu_io('-d vda/virtio-backend', 'write 4k 4k')) + + iotests.log('\n=== Commit it to the backing file ===') + result = vm.qmp_log('block-commit', job_id='job0', auto_dismiss=False, + device='top-fmt', top_node='top-fmt', + filters=[iotests.filter_qmp_testfiles]) + if 'return' in result: + vm.run_job('job0') diff --git a/tests/qemu-iotests/280.out b/tests/qemu-iotests/280.out new file mode 100644 index 0000000000..5d382faaa8 --- /dev/null +++ b/tests/qemu-iotests/280.out @@ -0,0 +1,50 @@ +Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 + +=== Launch VM === +Enabling migration QMP events on VM... +{"return": {}} + +=== Migrate to file === +{"execute": "migrate", "arguments": {"uri": "exec:cat > /dev/null"}} +{"return": {}} +{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + +VM is now stopped: +completed +{"execute": "query-status", "arguments": {}} +{"return": {"running": false, "singlestep": false, "status": "postmigrate"}} + +=== Create a snapshot of the disk image === +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-top", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-top", "node-name": "top-file"}} +{"return": {}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "top-file", "size": 1048576}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": "top-file", "node-name": "top-fmt"}} +{"return": {}} +{"execute": "blockdev-snapshot", "arguments": {"node": "base-fmt", "overlay": "top-fmt"}} +{"return": {}} + +=== Resume the VM and simulate a write request === +{"execute": "cont", "arguments": {}} +{"return": {}} +{"return": ""} + +=== Commit it to the backing file === +{"execute": "block-commit", "arguments": {"auto-dismiss": false, "device": "top-fmt", "job-id": "job0", "top-node": "top-fmt"}} +{"return": {}} +{"execute": "job-complete", "arguments": {"id": "job0"}} +{"return": {}} +{"data": {"device": "job0", "len": 65536, "offset": 65536, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"data": {"device": "job0", "len": 65536, "offset": 65536, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 6f0582c79a..555c453911 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -217,7 +217,8 @@ if [ "$IMGOPTSSYNTAX" = "true" ]; then TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT" elif [ "$IMGPROTO" = "nbd" ]; then TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT - TEST_IMG="$DRIVER,file.driver=nbd,file.type=unix,file.path=$SOCKDIR/nbd" + TEST_IMG="$DRIVER,file.driver=nbd,file.type=unix" + TEST_IMG="$TEST_IMG,file.path=$SOCK_DIR/nbd" elif [ "$IMGPROTO" = "ssh" ]; then TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT TEST_IMG="$DRIVER,file.driver=ssh,file.host=127.0.0.1,file.path=$TEST_IMG_FILE" diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 6b10a6a762..cb2b789e44 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -286,3 +286,5 @@ 272 rw 273 backing quick 277 rw quick +279 rw backing quick +280 rw migration quick diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index df0708923d..8739ec6613 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -162,6 +162,11 @@ def qemu_io(*args): sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args))) return subp.communicate()[0] +def qemu_io_log(*args): + result = qemu_io(*args) + log(result, filters=[filter_testfiles, filter_qemu_io]) + return result + def qemu_io_silent(*args): '''Run qemu-io and return the exit code, suppressing stdout''' args = qemu_io_args + list(args) @@ -604,7 +609,7 @@ class VM(qtest.QEMUQtestMachine): ] error = None while True: - ev = filter_qmp_event(self.events_wait(events)) + ev = filter_qmp_event(self.events_wait(events, timeout=wait)) if ev['event'] != 'JOB_STATUS_CHANGE': if use_log: log(ev) @@ -617,6 +622,8 @@ class VM(qtest.QEMUQtestMachine): error = j['error'] if use_log: log('Job failed: %s' % (j['error'])) + elif status == 'ready': + self.qmp_log('job-complete', id=job) elif status == 'pending' and not auto_finalize: if pre_finalize: pre_finalize() @@ -636,6 +643,22 @@ class VM(qtest.QEMUQtestMachine): elif status == 'null': return error + # Returns None on success, and an error string on failure + def blockdev_create(self, options, job_id='job0', filters=None): + if filters is None: + filters = [filter_qmp_testfiles] + result = self.qmp_log('blockdev-create', filters=filters, + job_id=job_id, options=options) + + if 'return' in result: + assert result['return'] == {} + job_result = self.run_job(job_id) + else: + job_result = result['error'] + + log("") + return job_result + def enable_migration_events(self, name): log('Enabling migration QMP events on %s...' % name) log(self.qmp('migrate-set-capabilities', capabilities=[ |