diff --git a/block.c b/block.c index 38bbdf3083..f1ef4b0109 100644 --- a/block.c +++ b/block.c @@ -935,7 +935,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, bdrv_refresh_limits(bs); assert(bdrv_opt_mem_align(bs) != 0); - assert(bs->request_alignment != 0); + assert((bs->request_alignment != 0) || bs->sg); #ifndef _WIN32 if (bs->is_temporary) { @@ -1017,7 +1017,12 @@ static int bdrv_file_open(BlockDriverState *bs, const char *filename, ret = -EINVAL; goto fail; } - qdict_del(*options, "filename"); + + if (!drv->bdrv_needs_filename) { + qdict_del(*options, "filename"); + } else { + filename = qdict_get_str(*options, "filename"); + } } if (!drv->bdrv_file_open) { @@ -1229,6 +1234,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, ret = bdrv_file_open(bs, filename, &options, flags & ~BDRV_O_PROTOCOL, &local_err); if (!ret) { + drv = bs->drv; goto done; } else if (bs->drv) { goto close_and_fail; @@ -1847,11 +1853,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name), bs_src->device_name); bs_dest->device_list = bs_src->device_list; - - /* keep the same entry in graph_bdrv_states - * We do want to swap name but don't want to swap linked list entries - */ - bs_dest->node_list = bs_src->node_list; } /* @@ -1870,6 +1871,17 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) { BlockDriverState tmp; + /* The code needs to swap the node_name but simply swapping node_list won't + * work so first remove the nodes from the graph list, do the swap then + * insert them back if needed. + */ + if (bs_new->node_name[0] != '\0') { + QTAILQ_REMOVE(&graph_bdrv_states, bs_new, node_list); + } + if (bs_old->node_name[0] != '\0') { + QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list); + } + /* bs_new must be anonymous and shouldn't have anything fancy enabled */ assert(bs_new->device_name[0] == '\0'); assert(QLIST_EMPTY(&bs_new->dirty_bitmaps)); @@ -1898,6 +1910,14 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old) assert(bs_new->io_limits_enabled == false); assert(!throttle_have_timer(&bs_new->throttle_state)); + /* insert the nodes back into the graph node list if needed */ + if (bs_new->node_name[0] != '\0') { + QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_new, node_list); + } + if (bs_old->node_name[0] != '\0') { + QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_old, node_list); + } + bdrv_rebind(bs_new); bdrv_rebind(bs_old); } diff --git a/block/gluster.c b/block/gluster.c index fe7a10c30b..a44d612923 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -3,21 +3,12 @@ * * Copyright (C) 2012 Bharata B Rao * - * Pipe handling mechanism in AIO implementation is derived from - * block/rbd.c. Hence, + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. * - * Copyright (C) 2010-2011 Christian Brunner , - * Josh Durgin - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. */ #include #include "block/block_int.h" -#include "qemu/sockets.h" #include "qemu/uri.h" typedef struct GlusterAIOCB { @@ -32,9 +23,6 @@ typedef struct BDRVGlusterState { struct glfs_fd *fd; } BDRVGlusterState; -#define GLUSTER_FD_READ 0 -#define GLUSTER_FD_WRITE 1 - typedef struct GlusterConf { char *server; int port; diff --git a/block/iscsi.c b/block/iscsi.c index 0a15f53f8c..b490e98c05 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1231,12 +1231,11 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun); bs->request_alignment = iscsilun->block_size; - /* Medium changer or tape. We dont have any emulation for this so this must - * be sg ioctl compatible. We force it to be sg, otherwise qemu will try - * to read from the device to guess the image format. + /* We don't have any emulation for devices other than disks and CD-ROMs, so + * this must be sg ioctl compatible. We force it to be sg, otherwise qemu + * will try to read from the device to guess the image format. */ - if (iscsilun->type == TYPE_MEDIUM_CHANGER || - iscsilun->type == TYPE_TAPE) { + if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) { bs->sg = 1; } diff --git a/block/mirror.c b/block/mirror.c index e683959570..dd5ee056b4 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -520,9 +520,6 @@ static void mirror_complete(BlockJob *job, Error **errp) ret = bdrv_open_backing_file(s->target, NULL, &local_err); if (ret < 0) { - char backing_filename[PATH_MAX]; - bdrv_get_full_backing_filename(s->target, backing_filename, - sizeof(backing_filename)); error_propagate(errp, local_err); return; } diff --git a/block/raw-posix.c b/block/raw-posix.c index 161ea14812..e6b4c1fe02 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -336,6 +336,17 @@ error: } #endif +static void raw_parse_filename(const char *filename, QDict *options, + Error **errp) +{ + /* The filename does not have to be prefixed by the protocol name, since + * "file" is the default protocol; therefore, the return value of this + * function call can be ignored. */ + strstart(filename, "file:", &filename); + + qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename))); +} + static QemuOptsList raw_runtime_opts = { .name = "raw", .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head), @@ -1230,6 +1241,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options, int result = 0; int64_t total_size = 0; + strstart(filename, "file:", &filename); + /* Read out options */ while (options && options->name) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) { @@ -1412,6 +1425,7 @@ static BlockDriver bdrv_file = { .instance_size = sizeof(BDRVRawState), .bdrv_needs_filename = true, .bdrv_probe = NULL, /* no probe for protocols */ + .bdrv_parse_filename = raw_parse_filename, .bdrv_file_open = raw_open, .bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_commit = raw_reopen_commit, diff --git a/block/raw-win32.c b/block/raw-win32.c index ae1c8e6cca..99547488e4 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -251,6 +251,17 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped) } } +static void raw_parse_filename(const char *filename, QDict *options, + Error **errp) +{ + /* The filename does not have to be prefixed by the protocol name, since + * "file" is the default protocol; therefore, the return value of this + * function call can be ignored. */ + strstart(filename, "file:", &filename); + + qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename))); +} + static QemuOptsList raw_runtime_opts = { .name = "raw", .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head), @@ -470,6 +481,8 @@ static int raw_create(const char *filename, QEMUOptionParameter *options, int fd; int64_t total_size = 0; + strstart(filename, "file:", &filename); + /* Read out options */ while (options && options->name) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) { @@ -504,6 +517,7 @@ static BlockDriver bdrv_file = { .protocol_name = "file", .instance_size = sizeof(BDRVRawState), .bdrv_needs_filename = true, + .bdrv_parse_filename = raw_parse_filename, .bdrv_file_open = raw_open, .bdrv_close = raw_close, .bdrv_create = raw_create, diff --git a/blockdev.c b/blockdev.c index 357f7607ff..c3422a1d41 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2266,6 +2266,7 @@ void qmp_block_job_complete(const char *device, Error **errp) void qmp_blockdev_add(BlockdevOptions *options, Error **errp) { QmpOutputVisitor *ov = qmp_output_visitor_new(); + DriveInfo *dinfo; QObject *obj; QDict *qdict; Error *local_err = NULL; @@ -2282,8 +2283,10 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) * * For now, simply forbidding the combination for all drivers will do. */ if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) { - bool direct = options->cache->has_direct && options->cache->direct; - if (!options->has_cache && !direct) { + bool direct = options->has_cache && + options->cache->has_direct && + options->cache->direct; + if (!direct) { error_setg(errp, "aio=native requires cache.direct=true"); goto fail; } @@ -2301,12 +2304,18 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) qdict_flatten(qdict); - blockdev_init(NULL, qdict, &local_err); + dinfo = blockdev_init(NULL, qdict, &local_err); if (local_err) { error_propagate(errp, local_err); goto fail; } + if (bdrv_key_required(dinfo->bdrv)) { + drive_uninit(dinfo); + error_setg(errp, "blockdev-add doesn't support encrypted devices"); + goto fail; + } + fail: qmp_output_visitor_cleanup(ov); } diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index 20e412c240..9a4064f892 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -40,7 +40,7 @@ #define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \ AHCI_RX_FIS_SZ) -#define AHCI_IRQ_ON_SG (1 << 31) +#define AHCI_IRQ_ON_SG (1U << 31) #define AHCI_CMD_ATAPI (1 << 5) #define AHCI_CMD_WRITE (1 << 6) #define AHCI_CMD_PREFETCH (1 << 7) @@ -61,7 +61,7 @@ /* HOST_CTL bits */ #define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ #define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ -#define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */ +#define HOST_CTL_AHCI_EN (1U << 31) /* AHCI enabled */ /* HOST_CAP bits */ #define HOST_CAP_SSC (1 << 14) /* Slumber capable */ @@ -69,7 +69,7 @@ #define HOST_CAP_CLO (1 << 24) /* Command List Override support */ #define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ #define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ -#define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */ +#define HOST_CAP_64 (1U << 31) /* PCI DAC (64-bit DMA) support */ /* registers for each SATA port */ #define PORT_LST_ADDR 0x00 /* command list DMA addr */ @@ -89,7 +89,7 @@ #define PORT_RESERVED 0x3c /* reserved */ /* PORT_IRQ_{STAT,MASK} bits */ -#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */ +#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */ #define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ #define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ #define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ @@ -151,7 +151,7 @@ #define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */ #define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */ #define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */ -#define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */ +#define PORT_IRQ_STAT_CPDS (1U << 31) /* Code Port Detect Status */ /* ap->flags bits */ #define AHCI_FLAG_NO_NCQ (1 << 24) diff --git a/qemu-img.c b/qemu-img.c index 886db881b3..2e40cc1e69 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1162,9 +1162,6 @@ static int img_convert(int argc, char **argv) Error *local_err = NULL; QemuOpts *sn_opts = NULL; - /* Initialize before goto out */ - qemu_progress_init(progress, 1.0); - fmt = NULL; out_fmt = "raw"; cache = "unsafe"; @@ -1197,17 +1194,17 @@ static int img_convert(int argc, char **argv) error_report("option -e is deprecated, please use \'-o " "encryption\' instead!"); ret = -1; - goto out; + goto fail_getopt; case '6': error_report("option -6 is deprecated, please use \'-o " "compat6\' instead!"); ret = -1; - goto out; + goto fail_getopt; case 'o': if (!is_valid_option_list(optarg)) { error_report("Invalid option list: %s", optarg); ret = -1; - goto out; + goto fail_getopt; } if (!options) { options = g_strdup(optarg); @@ -1227,7 +1224,7 @@ static int img_convert(int argc, char **argv) error_report("Failed in parsing snapshot param '%s'", optarg); ret = -1; - goto out; + goto fail_getopt; } } else { snapshot_name = optarg; @@ -1241,7 +1238,7 @@ static int img_convert(int argc, char **argv) if (sval < 0 || *end) { error_report("Invalid minimum zero buffer size for sparse output specified"); ret = -1; - goto out; + goto fail_getopt; } min_sparse = sval / BDRV_SECTOR_SIZE; @@ -1262,9 +1259,12 @@ static int img_convert(int argc, char **argv) } } + /* Initialize before goto out */ if (quiet) { progress = 0; } + qemu_progress_init(progress, 1.0); + bs_n = argc - optind - 1; out_filename = bs_n >= 1 ? argv[argc - 1] : NULL; @@ -1667,7 +1667,6 @@ out: free_option_parameters(create_options); free_option_parameters(param); qemu_vfree(buf); - g_free(options); if (sn_opts) { qemu_opts_del(sn_opts); } @@ -1682,6 +1681,9 @@ out: } g_free(bs); } +fail_getopt: + g_free(options); + if (ret) { return 1; } diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 46345fb155..14694e176b 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -77,6 +77,15 @@ run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=on run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=1234 run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=foo +echo +echo === Unknown protocol option === +echo + +run_qemu -drive file="$TEST_IMG",format=qcow2,file.unknown_opt= +run_qemu -drive file="$TEST_IMG",format=qcow2,file.unknown_opt=on +run_qemu -drive file="$TEST_IMG",format=qcow2,file.unknown_opt=1234 +run_qemu -drive file="$TEST_IMG",format=qcow2,file.unknown_opt=foo + echo echo === Invalid format === echo diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 7de18704f8..f5e33ff395 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -17,6 +17,21 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +=== Unknown protocol option === + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt= +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=: could not open disk image TEST_DIR/t.qcow2: Block protocol 'file' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=on +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=on: could not open disk image TEST_DIR/t.qcow2: Block protocol 'file' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=1234 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=1234: could not open disk image TEST_DIR/t.qcow2: Block protocol 'file' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=foo +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=foo: could not open disk image TEST_DIR/t.qcow2: Block protocol 'file' doesn't support the option 'unknown_opt' + + === Invalid format === Testing: -drive file=TEST_DIR/t.qcow2,format=foo diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085 new file mode 100755 index 0000000000..33c8dc410a --- /dev/null +++ b/tests/qemu-iotests/085 @@ -0,0 +1,192 @@ +#!/bin/bash +# +# Live snapshot tests +# +# This tests live snapshots of images on a running QEMU instance, using +# QMP commands. Both single disk snapshots, and transactional group +# snapshots are performed. +# +# Copyright (C) 2014 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 . +# + +# creator +owner=jcody@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +status=1 # failure is the default! +qemu_pid= + +QMP_IN="${TEST_DIR}/qmp-in-$$" +QMP_OUT="${TEST_DIR}/qmp-out-$$" + +snapshot_virt0="snapshot-v0.qcow2" +snapshot_virt1="snapshot-v1.qcow2" + +MAX_SNAPSHOTS=10 + +_cleanup() +{ + kill -KILL ${qemu_pid} + wait ${qemu_pid} 2>/dev/null # silent kill + + rm -f "${QMP_IN}" "${QMP_OUT}" + for i in $(seq 1 ${MAX_SNAPSHOTS}) + do + rm -f "${TEST_DIR}/${i}-${snapshot_virt0}" + rm -f "${TEST_DIR}/${i}-${snapshot_virt1}" + done + _cleanup_test_img + +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +# Wait for expected QMP response from QEMU. Will time out +# after 10 seconds, which counts as failure. +# +# $1 is the string to expect +# +# If $silent is set to anything but an empty string, then +# response is not echoed out. +function timed_wait_for() +{ + while read -t 10 resp <&5 + do + if [ "${silent}" == "" ]; then + echo "${resp}" | _filter_testdir | _filter_qemu + fi + grep -q "${1}" < <(echo ${resp}) + if [ $? -eq 0 ]; then + return + fi + done + echo "Timeout waiting for ${1}" + exit 1 # Timeout means the test failed +} + +# Sends QMP command to QEMU, and waits for the expected response +# +# ${1}: String of the QMP command to send +# ${2}: String that the QEMU response should contain +function send_qmp_cmd() +{ + echo "${1}" >&6 + timed_wait_for "${2}" +} + +# ${1}: unique identifier for the snapshot filename +function create_single_snapshot() +{ + cmd="{ 'execute': 'blockdev-snapshot-sync', + 'arguments': { 'device': 'virtio0', + 'snapshot-file':'"${TEST_DIR}/${1}-${snapshot_virt0}"', + 'format': 'qcow2' } }" + send_qmp_cmd "${cmd}" "return" +} + +# ${1}: unique identifier for the snapshot filename +function create_group_snapshot() +{ + cmd="{ 'execute': 'transaction', 'arguments': + {'actions': [ + { 'type': 'blockdev-snapshot-sync', 'data' : + { 'device': 'virtio0', + 'snapshot-file': '"${TEST_DIR}/${1}-${snapshot_virt0}"' } }, + { 'type': 'blockdev-snapshot-sync', 'data' : + { 'device': 'virtio1', + 'snapshot-file': '"${TEST_DIR}/${1}-${snapshot_virt1}"' } } ] + } }" + + send_qmp_cmd "${cmd}" "return" +} + +size=128M + +mkfifo "${QMP_IN}" +mkfifo "${QMP_OUT}" + +_make_test_img $size +mv "${TEST_IMG}" "${TEST_IMG}.orig" +_make_test_img $size + +echo +echo === Running QEMU === +echo + +"${QEMU}" -nographic -monitor none -serial none -qmp stdio\ + -drive file="${TEST_IMG}.orig",if=virtio\ + -drive file="${TEST_IMG}",if=virtio 2>&1 >"${QMP_OUT}" <"${QMP_IN}"& +qemu_pid=$! + +# redirect fifos to file descriptors, to keep from blocking +exec 5<"${QMP_OUT}" +exec 6>"${QMP_IN}" + +# Don't print response, since it has version information in it +silent=yes timed_wait_for "capabilities" + +echo +echo === Sending capabilities === +echo + +send_qmp_cmd "{ 'execute': 'qmp_capabilities' }" "return" + +echo +echo === Create a single snapshot on virtio0 === +echo + +create_single_snapshot 1 + + +echo +echo === Invalid command - missing device and nodename === +echo + +send_qmp_cmd "{ 'execute': 'blockdev-snapshot-sync', + 'arguments': { 'snapshot-file':'"${TEST_DIR}"/1-${snapshot_virt0}', + 'format': 'qcow2' } }" "error" + +echo +echo === Invalid command - missing snapshot-file === +echo + +send_qmp_cmd "{ 'execute': 'blockdev-snapshot-sync', + 'arguments': { 'device': 'virtio0', + 'format': 'qcow2' } }" "error" +echo +echo +echo === Create several transactional group snapshots === +echo + +for i in $(seq 2 ${MAX_SNAPSHOTS}) +do + create_group_snapshot ${i} +done + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out new file mode 100644 index 0000000000..0f2b17f99e --- /dev/null +++ b/tests/qemu-iotests/085.out @@ -0,0 +1,55 @@ +QA output created by 085 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 + +=== Running QEMU === + + +=== Sending capabilities === + +{"return": {}} + +=== Create a single snapshot on virtio0 === + +Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2.orig' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} + +=== Invalid command - missing device and nodename === + +{"error": {"class": "GenericError", "desc": "Cannot find device= nor node_name="}} + +=== Invalid command - missing snapshot-file === + +{"error": {"class": "GenericError", "desc": "Parameter 'snapshot-file' is missing"}} + + +=== Create several transactional group snapshots === + +Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/1-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/2-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/2-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/3-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/3-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/4-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/4-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/5-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/5-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/6-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/6-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/7-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/7-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/8-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/8-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/9-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/9-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off +{"return": {}} +*** done diff --git a/tests/qemu-iotests/086 b/tests/qemu-iotests/086 new file mode 100755 index 0000000000..48fe85bc43 --- /dev/null +++ b/tests/qemu-iotests/086 @@ -0,0 +1,65 @@ +#!/bin/bash +# +# Test qemu-img progress output +# +# Copyright (C) 2014 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 . +# + +# creator +owner=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +function run_qemu_img() +{ + echo + echo Testing: "$@" | _filter_testdir +} + +size=128M + +_make_test_img $size +$QEMU_IO -c 'write 0 1M' $TEST_IMG | _filter_qemu_io +$QEMU_IO -c 'write 2M 1M' $TEST_IMG | _filter_qemu_io +$QEMU_IO -c 'write 4M 1M' $TEST_IMG | _filter_qemu_io +$QEMU_IO -c 'write 32M 1M' $TEST_IMG | _filter_qemu_io + +$QEMU_IMG convert -p -O $IMGFMT -f $IMGFMT "$TEST_IMG" "$TEST_IMG".base 2>&1 |\ + _filter_testdir | sed -e 's/\r/\n/g' + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/086.out b/tests/qemu-iotests/086.out new file mode 100644 index 0000000000..9c0bf23718 --- /dev/null +++ b/tests/qemu-iotests/086.out @@ -0,0 +1,18 @@ +QA output created by 086 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1048576/1048576 bytes at offset 2097152 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1048576/1048576 bytes at offset 4194304 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1048576/1048576 bytes at offset 33554432 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + (0.00/100%) + (25.00/100%) + (50.00/100%) + (75.00/100%) + (100.00/100%) + (100.00/100%) + +*** done diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087 new file mode 100755 index 0000000000..53b6c43bff --- /dev/null +++ b/tests/qemu-iotests/087 @@ -0,0 +1,122 @@ +#!/bin/bash +# +# Test unsupported blockdev-add cases +# +# Copyright (C) 2014 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 . +# + +# creator +owner=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +function do_run_qemu() +{ + echo Testing: "$@" + $QEMU -nographic -qmp stdio -serial none "$@" + echo +} + +function run_qemu() +{ + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' +} + +size=128M + +_make_test_img $size + +echo +echo === Missing ID === +echo + +run_qemu <