diff --git a/aio-posix.c b/aio-posix.c index d3ac06e238..cbd4c3438c 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -73,7 +73,7 @@ void aio_set_fd_handler(AioContext *ctx, } else { if (node == NULL) { /* Alloc and insert if it's not already there */ - node = g_malloc0(sizeof(AioHandler)); + node = g_new0(AioHandler, 1); node->pfd.fd = fd; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); diff --git a/aio-win32.c b/aio-win32.c index d81313b00b..e6f4cedf48 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -67,7 +67,7 @@ void aio_set_fd_handler(AioContext *ctx, if (node == NULL) { /* Alloc and insert if it's not already there */ - node = g_malloc0(sizeof(AioHandler)); + node = g_new0(AioHandler, 1); node->pfd.fd = fd; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); } @@ -129,7 +129,7 @@ void aio_set_event_notifier(AioContext *ctx, } else { if (node == NULL) { /* Alloc and insert if it's not already there */ - node = g_malloc0(sizeof(AioHandler)); + node = g_new0(AioHandler, 1); node->e = e; node->pfd.fd = (uintptr_t)event_notifier_get_handle(e); node->pfd.events = G_IO_IN; diff --git a/async.c b/async.c index 6e1b282aa7..3939b795e5 100644 --- a/async.c +++ b/async.c @@ -44,7 +44,7 @@ struct QEMUBH { QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) { QEMUBH *bh; - bh = g_malloc0(sizeof(QEMUBH)); + bh = g_new0(QEMUBH, 1); bh->ctx = ctx; bh->cb = cb; bh->opaque = opaque; diff --git a/block.c b/block.c index a612594db5..82f33c51b7 100644 --- a/block.c +++ b/block.c @@ -629,7 +629,7 @@ BlockDriver *bdrv_find_protocol(const char *filename, } if (!path_has_protocol(filename) || !allow_protocol_prefix) { - return bdrv_find_format("file"); + return &bdrv_file; } p = strchr(filename, ':'); @@ -648,22 +648,49 @@ BlockDriver *bdrv_find_protocol(const char *filename, return NULL; } +/* + * Guess image format by probing its contents. + * This is not a good idea when your image is raw (CVE-2008-2004), but + * we do it anyway for backward compatibility. + * + * @buf contains the image's first @buf_size bytes. + * @buf_size is the buffer size in bytes (generally BLOCK_PROBE_BUF_SIZE, + * but can be smaller if the image file is smaller) + * @filename is its filename. + * + * For all block drivers, call the bdrv_probe() method to get its + * probing score. + * Return the first block driver with the highest probing score. + */ +BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, + const char *filename) +{ + int score_max = 0, score; + BlockDriver *drv = NULL, *d; + + QLIST_FOREACH(d, &bdrv_drivers, list) { + if (d->bdrv_probe) { + score = d->bdrv_probe(buf, buf_size, filename); + if (score > score_max) { + score_max = score; + drv = d; + } + } + } + + return drv; +} + static int find_image_format(BlockDriverState *bs, const char *filename, BlockDriver **pdrv, Error **errp) { - int score, score_max; - BlockDriver *drv1, *drv; - uint8_t buf[2048]; + BlockDriver *drv; + uint8_t buf[BLOCK_PROBE_BUF_SIZE]; int ret = 0; /* Return the raw BlockDriver * to scsi-generic devices or empty drives */ if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) { - drv = bdrv_find_format("raw"); - if (!drv) { - error_setg(errp, "Could not find raw image format"); - ret = -ENOENT; - } - *pdrv = drv; + *pdrv = &bdrv_raw; return ret; } @@ -675,17 +702,7 @@ static int find_image_format(BlockDriverState *bs, const char *filename, return ret; } - score_max = 0; - drv = NULL; - QLIST_FOREACH(drv1, &bdrv_drivers, list) { - if (drv1->bdrv_probe) { - score = drv1->bdrv_probe(buf, ret, filename); - if (score > score_max) { - score_max = score; - drv = drv1; - } - } - } + drv = bdrv_probe_all(buf, ret, filename); if (!drv) { error_setg(errp, "Could not determine image format: No compatible " "driver found"); @@ -1180,7 +1197,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) { char *backing_filename = g_malloc0(PATH_MAX); int ret = 0; - BlockDriver *back_drv = NULL; BlockDriverState *backing_hd; Error *local_err = NULL; @@ -1213,14 +1229,14 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) backing_hd = bdrv_new(); - if (bs->backing_format[0] != '\0') { - back_drv = bdrv_find_format(bs->backing_format); + if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) { + qdict_put(options, "driver", qstring_from_str(bs->backing_format)); } assert(bs->backing_hd == NULL); ret = bdrv_open(&backing_hd, *backing_filename ? backing_filename : NULL, NULL, options, - bdrv_backing_flags(bs->open_flags), back_drv, &local_err); + bdrv_backing_flags(bs->open_flags), NULL, &local_err); if (ret < 0) { bdrv_unref(backing_hd); backing_hd = NULL; @@ -1294,7 +1310,6 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ char *tmp_filename = g_malloc0(PATH_MAX + 1); int64_t total_size; - BlockDriver *bdrv_qcow2; QemuOpts *opts = NULL; QDict *snapshot_options; BlockDriverState *bs_snapshot; @@ -1319,11 +1334,10 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) goto out; } - bdrv_qcow2 = bdrv_find_format("qcow2"); - opts = qemu_opts_create(bdrv_qcow2->create_opts, NULL, 0, + opts = qemu_opts_create(bdrv_qcow2.create_opts, NULL, 0, &error_abort); qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size); - ret = bdrv_create(bdrv_qcow2, tmp_filename, opts, &local_err); + ret = bdrv_create(&bdrv_qcow2, tmp_filename, opts, &local_err); qemu_opts_del(opts); if (ret < 0) { error_setg_errno(errp, -ret, "Could not create temporary overlay " @@ -1343,7 +1357,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp) bs_snapshot = bdrv_new(); ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options, - flags, bdrv_qcow2, &local_err); + flags, &bdrv_qcow2, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto out; @@ -1467,6 +1481,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename, } /* Image format probing */ + bs->probed = !drv; if (!drv && file) { ret = find_image_format(file, filename, &drv, &local_err); if (ret < 0) { @@ -3801,6 +3816,14 @@ bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base) return top != NULL; } +BlockDriverState *bdrv_next_node(BlockDriverState *bs) +{ + if (!bs) { + return QTAILQ_FIRST(&graph_bdrv_states); + } + return QTAILQ_NEXT(bs, node_list); +} + BlockDriverState *bdrv_next(BlockDriverState *bs) { if (!bs) { @@ -3809,6 +3832,11 @@ BlockDriverState *bdrv_next(BlockDriverState *bs) return QTAILQ_NEXT(bs, device_list); } +const char *bdrv_get_node_name(const BlockDriverState *bs) +{ + return bs->node_name; +} + /* TODO check what callers really want: bs->node_name or blk_name() */ const char *bdrv_get_device_name(const BlockDriverState *bs) { @@ -5541,6 +5569,18 @@ void bdrv_img_create(const char *filename, const char *fmt, return; } + if (!drv->create_opts) { + error_setg(errp, "Format driver '%s' does not support image creation", + drv->format_name); + return; + } + + if (!proto_drv->create_opts) { + error_setg(errp, "Protocol driver '%s' does not support image creation", + proto_drv->format_name); + return; + } + create_opts = qemu_opts_append(create_opts, drv->create_opts); create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); diff --git a/block/accounting.c b/block/accounting.c index edbb1cc89f..18102f015d 100644 --- a/block/accounting.c +++ b/block/accounting.c @@ -24,6 +24,7 @@ #include "block/accounting.h" #include "block/block_int.h" +#include "qemu/timer.h" void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, int64_t bytes, enum BlockAcctType type) @@ -31,7 +32,7 @@ void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, assert(type < BLOCK_MAX_IOTYPE); cookie->bytes = bytes; - cookie->start_time_ns = get_clock(); + cookie->start_time_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); cookie->type = type; } @@ -41,7 +42,8 @@ void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie) stats->nr_bytes[cookie->type] += cookie->bytes; stats->nr_ops[cookie->type]++; - stats->total_time_ns[cookie->type] += get_clock() - cookie->start_time_ns; + stats->total_time_ns[cookie->type] += + qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - cookie->start_time_ns; } diff --git a/block/blkdebug.c b/block/blkdebug.c index 862d93b59b..9ce35cd035 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -721,93 +721,50 @@ static int64_t blkdebug_getlength(BlockDriverState *bs) static void blkdebug_refresh_filename(BlockDriverState *bs) { - BDRVBlkdebugState *s = bs->opaque; - struct BlkdebugRule *rule; QDict *opts; - QList *inject_error_list = NULL, *set_state_list = NULL; - QList *suspend_list = NULL; - int event; + const QDictEntry *e; + bool force_json = false; - if (!bs->file->full_open_options) { + for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) { + if (strcmp(qdict_entry_key(e), "config") && + strcmp(qdict_entry_key(e), "x-image") && + strcmp(qdict_entry_key(e), "image") && + strncmp(qdict_entry_key(e), "image.", strlen("image."))) + { + force_json = true; + break; + } + } + + if (force_json && !bs->file->full_open_options) { /* The config file cannot be recreated, so creating a plain filename * is impossible */ return; } + if (!force_json && bs->file->exact_filename[0]) { + snprintf(bs->exact_filename, sizeof(bs->exact_filename), + "blkdebug:%s:%s", + qdict_get_try_str(bs->options, "config") ?: "", + bs->file->exact_filename); + } + opts = qdict_new(); qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("blkdebug"))); QINCREF(bs->file->full_open_options); qdict_put_obj(opts, "image", QOBJECT(bs->file->full_open_options)); - for (event = 0; event < BLKDBG_EVENT_MAX; event++) { - QLIST_FOREACH(rule, &s->rules[event], next) { - if (rule->action == ACTION_INJECT_ERROR) { - QDict *inject_error = qdict_new(); - - qdict_put_obj(inject_error, "event", QOBJECT(qstring_from_str( - BlkdebugEvent_lookup[rule->event]))); - qdict_put_obj(inject_error, "state", - QOBJECT(qint_from_int(rule->state))); - qdict_put_obj(inject_error, "errno", QOBJECT(qint_from_int( - rule->options.inject.error))); - qdict_put_obj(inject_error, "sector", QOBJECT(qint_from_int( - rule->options.inject.sector))); - qdict_put_obj(inject_error, "once", QOBJECT(qbool_from_int( - rule->options.inject.once))); - qdict_put_obj(inject_error, "immediately", - QOBJECT(qbool_from_int( - rule->options.inject.immediately))); - - if (!inject_error_list) { - inject_error_list = qlist_new(); - } - - qlist_append_obj(inject_error_list, QOBJECT(inject_error)); - } else if (rule->action == ACTION_SET_STATE) { - QDict *set_state = qdict_new(); - - qdict_put_obj(set_state, "event", QOBJECT(qstring_from_str( - BlkdebugEvent_lookup[rule->event]))); - qdict_put_obj(set_state, "state", - QOBJECT(qint_from_int(rule->state))); - qdict_put_obj(set_state, "new_state", QOBJECT(qint_from_int( - rule->options.set_state.new_state))); - - if (!set_state_list) { - set_state_list = qlist_new(); - } - - qlist_append_obj(set_state_list, QOBJECT(set_state)); - } else if (rule->action == ACTION_SUSPEND) { - QDict *suspend = qdict_new(); - - qdict_put_obj(suspend, "event", QOBJECT(qstring_from_str( - BlkdebugEvent_lookup[rule->event]))); - qdict_put_obj(suspend, "state", - QOBJECT(qint_from_int(rule->state))); - qdict_put_obj(suspend, "tag", QOBJECT(qstring_from_str( - rule->options.suspend.tag))); - - if (!suspend_list) { - suspend_list = qlist_new(); - } - - qlist_append_obj(suspend_list, QOBJECT(suspend)); - } + for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) { + if (strcmp(qdict_entry_key(e), "x-image") && + strcmp(qdict_entry_key(e), "image") && + strncmp(qdict_entry_key(e), "image.", strlen("image."))) + { + qobject_incref(qdict_entry_value(e)); + qdict_put_obj(opts, qdict_entry_key(e), qdict_entry_value(e)); } } - if (inject_error_list) { - qdict_put_obj(opts, "inject-error", QOBJECT(inject_error_list)); - } - if (set_state_list) { - qdict_put_obj(opts, "set-state", QOBJECT(set_state_list)); - } - if (suspend_list) { - qdict_put_obj(opts, "suspend", QOBJECT(suspend_list)); - } - bs->full_open_options = opts; } diff --git a/block/block-backend.c b/block/block-backend.c index d0692b18e9..ef16d7356a 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -497,6 +497,16 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, return bdrv_aio_ioctl(blk->bs, req, buf, cb, opaque); } +int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors) +{ + return bdrv_co_discard(blk->bs, sector_num, nb_sectors); +} + +int blk_co_flush(BlockBackend *blk) +{ + return bdrv_co_flush(blk->bs); +} + int blk_flush(BlockBackend *blk) { return bdrv_flush(blk->bs); @@ -549,6 +559,11 @@ void blk_set_enable_write_cache(BlockBackend *blk, bool wce) bdrv_set_enable_write_cache(blk->bs, wce); } +void blk_invalidate_cache(BlockBackend *blk, Error **errp) +{ + bdrv_invalidate_cache(blk->bs, errp); +} + int blk_is_inserted(BlockBackend *blk) { return bdrv_is_inserted(blk->bs); @@ -609,6 +624,29 @@ void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) bdrv_set_aio_context(blk->bs, new_context); } +void blk_add_aio_context_notifier(BlockBackend *blk, + void (*attached_aio_context)(AioContext *new_context, void *opaque), + void (*detach_aio_context)(void *opaque), void *opaque) +{ + bdrv_add_aio_context_notifier(blk->bs, attached_aio_context, + detach_aio_context, opaque); +} + +void blk_remove_aio_context_notifier(BlockBackend *blk, + void (*attached_aio_context)(AioContext *, + void *), + void (*detach_aio_context)(void *), + void *opaque) +{ + bdrv_remove_aio_context_notifier(blk->bs, attached_aio_context, + detach_aio_context, opaque); +} + +void blk_add_close_notifier(BlockBackend *blk, Notifier *notify) +{ + bdrv_add_close_notifier(blk->bs, notify); +} + void blk_io_plug(BlockBackend *blk) { bdrv_io_plug(blk->bs); diff --git a/block/nfs.c b/block/nfs.c index c76e368b95..ca9e24efe5 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -409,6 +409,19 @@ out: return ret; } +static QemuOptsList nfs_create_opts = { + .name = "nfs-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(nfs_create_opts.head), + .desc = { + { + .name = BLOCK_OPT_SIZE, + .type = QEMU_OPT_SIZE, + .help = "Virtual disk size" + }, + { /* end of list */ } + } +}; + static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp) { int ret = 0; @@ -470,6 +483,8 @@ static BlockDriver bdrv_nfs = { .instance_size = sizeof(NFSClient), .bdrv_needs_filename = true, + .create_opts = &nfs_create_opts, + .bdrv_has_zero_init = nfs_has_zero_init, .bdrv_get_allocated_file_size = nfs_get_allocated_file_size, .bdrv_truncate = nfs_file_truncate, diff --git a/block/qapi.c b/block/qapi.c index a87a34a8b4..fa68ba731f 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -40,6 +40,13 @@ BlockDeviceInfo *bdrv_block_device_info(BlockDriverState *bs) info->encrypted = bs->encrypted; info->encryption_key_missing = bdrv_key_required(bs); + info->cache = g_new(BlockdevCacheInfo, 1); + *info->cache = (BlockdevCacheInfo) { + .writeback = bdrv_enable_write_cache(bs), + .direct = !!(bs->open_flags & BDRV_O_NOCACHE), + .no_flush = !!(bs->open_flags & BDRV_O_NO_FLUSH), + }; + if (bs->node_name[0]) { info->has_node_name = true; info->node_name = g_strdup(bs->node_name); @@ -300,7 +307,8 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, qapi_free_BlockInfo(info); } -static BlockStats *bdrv_query_stats(const BlockDriverState *bs) +static BlockStats *bdrv_query_stats(const BlockDriverState *bs, + bool query_backing) { BlockStats *s; @@ -311,6 +319,11 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs) s->device = g_strdup(bdrv_get_device_name(bs)); } + if (bdrv_get_node_name(bs)[0]) { + s->has_node_name = true; + s->node_name = g_strdup(bdrv_get_node_name(bs)); + } + s->stats = g_malloc0(sizeof(*s->stats)); s->stats->rd_bytes = bs->stats.nr_bytes[BLOCK_ACCT_READ]; s->stats->wr_bytes = bs->stats.nr_bytes[BLOCK_ACCT_WRITE]; @@ -325,12 +338,12 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs) if (bs->file) { s->has_parent = true; - s->parent = bdrv_query_stats(bs->file); + s->parent = bdrv_query_stats(bs->file, query_backing); } - if (bs->backing_hd) { + if (query_backing && bs->backing_hd) { s->has_backing = true; - s->backing = bdrv_query_stats(bs->backing_hd); + s->backing = bdrv_query_stats(bs->backing_hd, query_backing); } return s; @@ -361,17 +374,22 @@ BlockInfoList *qmp_query_block(Error **errp) return NULL; } -BlockStatsList *qmp_query_blockstats(Error **errp) +BlockStatsList *qmp_query_blockstats(bool has_query_nodes, + bool query_nodes, + Error **errp) { BlockStatsList *head = NULL, **p_next = &head; BlockDriverState *bs = NULL; - while ((bs = bdrv_next(bs))) { + /* Just to be safe if query_nodes is not always initialized */ + query_nodes = has_query_nodes && query_nodes; + + while ((bs = query_nodes ? bdrv_next_node(bs) : bdrv_next(bs))) { BlockStatsList *info = g_malloc0(sizeof(*info)); AioContext *ctx = bdrv_get_aio_context(bs); aio_context_acquire(ctx); - info->value = bdrv_query_stats(bs); + info->value = bdrv_query_stats(bs, !query_nodes); aio_context_release(ctx); *p_next = info; diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index df0b2c9cec..1fea5142d0 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1263,7 +1263,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, again: start = offset; - remaining = *num << BDRV_SECTOR_BITS; + remaining = (uint64_t)*num << BDRV_SECTOR_BITS; cluster_offset = 0; *host_offset = 0; cur_bytes = 0; diff --git a/block/qcow2.c b/block/qcow2.c index d12049451a..e4e690a42b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -117,7 +117,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, #ifdef DEBUG_EXT printf("ext.magic = 0x%x\n", ext.magic); #endif - if (ext.len > end_offset - offset) { + if (offset > end_offset || ext.len > end_offset - offset) { error_setg(errp, "Header extension too large"); return -EINVAL; } @@ -1428,10 +1428,23 @@ static void qcow2_close(BlockDriverState *bs) s->l1_table = NULL; if (!(bs->open_flags & BDRV_O_INCOMING)) { - qcow2_cache_flush(bs, s->l2_table_cache); - qcow2_cache_flush(bs, s->refcount_block_cache); + int ret1, ret2; - qcow2_mark_clean(bs); + ret1 = qcow2_cache_flush(bs, s->l2_table_cache); + ret2 = qcow2_cache_flush(bs, s->refcount_block_cache); + + if (ret1) { + error_report("Failed to flush the L2 table cache: %s", + strerror(-ret1)); + } + if (ret2) { + error_report("Failed to flush the refcount block cache: %s", + strerror(-ret2)); + } + + if (!ret1 && !ret2) { + qcow2_mark_clean(bs); + } } qcow2_cache_destroy(bs, s->l2_table_cache); @@ -1915,10 +1928,9 @@ static int qcow2_create2(const char *filename, int64_t total_size, * refcount of the cluster that is occupied by the header and the refcount * table) */ - BlockDriver* drv = bdrv_find_format("qcow2"); - assert(drv != NULL); ret = bdrv_open(&bs, filename, NULL, NULL, - BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, &local_err); + BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, + &bdrv_qcow2, &local_err); if (ret < 0) { error_propagate(errp, local_err); goto out; @@ -1970,7 +1982,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */ ret = bdrv_open(&bs, filename, NULL, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING, - drv, &local_err); + &bdrv_qcow2, &local_err); if (local_err) { error_propagate(errp, local_err); goto out; @@ -2150,8 +2162,7 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num, /* align end of file to a sector boundary to ease reading with sector based I/Os */ cluster_offset = bdrv_getlength(bs->file); - bdrv_truncate(bs->file, cluster_offset); - return 0; + return bdrv_truncate(bs->file, cluster_offset); } if (nb_sectors != s->cluster_sectors) { @@ -2847,7 +2858,7 @@ static QemuOptsList qcow2_create_opts = { } }; -static BlockDriver bdrv_qcow2 = { +BlockDriver bdrv_qcow2 = { .format_name = "qcow2", .instance_size = sizeof(BDRVQcowState), .bdrv_probe = qcow2_probe, diff --git a/block/raw-posix.c b/block/raw-posix.c index b1af77e47f..e51293a455 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -446,6 +446,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } if (fstat(s->fd, &st) < 0) { + ret = -errno; error_setg_errno(errp, errno, "Could not stat file"); goto fail; } @@ -1684,7 +1685,7 @@ static QemuOptsList raw_create_opts = { } }; -static BlockDriver bdrv_file = { +BlockDriver bdrv_file = { .format_name = "file", .protocol_name = "file", .instance_size = sizeof(BDRVRawState), @@ -1922,7 +1923,7 @@ static int fd_open(BlockDriverState *bs) return 0; last_media_present = (s->fd >= 0); if (s->fd >= 0 && - (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) { + (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->fd_open_time) >= FD_OPEN_TIMEOUT) { qemu_close(s->fd); s->fd = -1; #ifdef DEBUG_FLOPPY @@ -1931,7 +1932,7 @@ static int fd_open(BlockDriverState *bs) } if (s->fd < 0) { if (s->fd_got_error && - (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) { + (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->fd_error_time) < FD_OPEN_TIMEOUT) { #ifdef DEBUG_FLOPPY printf("No floppy (open delayed)\n"); #endif @@ -1939,7 +1940,7 @@ static int fd_open(BlockDriverState *bs) } s->fd = qemu_open(bs->filename, s->open_flags & ~O_NONBLOCK); if (s->fd < 0) { - s->fd_error_time = get_clock(); + s->fd_error_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); s->fd_got_error = 1; if (last_media_present) s->fd_media_changed = 1; @@ -1954,7 +1955,7 @@ static int fd_open(BlockDriverState *bs) } if (!last_media_present) s->fd_media_changed = 1; - s->fd_open_time = get_clock(); + s->fd_open_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); s->fd_got_error = 0; return 0; } diff --git a/block/raw-win32.c b/block/raw-win32.c index 7b588815b9..06243d76df 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -540,7 +540,7 @@ static QemuOptsList raw_create_opts = { } }; -static BlockDriver bdrv_file = { +BlockDriver bdrv_file = { .format_name = "file", .protocol_name = "file", .instance_size = sizeof(BDRVRawState), diff --git a/block/raw_bsd.c b/block/raw_bsd.c index 401b967e85..05b02c76d4 100644 --- a/block/raw_bsd.c +++ b/block/raw_bsd.c @@ -58,8 +58,58 @@ static int coroutine_fn raw_co_readv(BlockDriverState *bs, int64_t sector_num, static int coroutine_fn raw_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov) { + void *buf = NULL; + BlockDriver *drv; + QEMUIOVector local_qiov; + int ret; + + if (bs->probed && sector_num == 0) { + /* As long as these conditions are true, we can't get partial writes to + * the probe buffer and can just directly check the request. */ + QEMU_BUILD_BUG_ON(BLOCK_PROBE_BUF_SIZE != 512); + QEMU_BUILD_BUG_ON(BDRV_SECTOR_SIZE != 512); + + if (nb_sectors == 0) { + /* qemu_iovec_to_buf() would fail, but we want to return success + * instead of -EINVAL in this case. */ + return 0; + } + + buf = qemu_try_blockalign(bs->file, 512); + if (!buf) { + ret = -ENOMEM; + goto fail; + } + + ret = qemu_iovec_to_buf(qiov, 0, buf, 512); + if (ret != 512) { + ret = -EINVAL; + goto fail; + } + + drv = bdrv_probe_all(buf, 512, NULL); + if (drv != bs->drv) { + ret = -EPERM; + goto fail; + } + + /* Use the checked buffer, a malicious guest might be overwriting its + * original buffer in the background. */ + qemu_iovec_init(&local_qiov, qiov->niov + 1); + qemu_iovec_add(&local_qiov, buf, 512); + qemu_iovec_concat(&local_qiov, qiov, 512, qiov->size - 512); + qiov = &local_qiov; + } + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); - return bdrv_co_writev(bs->file, sector_num, nb_sectors, qiov); + ret = bdrv_co_writev(bs->file, sector_num, nb_sectors, qiov); + +fail: + if (qiov == &local_qiov) { + qemu_iovec_destroy(&local_qiov); + } + qemu_vfree(buf); + return ret; } static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, @@ -158,6 +208,18 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { bs->sg = bs->file->sg; + + if (bs->probed && !bdrv_is_read_only(bs)) { + fprintf(stderr, + "WARNING: Image format was not specified for '%s' and probing " + "guessed raw.\n" + " Automatically detecting the format is dangerous for " + "raw images, write operations on block 0 will be restricted.\n" + " Specify the 'raw' format explicitly to remove the " + "restrictions.\n", + bs->file->filename); + } + return 0; } @@ -173,7 +235,7 @@ static int raw_probe(const uint8_t *buf, int buf_size, const char *filename) return 1; } -static BlockDriver bdrv_raw = { +BlockDriver bdrv_raw = { .format_name = "raw", .bdrv_probe = &raw_probe, .bdrv_reopen_prepare = &raw_reopen_prepare, diff --git a/block/vdi.c b/block/vdi.c index 39070b75e8..74030c6e30 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -852,11 +852,6 @@ static QemuOptsList vdi_create_opts = { .def_value_str = "off" }, #endif - { - .name = BLOCK_OPT_NOCOW, - .type = QEMU_OPT_BOOL, - .help = "Turn off copy-on-write (valid only on btrfs)" - }, /* TODO: An additional option to set UUID values might be useful. */ { /* end of list */ } } diff --git a/block/vmdk.c b/block/vmdk.c index 2cbfd3e72e..65af414f3c 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -28,6 +28,7 @@ #include "qemu/module.h" #include "migration/migration.h" #include +#include #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V') @@ -556,8 +557,16 @@ static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset, return NULL; } - size = MIN(size, 1 << 20); /* avoid unbounded allocation */ - buf = g_malloc0(size + 1); + if (size < 4) { + /* Both descriptor file and sparse image must be much larger than 4 + * bytes, also callers of vmdk_read_desc want to compare the first 4 + * bytes with VMDK4_MAGIC, let's error out if less is read. */ + error_setg(errp, "File is too small, not a valid image"); + return NULL; + } + + size = MIN(size, (1 << 20) - 1); /* avoid unbounded allocation */ + buf = g_malloc(size + 1); ret = bdrv_pread(file, desc_offset, buf, size); if (ret < 0) { @@ -565,6 +574,7 @@ static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset, g_free(buf); return NULL; } + buf[ret] = 0; return buf; } @@ -635,6 +645,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, bs->file->total_sectors * 512 - 1536, &footer, sizeof(footer)); if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to read footer"); return ret; } @@ -646,6 +657,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, le32_to_cpu(footer.eos_marker.size) != 0 || le32_to_cpu(footer.eos_marker.type) != MARKER_END_OF_STREAM) { + error_setg(errp, "Invalid footer"); return -EINVAL; } @@ -676,6 +688,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gt) * le64_to_cpu(header.granularity); if (l1_entry_sectors == 0) { + error_setg(errp, "L1 entry size is invalid"); return -EINVAL; } l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) @@ -784,10 +797,12 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, VmdkExtent *extent; while (*p) { - /* parse extent line: + /* parse extent line in one of below formats: + * * RW [size in sectors] FLAT "file-name.vmdk" OFFSET - * or * RW [size in sectors] SPARSE "file-name.vmdk" + * RW [size in sectors] VMFS "file-name.vmdk" + * RW [size in sectors] VMFSSPARSE "file-name.vmdk" */ flat_offset = -1; ret = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64, @@ -902,7 +917,7 @@ exit: static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { - char *buf = NULL; + char *buf; int ret; BDRVVmdkState *s = bs->opaque; uint32_t magic; @@ -1538,7 +1553,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, /* update CID on the first write every time the virtual disk is * opened */ if (!s->cid_updated) { - ret = vmdk_write_cid(bs, time(NULL)); + ret = vmdk_write_cid(bs, g_random_int()); if (ret < 0) { return ret; } @@ -1922,7 +1937,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) } /* generate descriptor file */ desc = g_strdup_printf(desc_template, - (uint32_t)time(NULL), + g_random_int(), parent_cid, fmt, parent_desc_line, diff --git a/block/vpc.c b/block/vpc.c index 38c4f02fff..46803b14be 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -893,11 +893,6 @@ static QemuOptsList vpc_create_opts = { "Type of virtual hard disk format. Supported formats are " "{dynamic (default) | fixed} " }, - { - .name = BLOCK_OPT_NOCOW, - .type = QEMU_OPT_BOOL, - .help = "Turn off copy-on-write (valid only on btrfs)" - }, { /* end of list */ } } }; diff --git a/block/vvfat.c b/block/vvfat.c index cefe3a4f79..e34a789699 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -2917,6 +2917,12 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp) } bdrv_qcow = bdrv_find_format("qcow"); + if (!bdrv_qcow) { + error_setg(errp, "Failed to locate qcow driver"); + ret = -ENOENT; + goto err; + } + opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort); qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512); qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:"); diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 06f901ef6f..22e95d17ee 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -10,6 +10,7 @@ */ #include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" #include "hw/block/block.h" #include "monitor/monitor.h" #include "qapi/qmp/qerror.h" @@ -73,7 +74,7 @@ static void nbd_close_notifier(Notifier *n, void *data) void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, Error **errp) { - BlockDriverState *bs; + BlockBackend *blk; NBDExport *exp; NBDCloseNotifier *n; @@ -87,12 +88,12 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, return; } - bs = bdrv_find(device); - if (!bs) { + blk = blk_by_name(device); + if (!blk) { error_set(errp, QERR_DEVICE_NOT_FOUND, device); return; } - if (!bdrv_is_inserted(bs)) { + if (!blk_is_inserted(blk)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); return; } @@ -100,18 +101,18 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, if (!has_writable) { writable = false; } - if (bdrv_is_read_only(bs)) { + if (blk_is_read_only(blk)) { writable = false; } - exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL); + exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL); nbd_export_set_name(exp, device); n = g_new0(NBDCloseNotifier, 1); n->n.notify = nbd_close_notifier; n->exp = exp; - bdrv_add_close_notifier(bs, &n->n); + blk_add_close_notifier(blk, &n->n); QTAILQ_INSERT_TAIL(&close_notifiers, n, next); } diff --git a/blockdev.c b/blockdev.c index 57910b82c7..5651a8e140 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1105,6 +1105,7 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, Error **errp) { BlockDriverState *bs = bdrv_find(device); + AioContext *aio_context; QEMUSnapshotInfo sn; Error *local_err = NULL; SnapshotInfo *info = NULL; @@ -1128,25 +1129,34 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, return NULL; } + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, errp)) { + goto out_aio_context; + } + ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err); if (local_err) { error_propagate(errp, local_err); - return NULL; + goto out_aio_context; } if (!ret) { error_setg(errp, "Snapshot with id '%s' and name '%s' does not exist on " "device '%s'", STR_OR_NULL(id), STR_OR_NULL(name), device); - return NULL; + goto out_aio_context; } bdrv_snapshot_delete(bs, id, name, &local_err); if (local_err) { error_propagate(errp, local_err); - return NULL; + goto out_aio_context; } + aio_context_release(aio_context); + info = g_new0(SnapshotInfo, 1); info->id = g_strdup(sn.id_str); info->name = g_strdup(sn.name); @@ -1157,9 +1167,13 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, info->vm_clock_sec = sn.vm_clock_nsec / 1000000000; return info; + +out_aio_context: + aio_context_release(aio_context); + return NULL; } -/* New and old BlockDriverState structs for group snapshots */ +/* New and old BlockDriverState structs for atomic group operations */ typedef struct BlkTransactionState BlkTransactionState; @@ -1193,6 +1207,7 @@ struct BlkTransactionState { typedef struct InternalSnapshotState { BlkTransactionState common; BlockDriverState *bs; + AioContext *aio_context; QEMUSnapshotInfo sn; } InternalSnapshotState; @@ -1226,11 +1241,19 @@ static void internal_snapshot_prepare(BlkTransactionState *common, return; } + /* AioContext is released in .clean() */ + state->aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(state->aio_context); + if (!bdrv_is_inserted(bs)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); return; } + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, errp)) { + return; + } + if (bdrv_is_read_only(bs)) { error_set(errp, QERR_DEVICE_IS_READ_ONLY, device); return; @@ -1303,11 +1326,22 @@ static void internal_snapshot_abort(BlkTransactionState *common) } } +static void internal_snapshot_clean(BlkTransactionState *common) +{ + InternalSnapshotState *state = DO_UPCAST(InternalSnapshotState, + common, common); + + if (state->aio_context) { + aio_context_release(state->aio_context); + } +} + /* external snapshot private data */ typedef struct ExternalSnapshotState { BlkTransactionState common; BlockDriverState *old_bs; BlockDriverState *new_bs; + AioContext *aio_context; } ExternalSnapshotState; static void external_snapshot_prepare(BlkTransactionState *common, @@ -1374,6 +1408,10 @@ static void external_snapshot_prepare(BlkTransactionState *common, return; } + /* Acquire AioContext now so any threads operating on old_bs stop */ + state->aio_context = bdrv_get_aio_context(state->old_bs); + aio_context_acquire(state->aio_context); + if (!bdrv_is_inserted(state->old_bs)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); return; @@ -1432,6 +1470,8 @@ static void external_snapshot_commit(BlkTransactionState *common) ExternalSnapshotState *state = DO_UPCAST(ExternalSnapshotState, common, common); + bdrv_set_aio_context(state->new_bs, state->aio_context); + /* This removes our old bs and adds the new bs */ bdrv_append(state->new_bs, state->old_bs); /* We don't need (or want) to use the transactional @@ -1439,6 +1479,8 @@ static void external_snapshot_commit(BlkTransactionState *common) * don't want to abort all of them if one of them fails the reopen */ bdrv_reopen(state->new_bs, state->new_bs->open_flags & ~BDRV_O_RDWR, NULL); + + aio_context_release(state->aio_context); } static void external_snapshot_abort(BlkTransactionState *common) @@ -1448,23 +1490,38 @@ static void external_snapshot_abort(BlkTransactionState *common) if (state->new_bs) { bdrv_unref(state->new_bs); } + if (state->aio_context) { + aio_context_release(state->aio_context); + } } typedef struct DriveBackupState { BlkTransactionState common; BlockDriverState *bs; + AioContext *aio_context; BlockJob *job; } DriveBackupState; static void drive_backup_prepare(BlkTransactionState *common, Error **errp) { DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); + BlockDriverState *bs; DriveBackup *backup; Error *local_err = NULL; assert(common->action->kind == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); backup = common->action->drive_backup; + bs = bdrv_find(backup->device); + if (!bs) { + error_set(errp, QERR_DEVICE_NOT_FOUND, backup->device); + return; + } + + /* AioContext is released in .clean() */ + state->aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(state->aio_context); + qmp_drive_backup(backup->device, backup->target, backup->has_format, backup->format, backup->sync, @@ -1475,12 +1532,10 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp) &local_err); if (local_err) { error_propagate(errp, local_err); - state->bs = NULL; - state->job = NULL; return; } - state->bs = bdrv_find(backup->device); + state->bs = bs; state->job = state->bs->job; } @@ -1495,6 +1550,15 @@ static void drive_backup_abort(BlkTransactionState *common) } } +static void drive_backup_clean(BlkTransactionState *common) +{ + DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); + + if (state->aio_context) { + aio_context_release(state->aio_context); + } +} + static void abort_prepare(BlkTransactionState *common, Error **errp) { error_setg(errp, "Transaction aborted using Abort action"); @@ -1516,6 +1580,7 @@ static const BdrvActionOps actions[] = { .instance_size = sizeof(DriveBackupState), .prepare = drive_backup_prepare, .abort = drive_backup_abort, + .clean = drive_backup_clean, }, [TRANSACTION_ACTION_KIND_ABORT] = { .instance_size = sizeof(BlkTransactionState), @@ -1526,13 +1591,13 @@ static const BdrvActionOps actions[] = { .instance_size = sizeof(InternalSnapshotState), .prepare = internal_snapshot_prepare, .abort = internal_snapshot_abort, + .clean = internal_snapshot_clean, }, }; /* - * 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail - * then we do not pivot any of the devices in the group, and abandon the - * snapshots + * 'Atomic' group operations. The operations are performed as a set, and if + * any fail then we roll back all operations in the group. */ void qmp_transaction(TransactionActionList *dev_list, Error **errp) { @@ -1543,10 +1608,10 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp) QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionState) snap_bdrv_states; QSIMPLEQ_INIT(&snap_bdrv_states); - /* drain all i/o before any snapshots */ + /* drain all i/o before any operations */ bdrv_drain_all(); - /* We don't do anything in this loop that commits us to the snapshot */ + /* We don't do anything in this loop that commits us to the operations */ while (NULL != dev_entry) { TransactionAction *dev_info = NULL; const BdrvActionOps *ops; @@ -1581,10 +1646,7 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp) goto exit; delete_and_fail: - /* - * failure, and it is all-or-none; abandon each new bs, and keep using - * the original bs for all images - */ + /* failure, and it is all-or-none; roll back all operations */ QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) { if (state->ops->abort) { state->ops->abort(state); @@ -1603,14 +1665,18 @@ exit: static void eject_device(BlockBackend *blk, int force, Error **errp) { BlockDriverState *bs = blk_bs(blk); + AioContext *aio_context; + + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) { - return; + goto out; } if (!blk_dev_has_removable_media(blk)) { error_setg(errp, "Device '%s' is not removable", bdrv_get_device_name(bs)); - return; + goto out; } if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) { @@ -1618,11 +1684,14 @@ static void eject_device(BlockBackend *blk, int force, Error **errp) if (!force) { error_setg(errp, "Device '%s' is locked", bdrv_get_device_name(bs)); - return; + goto out; } } bdrv_close(bs); + +out: + aio_context_release(aio_context); } void qmp_eject(const char *device, bool has_force, bool force, Error **errp) @@ -1644,6 +1713,7 @@ void qmp_block_passwd(bool has_device, const char *device, { Error *local_err = NULL; BlockDriverState *bs; + AioContext *aio_context; int err; bs = bdrv_lookup_bs(has_device ? device : NULL, @@ -1654,16 +1724,23 @@ void qmp_block_passwd(bool has_device, const char *device, return; } + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + err = bdrv_set_key(bs, password); if (err == -EINVAL) { error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); - return; + goto out; } else if (err < 0) { error_set(errp, QERR_INVALID_PASSWORD); - return; + goto out; } + +out: + aio_context_release(aio_context); } +/* Assumes AioContext is held */ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename, int bdrv_flags, BlockDriver *drv, const char *password, Error **errp) @@ -1696,6 +1773,7 @@ void qmp_change_blockdev(const char *device, const char *filename, { BlockBackend *blk; BlockDriverState *bs; + AioContext *aio_context; BlockDriver *drv = NULL; int bdrv_flags; Error *err = NULL; @@ -1707,24 +1785,30 @@ void qmp_change_blockdev(const char *device, const char *filename, } bs = blk_bs(blk); + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + if (format) { drv = bdrv_find_whitelisted_format(format, bs->read_only); if (!drv) { error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - return; + goto out; } } eject_device(blk, 0, &err); if (err) { error_propagate(errp, err); - return; + goto out; } bdrv_flags = bdrv_is_read_only(bs) ? 0 : BDRV_O_RDWR; bdrv_flags |= bdrv_is_snapshot(bs) ? BDRV_O_SNAPSHOT : 0; qmp_bdrv_open_encrypted(bs, filename, bdrv_flags, drv, NULL, errp); + +out: + aio_context_release(aio_context); } /* throttling disk I/O limits */ @@ -2548,6 +2632,7 @@ void qmp_change_backing_file(const char *device, Error **errp) { BlockDriverState *bs = NULL; + AioContext *aio_context; BlockDriverState *image_bs = NULL; Error *local_err = NULL; bool ro; @@ -2561,34 +2646,37 @@ void qmp_change_backing_file(const char *device, return; } + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err); if (local_err) { error_propagate(errp, local_err); - return; + goto out; } if (!image_bs) { error_setg(errp, "image file not found"); - return; + goto out; } if (bdrv_find_base(image_bs) == image_bs) { error_setg(errp, "not allowing backing file change on an image " "without a backing file"); - return; + goto out; } /* even though we are not necessarily operating on bs, we need it to * determine if block ops are currently prohibited on the chain */ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) { - return; + goto out; } /* final sanity check */ if (!bdrv_chain_contains(bs, image_bs)) { error_setg(errp, "'%s' and image file are not in the same chain", device); - return; + goto out; } /* if not r/w, reopen to make r/w */ @@ -2599,7 +2687,7 @@ void qmp_change_backing_file(const char *device, bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err); if (local_err) { error_propagate(errp, local_err); - return; + goto out; } } @@ -2619,6 +2707,9 @@ void qmp_change_backing_file(const char *device, error_propagate(errp, local_err); /* will preserve prior errp */ } } + +out: + aio_context_release(aio_context); } void qmp_blockdev_add(BlockdevOptions *options, Error **errp) diff --git a/hmp.c b/hmp.c index 63d76868b9..481be8019b 100644 --- a/hmp.c +++ b/hmp.c @@ -290,14 +290,131 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict) qapi_free_CpuInfoList(cpu_list); } +static void print_block_info(Monitor *mon, BlockInfo *info, + BlockDeviceInfo *inserted, bool verbose) +{ + ImageInfo *image_info; + + assert(!info || !info->has_inserted || info->inserted == inserted); + + if (info) { + monitor_printf(mon, "%s", info->device); + if (inserted && inserted->has_node_name) { + monitor_printf(mon, " (%s)", inserted->node_name); + } + } else { + assert(inserted); + monitor_printf(mon, "%s", + inserted->has_node_name + ? inserted->node_name + : ""); + } + + if (inserted) { + monitor_printf(mon, ": %s (%s%s%s)\n", + inserted->file, + inserted->drv, + inserted->ro ? ", read-only" : "", + inserted->encrypted ? ", encrypted" : ""); + } else { + monitor_printf(mon, ": [not inserted]\n"); + } + + if (info) { + if (info->has_io_status && info->io_status != BLOCK_DEVICE_IO_STATUS_OK) { + monitor_printf(mon, " I/O status: %s\n", + BlockDeviceIoStatus_lookup[info->io_status]); + } + + if (info->removable) { + monitor_printf(mon, " Removable device: %slocked, tray %s\n", + info->locked ? "" : "not ", + info->tray_open ? "open" : "closed"); + } + } + + + if (!inserted) { + return; + } + + monitor_printf(mon, " Cache mode: %s%s%s\n", + inserted->cache->writeback ? "writeback" : "writethrough", + inserted->cache->direct ? ", direct" : "", + inserted->cache->no_flush ? ", ignore flushes" : ""); + + if (inserted->has_backing_file) { + monitor_printf(mon, + " Backing file: %s " + "(chain depth: %" PRId64 ")\n", + inserted->backing_file, + inserted->backing_file_depth); + } + + if (inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) { + monitor_printf(mon, " Detect zeroes: %s\n", + BlockdevDetectZeroesOptions_lookup[inserted->detect_zeroes]); + } + + if (inserted->bps || inserted->bps_rd || inserted->bps_wr || + inserted->iops || inserted->iops_rd || inserted->iops_wr) + { + monitor_printf(mon, " I/O throttling: bps=%" PRId64 + " bps_rd=%" PRId64 " bps_wr=%" PRId64 + " bps_max=%" PRId64 + " bps_rd_max=%" PRId64 + " bps_wr_max=%" PRId64 + " iops=%" PRId64 " iops_rd=%" PRId64 + " iops_wr=%" PRId64 + " iops_max=%" PRId64 + " iops_rd_max=%" PRId64 + " iops_wr_max=%" PRId64 + " iops_size=%" PRId64 "\n", + inserted->bps, + inserted->bps_rd, + inserted->bps_wr, + inserted->bps_max, + inserted->bps_rd_max, + inserted->bps_wr_max, + inserted->iops, + inserted->iops_rd, + inserted->iops_wr, + inserted->iops_max, + inserted->iops_rd_max, + inserted->iops_wr_max, + inserted->iops_size); + } + + if (verbose) { + monitor_printf(mon, "\nImages:\n"); + image_info = inserted->image; + while (1) { + bdrv_image_info_dump((fprintf_function)monitor_printf, + mon, image_info); + if (image_info->has_backing_image) { + image_info = image_info->backing_image; + } else { + break; + } + } + } +} + void hmp_info_block(Monitor *mon, const QDict *qdict) { BlockInfoList *block_list, *info; - ImageInfo *image_info; + BlockDeviceInfoList *blockdev_list, *blockdev; const char *device = qdict_get_try_str(qdict, "device"); bool verbose = qdict_get_try_bool(qdict, "verbose", 0); + bool nodes = qdict_get_try_bool(qdict, "nodes", 0); + bool printed = false; - block_list = qmp_query_block(NULL); + /* Print BlockBackend information */ + if (!nodes) { + block_list = qmp_query_block(false); + } else { + block_list = NULL; + } for (info = block_list; info; info = info->next) { if (device && strcmp(device, info->value->device)) { @@ -308,102 +425,40 @@ void hmp_info_block(Monitor *mon, const QDict *qdict) monitor_printf(mon, "\n"); } - monitor_printf(mon, "%s", info->value->device); - if (info->value->has_inserted) { - monitor_printf(mon, ": %s (%s%s%s)\n", - info->value->inserted->file, - info->value->inserted->drv, - info->value->inserted->ro ? ", read-only" : "", - info->value->inserted->encrypted ? ", encrypted" : ""); - } else { - monitor_printf(mon, ": [not inserted]\n"); - } - - if (info->value->has_io_status && info->value->io_status != BLOCK_DEVICE_IO_STATUS_OK) { - monitor_printf(mon, " I/O status: %s\n", - BlockDeviceIoStatus_lookup[info->value->io_status]); - } - - if (info->value->removable) { - monitor_printf(mon, " Removable device: %slocked, tray %s\n", - info->value->locked ? "" : "not ", - info->value->tray_open ? "open" : "closed"); - } - - - if (!info->value->has_inserted) { - continue; - } - - if (info->value->inserted->has_backing_file) { - monitor_printf(mon, - " Backing file: %s " - "(chain depth: %" PRId64 ")\n", - info->value->inserted->backing_file, - info->value->inserted->backing_file_depth); - } - - if (info->value->inserted->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF) { - monitor_printf(mon, " Detect zeroes: %s\n", - BlockdevDetectZeroesOptions_lookup[info->value->inserted->detect_zeroes]); - } - - if (info->value->inserted->bps - || info->value->inserted->bps_rd - || info->value->inserted->bps_wr - || info->value->inserted->iops - || info->value->inserted->iops_rd - || info->value->inserted->iops_wr) - { - monitor_printf(mon, " I/O throttling: bps=%" PRId64 - " bps_rd=%" PRId64 " bps_wr=%" PRId64 - " bps_max=%" PRId64 - " bps_rd_max=%" PRId64 - " bps_wr_max=%" PRId64 - " iops=%" PRId64 " iops_rd=%" PRId64 - " iops_wr=%" PRId64 - " iops_max=%" PRId64 - " iops_rd_max=%" PRId64 - " iops_wr_max=%" PRId64 - " iops_size=%" PRId64 "\n", - info->value->inserted->bps, - info->value->inserted->bps_rd, - info->value->inserted->bps_wr, - info->value->inserted->bps_max, - info->value->inserted->bps_rd_max, - info->value->inserted->bps_wr_max, - info->value->inserted->iops, - info->value->inserted->iops_rd, - info->value->inserted->iops_wr, - info->value->inserted->iops_max, - info->value->inserted->iops_rd_max, - info->value->inserted->iops_wr_max, - info->value->inserted->iops_size); - } - - if (verbose) { - monitor_printf(mon, "\nImages:\n"); - image_info = info->value->inserted->image; - while (1) { - bdrv_image_info_dump((fprintf_function)monitor_printf, - mon, image_info); - if (image_info->has_backing_image) { - image_info = image_info->backing_image; - } else { - break; - } - } - } + print_block_info(mon, info->value, info->value->has_inserted + ? info->value->inserted : NULL, + verbose); + printed = true; } qapi_free_BlockInfoList(block_list); + + if ((!device && !nodes) || printed) { + return; + } + + /* Print node information */ + blockdev_list = qmp_query_named_block_nodes(NULL); + for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) { + assert(blockdev->value->has_node_name); + if (device && strcmp(device, blockdev->value->node_name)) { + continue; + } + + if (blockdev != blockdev_list) { + monitor_printf(mon, "\n"); + } + + print_block_info(mon, NULL, blockdev->value, verbose); + } + qapi_free_BlockDeviceInfoList(blockdev_list); } void hmp_info_blockstats(Monitor *mon, const QDict *qdict) { BlockStatsList *stats_list, *stats; - stats_list = qmp_query_blockstats(NULL); + stats_list = qmp_query_blockstats(false, false, NULL); for (stats = stats_list; stats; stats = stats->next) { if (!stats->value->has_device) { diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 1222a37f4f..2a28978cba 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -197,7 +197,13 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, s->blocker); + blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, + s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_MIRROR, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker); diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 13276589e4..aa1ed986d2 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -811,6 +811,7 @@ static int nvme_init(PCIDevice *pci_dev) NVME_CAP_SET_AMS(n->bar.cap, 1); NVME_CAP_SET_TO(n->bar.cap, 0xf); NVME_CAP_SET_CSS(n->bar.cap, 1); + NVME_CAP_SET_MPSMAX(n->bar.cap, 4); n->bar.vs = 0x00010001; n->bar.intmc = n->bar.intms = 0; diff --git a/hw/block/nvme.h b/hw/block/nvme.h index 993c51131c..b6ccb655a6 100644 --- a/hw/block/nvme.h +++ b/hw/block/nvme.h @@ -688,7 +688,7 @@ typedef struct NvmeCtrl { NvmeBar bar; BlockConf conf; - uint16_t page_size; + uint32_t page_size; uint16_t page_bits; uint16_t max_prp_ents; uint16_t cqe_size; diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 94f28e6bac..5651372be3 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -34,15 +34,15 @@ #include #include -/* #define DEBUG_AHCI */ +#define DEBUG_AHCI 0 -#ifdef DEBUG_AHCI #define DPRINTF(port, fmt, ...) \ -do { fprintf(stderr, "ahci: %s: [%d] ", __FUNCTION__, port); \ - fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(port, fmt, ...) do {} while(0) -#endif +do { \ + if (DEBUG_AHCI) { \ + fprintf(stderr, "ahci: %s: [%d] ", __func__, port); \ + fprintf(stderr, fmt, ## __VA_ARGS__); \ + } \ +} while (0) static void check_cmd(AHCIState *s, int port); static int handle_cmd(AHCIState *s,int port,int slot); @@ -551,7 +551,7 @@ static void ahci_reset_port(AHCIState *s, int port) static void debug_print_fis(uint8_t *fis, int cmd_len) { -#ifdef DEBUG_AHCI +#if DEBUG_AHCI int i; fprintf(stderr, "fis:"); @@ -580,7 +580,7 @@ static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished) sdb_fis = (SDBFIS *)&ad->res_fis[RES_FIS_SDBFIS]; ide_state = &ad->port.ifs[0]; - sdb_fis->type = 0xA1; + sdb_fis->type = SATA_FIS_TYPE_SDB; /* Interrupt pending & Notification bit */ sdb_fis->flags = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); sdb_fis->status = ide_state->status & 0x77; @@ -631,7 +631,7 @@ static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len) pio_fis = &ad->res_fis[RES_FIS_PSFIS]; - pio_fis[0] = 0x5f; + pio_fis[0] = SATA_FIS_TYPE_PIO_SETUP; pio_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); pio_fis[2] = s->status; pio_fis[3] = s->error; @@ -690,7 +690,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) d2h_fis = &ad->res_fis[RES_FIS_RFIS]; - d2h_fis[0] = 0x34; + d2h_fis[0] = SATA_FIS_TYPE_REGISTER_D2H; d2h_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); d2h_fis[2] = s->status; d2h_fis[3] = s->error; @@ -1154,9 +1154,7 @@ out: static void ahci_start_dma(IDEDMA *dma, IDEState *s, BlockCompletionFunc *dma_cb) { -#ifdef DEBUG_AHCI AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); -#endif DPRINTF(ad->port_no, "\n"); s->io_buffer_offset = 0; dma_cb(s, 0); diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index e0d2eb8f15..99aa0c967f 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -156,7 +156,10 @@ #define AHCI_SCR_SCTL_DET 0xf #define SATA_FIS_TYPE_REGISTER_H2D 0x27 -#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 +#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 +#define SATA_FIS_TYPE_REGISTER_D2H 0x34 +#define SATA_FIS_TYPE_PIO_SETUP 0x5f +#define SATA_FIS_TYPE_SDB 0xA1 #define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f #define AHCI_CMD_HDR_PRDT_LEN 16 diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index b4f096e12e..1ebb58d36d 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -163,6 +163,11 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) return -1; } + if (dev->conf.logical_block_size != 512) { + error_report("logical_block_size must be 512 for IDE"); + return -1; + } + blkconf_serial(&dev->conf, &dev->serial); if (kind != IDE_CD) { blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255, &err); diff --git a/include/block/block.h b/include/block/block.h index 5450610bc1..610be9ff04 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -374,6 +374,7 @@ BlockDriverState *bdrv_lookup_bs(const char *device, const char *node_name, Error **errp); bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base); +BlockDriverState *bdrv_next_node(BlockDriverState *bs); BlockDriverState *bdrv_next(BlockDriverState *bs); int bdrv_is_encrypted(BlockDriverState *bs); int bdrv_key_required(BlockDriverState *bs); @@ -381,6 +382,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key); int bdrv_query_missing_keys(void); void bdrv_iterate_format(void (*it)(void *opaque, const char *name), void *opaque); +const char *bdrv_get_node_name(const BlockDriverState *bs); const char *bdrv_get_device_name(const BlockDriverState *bs); int bdrv_get_flags(BlockDriverState *bs); int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, diff --git a/include/block/block_int.h b/include/block/block_int.h index a1c17b9578..06a21dd13d 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -57,6 +57,8 @@ #define BLOCK_OPT_REDUNDANCY "redundancy" #define BLOCK_OPT_NOCOW "nocow" +#define BLOCK_PROBE_BUF_SIZE 512 + typedef struct BdrvTrackedRequest { BlockDriverState *bs; int64_t offset; @@ -324,6 +326,7 @@ struct BlockDriverState { int sg; /* if true, the device is a /dev/sg* */ int copy_on_read; /* if true, copy read backing sectors into image note this is a reference count */ + bool probed; BlockDriver *drv; /* NULL means no media */ void *opaque; @@ -411,7 +414,17 @@ struct BlockDriverState { Error *backing_blocker; }; + +/* Essential block drivers which must always be statically linked into qemu, and + * which therefore can be accessed without using bdrv_find_format() */ +extern BlockDriver bdrv_file; +extern BlockDriver bdrv_raw; +extern BlockDriver bdrv_qcow2; + + int get_tmp_filename(char *filename, int size); +BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, + const char *filename); void bdrv_set_io_limits(BlockDriverState *bs, ThrottleConfig *cfg); diff --git a/include/block/nbd.h b/include/block/nbd.h index 9e835d2cbb..348302c90b 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -85,14 +85,13 @@ int nbd_disconnect(int fd); typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; -NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, - off_t size, uint32_t nbdflags, - void (*close)(NBDExport *)); +NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, + uint32_t nbdflags, void (*close)(NBDExport *)); void nbd_export_close(NBDExport *exp); void nbd_export_get(NBDExport *exp); void nbd_export_put(NBDExport *exp); -BlockDriverState *nbd_export_get_blockdev(NBDExport *exp); +BlockBackend *nbd_export_get_blockdev(NBDExport *exp); NBDExport *nbd_export_find(const char *name); void nbd_export_set_name(NBDExport *exp, const char *name); diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 52d13c1c0e..8871a021d0 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -108,6 +108,8 @@ int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs); int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf); BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, BlockCompletionFunc *cb, void *opaque); +int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors); +int blk_co_flush(BlockBackend *blk); int blk_flush(BlockBackend *blk); int blk_flush_all(void); void blk_drain_all(void); @@ -120,6 +122,7 @@ int blk_is_read_only(BlockBackend *blk); int blk_is_sg(BlockBackend *blk); int blk_enable_write_cache(BlockBackend *blk); void blk_set_enable_write_cache(BlockBackend *blk, bool wce); +void blk_invalidate_cache(BlockBackend *blk, Error **errp); int blk_is_inserted(BlockBackend *blk); void blk_lock_medium(BlockBackend *blk, bool locked); void blk_eject(BlockBackend *blk, bool eject_flag); @@ -132,6 +135,15 @@ void blk_op_block_all(BlockBackend *blk, Error *reason); void blk_op_unblock_all(BlockBackend *blk, Error *reason); AioContext *blk_get_aio_context(BlockBackend *blk); void blk_set_aio_context(BlockBackend *blk, AioContext *new_context); +void blk_add_aio_context_notifier(BlockBackend *blk, + void (*attached_aio_context)(AioContext *new_context, void *opaque), + void (*detach_aio_context)(void *opaque), void *opaque); +void blk_remove_aio_context_notifier(BlockBackend *blk, + void (*attached_aio_context)(AioContext *, + void *), + void (*detach_aio_context)(void *), + void *opaque); +void blk_add_close_notifier(BlockBackend *blk, Notifier *notify); void blk_io_plug(BlockBackend *blk); void blk_io_unplug(BlockBackend *blk); BlockAcctStats *blk_get_stats(BlockBackend *blk); diff --git a/monitor.c b/monitor.c index f1031a1e34..b37ddda457 100644 --- a/monitor.c +++ b/monitor.c @@ -2628,10 +2628,10 @@ static mon_cmd_t info_cmds[] = { }, { .name = "block", - .args_type = "verbose:-v,device:B?", - .params = "[-v] [device]", + .args_type = "nodes:-n,verbose:-v,device:B?", + .params = "[-n] [-v] [device]", .help = "show info of one block device or all block devices " - "(and details of images with -v option)", + "(-n: show named nodes; -v: show details)", .mhandler.cmd = hmp_info_block, }, { @@ -4695,7 +4695,7 @@ static void monitor_find_completion_by_table(Monitor *mon, } } str = args[nb_args - 1]; - if (*ptype == '-' && ptype[1] != '\0') { + while (*ptype == '-' && ptype[1] != '\0') { ptype = next_arg_type(ptype); } switch(*ptype) { diff --git a/nbd.c b/nbd.c index a7bce45117..53cf82be0b 100644 --- a/nbd.c +++ b/nbd.c @@ -17,8 +17,7 @@ */ #include "block/nbd.h" -#include "block/block.h" -#include "block/block_int.h" +#include "sysemu/block-backend.h" #include "block/coroutine.h" @@ -101,7 +100,7 @@ struct NBDExport { int refcount; void (*close)(NBDExport *exp); - BlockDriverState *bs; + BlockBackend *blk; char *name; off_t dev_offset; off_t size; @@ -929,7 +928,7 @@ static void nbd_request_put(NBDRequest *req) nbd_client_put(client); } -static void bs_aio_attached(AioContext *ctx, void *opaque) +static void blk_aio_attached(AioContext *ctx, void *opaque) { NBDExport *exp = opaque; NBDClient *client; @@ -943,7 +942,7 @@ static void bs_aio_attached(AioContext *ctx, void *opaque) } } -static void bs_aio_detach(void *opaque) +static void blk_aio_detach(void *opaque) { NBDExport *exp = opaque; NBDClient *client; @@ -957,27 +956,26 @@ static void bs_aio_detach(void *opaque) exp->ctx = NULL; } -NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, - off_t size, uint32_t nbdflags, - void (*close)(NBDExport *)) +NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, + uint32_t nbdflags, void (*close)(NBDExport *)) { NBDExport *exp = g_malloc0(sizeof(NBDExport)); exp->refcount = 1; QTAILQ_INIT(&exp->clients); - exp->bs = bs; + exp->blk = blk; exp->dev_offset = dev_offset; exp->nbdflags = nbdflags; - exp->size = size == -1 ? bdrv_getlength(bs) : size; + exp->size = size == -1 ? blk_getlength(blk) : size; exp->close = close; - exp->ctx = bdrv_get_aio_context(bs); - bdrv_ref(bs); - bdrv_add_aio_context_notifier(bs, bs_aio_attached, bs_aio_detach, exp); + exp->ctx = blk_get_aio_context(blk); + blk_ref(blk); + blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp); /* * NBD exports are used for non-shared storage migration. Make sure * that BDRV_O_INCOMING is cleared and the image is ready for write * access since the export could be available before migration handover. */ - bdrv_invalidate_cache(bs, NULL); + blk_invalidate_cache(blk, NULL); return exp; } @@ -1024,11 +1022,11 @@ void nbd_export_close(NBDExport *exp) } nbd_export_set_name(exp, NULL); nbd_export_put(exp); - if (exp->bs) { - bdrv_remove_aio_context_notifier(exp->bs, bs_aio_attached, - bs_aio_detach, exp); - bdrv_unref(exp->bs); - exp->bs = NULL; + if (exp->blk) { + blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, + blk_aio_detach, exp); + blk_unref(exp->blk); + exp->blk = NULL; } } @@ -1056,9 +1054,9 @@ void nbd_export_put(NBDExport *exp) } } -BlockDriverState *nbd_export_get_blockdev(NBDExport *exp) +BlockBackend *nbd_export_get_blockdev(NBDExport *exp) { - return exp->bs; + return exp->blk; } void nbd_export_close_all(void) @@ -1137,7 +1135,7 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *reque command = request->type & NBD_CMD_MASK_COMMAND; if (command == NBD_CMD_READ || command == NBD_CMD_WRITE) { - req->data = qemu_blockalign(client->exp->bs, request->len); + req->data = blk_blockalign(client->exp->blk, request->len); } if (command == NBD_CMD_WRITE) { TRACE("Reading %u byte(s)", request->len); @@ -1203,7 +1201,7 @@ static void nbd_trip(void *opaque) TRACE("Request type is READ"); if (request.type & NBD_CMD_FLAG_FUA) { - ret = bdrv_co_flush(exp->bs); + ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); reply.error = -ret; @@ -1211,8 +1209,9 @@ static void nbd_trip(void *opaque) } } - ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512, - req->data, request.len / 512); + ret = blk_read(exp->blk, + (request.from + exp->dev_offset) / BDRV_SECTOR_SIZE, + req->data, request.len / BDRV_SECTOR_SIZE); if (ret < 0) { LOG("reading from file failed"); reply.error = -ret; @@ -1234,8 +1233,9 @@ static void nbd_trip(void *opaque) TRACE("Writing to device"); - ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512, - req->data, request.len / 512); + ret = blk_write(exp->blk, + (request.from + exp->dev_offset) / BDRV_SECTOR_SIZE, + req->data, request.len / BDRV_SECTOR_SIZE); if (ret < 0) { LOG("writing to file failed"); reply.error = -ret; @@ -1243,7 +1243,7 @@ static void nbd_trip(void *opaque) } if (request.type & NBD_CMD_FLAG_FUA) { - ret = bdrv_co_flush(exp->bs); + ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); reply.error = -ret; @@ -1262,7 +1262,7 @@ static void nbd_trip(void *opaque) case NBD_CMD_FLUSH: TRACE("Request type is FLUSH"); - ret = bdrv_co_flush(exp->bs); + ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); reply.error = -ret; @@ -1273,8 +1273,9 @@ static void nbd_trip(void *opaque) break; case NBD_CMD_TRIM: TRACE("Request type is TRIM"); - ret = bdrv_co_discard(exp->bs, (request.from + exp->dev_offset) / 512, - request.len / 512); + ret = blk_co_discard(exp->blk, (request.from + exp->dev_offset) + / BDRV_SECTOR_SIZE, + request.len / BDRV_SECTOR_SIZE); if (ret < 0) { LOG("discard failed"); reply.error = -ret; diff --git a/qapi/block-core.json b/qapi/block-core.json index a14e6ab1fd..6e8db15861 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -182,6 +182,22 @@ '*total-clusters': 'int', '*allocated-clusters': 'int', '*fragmented-clusters': 'int', '*compressed-clusters': 'int' } } +## +# @BlockdevCacheInfo +# +# Cache mode information for a block device +# +# @writeback: true if writeback mode is enabled +# @direct: true if the host page cache is bypassed (O_DIRECT) +# @no-flush: true if flush requests are ignored for the device +# +# Since: 2.3 +## +{ 'type': 'BlockdevCacheInfo', + 'data': { 'writeback': 'bool', + 'direct': 'bool', + 'no-flush': 'bool' } } + ## # @BlockDeviceInfo: # @@ -239,6 +255,8 @@ # # @iops_size: #optional an I/O size in bytes (Since 1.7) # +# @cache: the cache mode used for the block device (since: 2.3) +# # Since: 0.14.0 # ## @@ -253,7 +271,7 @@ '*bps_max': 'int', '*bps_rd_max': 'int', '*bps_wr_max': 'int', '*iops_max': 'int', '*iops_rd_max': 'int', '*iops_wr_max': 'int', - '*iops_size': 'int' } } + '*iops_size': 'int', 'cache': 'BlockdevCacheInfo' } } ## # @BlockDeviceIoStatus: @@ -405,6 +423,8 @@ # @device: #optional If the stats are for a virtual block device, the name # corresponding to the virtual block device. # +# @device: #optional The node name of the device. (Since 2.3) +# # @stats: A @BlockDeviceStats for the device. # # @parent: #optional This describes the file block device if it has one. @@ -415,7 +435,8 @@ # Since: 0.14.0 ## { 'type': 'BlockStats', - 'data': {'*device': 'str', 'stats': 'BlockDeviceStats', + 'data': {'*device': 'str', '*node-name': 'str', + 'stats': 'BlockDeviceStats', '*parent': 'BlockStats', '*backing': 'BlockStats'} } @@ -424,11 +445,20 @@ # # Query the @BlockStats for all virtual block devices. # +# @query-nodes: #optional If true, the command will query all the block nodes +# that have a node name, in a list which will include "parent" +# information, but not "backing". +# If false or omitted, the behavior is as before - query all the +# device backends, recursively including their "parent" and +# "backing". (Since 2.3) +# # Returns: A list of @BlockStats for each virtual block devices. # # Since: 0.14.0 ## -{ 'command': 'query-blockstats', 'returns': ['BlockStats'] } +{ 'command': 'query-blockstats', + 'data': { '*query-nodes': 'bool' }, + 'returns': ['BlockStats'] } ## # @BlockdevOnError: diff --git a/qemu-img.c b/qemu-img.c index a42335c632..7876258fa9 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1531,6 +1531,20 @@ static int img_convert(int argc, char **argv) goto out; } + if (!drv->create_opts) { + error_report("Format driver '%s' does not support image creation", + drv->format_name); + ret = -1; + goto out; + } + + if (!proto_drv->create_opts) { + error_report("Protocol driver '%s' does not support image creation", + proto_drv->format_name); + ret = -1; + goto out; + } + create_opts = qemu_opts_append(create_opts, drv->create_opts); create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); @@ -2972,6 +2986,13 @@ static int img_amend(int argc, char **argv) goto out; } + if (!bs->drv->create_opts) { + error_report("Format driver '%s' does not support any options to amend", + fmt); + ret = -1; + goto out; + } + create_opts = qemu_opts_append(create_opts, bs->drv->create_opts); opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); if (options && qemu_opts_do_parse(opts, options, NULL)) { diff --git a/qemu-io.c b/qemu-io.c index 60f84dd72a..91a445a106 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -51,7 +51,8 @@ static const cmdinfo_t close_cmd = { .oneline = "close the current open file", }; -static int openfile(char *name, int flags, int growable, QDict *opts) +static int openfile(char *name, BlockDriver *drv, int flags, int growable, + QDict *opts) { Error *local_err = NULL; @@ -68,7 +69,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts) flags |= BDRV_O_PROTOCOL; } - if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err) < 0) { + if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, drv, &local_err) < 0) { fprintf(stderr, "%s: can't open%s%s: %s\n", progname, name ? " device " : "", name ?: "", error_get_pretty(local_err)); @@ -169,9 +170,9 @@ static int open_f(BlockDriverState *bs, int argc, char **argv) qemu_opts_reset(&empty_opts); if (optind == argc - 1) { - return openfile(argv[optind], flags, growable, opts); + return openfile(argv[optind], NULL, flags, growable, opts); } else if (optind == argc) { - return openfile(NULL, flags, growable, opts); + return openfile(NULL, NULL, flags, growable, opts); } else { QDECREF(opts); return qemuio_command_usage(&open_cmd); @@ -196,11 +197,12 @@ static const cmdinfo_t quit_cmd = { static void usage(const char *name) { printf( -"Usage: %s [-h] [-V] [-rsnm] [-c STRING] ... [file]\n" +"Usage: %s [-h] [-V] [-rsnm] [-f FMT] [-c STRING] ... [file]\n" "QEMU Disk exerciser\n" "\n" " -c, --cmd STRING execute command with its arguments\n" " from the given string\n" +" -f, --format FMT specifies the block driver to use\n" " -r, --read-only export read-only\n" " -s, --snapshot use snapshot file\n" " -n, --nocache disable host cache\n" @@ -364,12 +366,13 @@ int main(int argc, char **argv) { int readonly = 0; int growable = 0; - const char *sopt = "hVc:d:rsnmgkt:T:"; + const char *sopt = "hVc:d:f:rsnmgkt:T:"; const struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "offset", 1, NULL, 'o' }, { "cmd", 1, NULL, 'c' }, + { "format", 1, NULL, 'f' }, { "read-only", 0, NULL, 'r' }, { "snapshot", 0, NULL, 's' }, { "nocache", 0, NULL, 'n' }, @@ -384,6 +387,7 @@ int main(int argc, char **argv) int c; int opt_index = 0; int flags = BDRV_O_UNMAP; + BlockDriver *drv = NULL; Error *local_error = NULL; #ifdef CONFIG_POSIX @@ -393,6 +397,8 @@ int main(int argc, char **argv) progname = basename(argv[0]); qemu_init_exec_dir(argv[0]); + bdrv_init(); + while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { switch (c) { case 's': @@ -407,6 +413,13 @@ int main(int argc, char **argv) exit(1); } break; + case 'f': + drv = bdrv_find_format(optarg); + if (!drv) { + error_report("Invalid format '%s'", optarg); + exit(EXIT_FAILURE); + } + break; case 'c': add_user_command(optarg); break; @@ -455,7 +468,6 @@ int main(int argc, char **argv) error_free(local_error); exit(1); } - bdrv_init(); /* initialize commands */ qemuio_add_command(&quit_cmd); @@ -477,7 +489,7 @@ int main(int argc, char **argv) } if ((argc - optind) == 1) { - openfile(argv[optind], flags, growable, NULL); + openfile(argv[optind], drv, flags, growable, NULL); } command_loop(); diff --git a/qemu-nbd.c b/qemu-nbd.c index 5cd6c6d187..d222512412 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -146,7 +146,7 @@ static void read_partition(uint8_t *p, struct partition_record *r) r->nb_sectors_abs = p[12] | p[13] << 8 | p[14] << 16 | p[15] << 24; } -static int find_partition(BlockDriverState *bs, int partition, +static int find_partition(BlockBackend *blk, int partition, off_t *offset, off_t *size) { struct partition_record mbr[4]; @@ -155,7 +155,7 @@ static int find_partition(BlockDriverState *bs, int partition, int ext_partnum = 4; int ret; - if ((ret = bdrv_read(bs, 0, data, 1)) < 0) { + if ((ret = blk_read(blk, 0, data, 1)) < 0) { errno = -ret; err(EXIT_FAILURE, "error while reading"); } @@ -175,7 +175,7 @@ static int find_partition(BlockDriverState *bs, int partition, uint8_t data1[512]; int j; - if ((ret = bdrv_read(bs, mbr[i].start_sector_abs, data1, 1)) < 0) { + if ((ret = blk_read(blk, mbr[i].start_sector_abs, data1, 1)) < 0) { errno = -ret; err(EXIT_FAILURE, "error while reading"); } @@ -720,17 +720,17 @@ int main(int argc, char **argv) } bs->detect_zeroes = detect_zeroes; - fd_size = bdrv_getlength(bs); + fd_size = blk_getlength(blk); if (partition != -1) { - ret = find_partition(bs, partition, &dev_offset, &fd_size); + ret = find_partition(blk, partition, &dev_offset, &fd_size); if (ret < 0) { errno = -ret; err(EXIT_FAILURE, "Could not find partition %d", partition); } } - exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed); + exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed); if (sockpath) { fd = unix_socket_incoming(sockpath); diff --git a/qemu-options.hx b/qemu-options.hx index 64af16d64c..6f273ee7f0 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2790,6 +2790,14 @@ STEXI @findex -qmp Like -monitor but opens in 'control' mode. ETEXI +DEF("qmp-pretty", HAS_ARG, QEMU_OPTION_qmp_pretty, \ + "-qmp-pretty dev like -qmp but uses pretty JSON formatting\n", + QEMU_ARCH_ALL) +STEXI +@item -qmp-pretty @var{dev} +@findex -qmp-pretty +Like -qmp but uses pretty JSON formatting. +ETEXI DEF("mon", HAS_ARG, QEMU_OPTION_mon, \ "-mon [chardev=]name[,mode=readline|control][,default]\n", QEMU_ARCH_ALL) diff --git a/qmp-commands.hx b/qmp-commands.hx index 718dd92f6a..d4b00101c7 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2347,7 +2347,7 @@ EQMP { .name = "query-blockstats", - .args_type = "", + .args_type = "query-nodes:b?", .mhandler.cmd_new = qmp_marshal_input_query_blockstats, }, diff --git a/qobject/qjson.c b/qobject/qjson.c index 6cf2511580..12c576d548 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -86,8 +86,9 @@ static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) QString *qkey; int j; - if (s->count) - qstring_append(s->str, ", "); + if (s->count) { + qstring_append(s->str, s->pretty ? "," : ", "); + } if (s->pretty) { qstring_append(s->str, "\n"); @@ -109,8 +110,9 @@ static void to_json_list_iter(QObject *obj, void *opaque) ToJsonIterState *s = opaque; int j; - if (s->count) - qstring_append(s->str, ", "); + if (s->count) { + qstring_append(s->str, s->pretty ? "," : ", "); + } if (s->pretty) { qstring_append(s->str, "\n"); diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 4c77ebec7a..e77fa3a25c 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -487,7 +487,8 @@ static void qtest_shutdown(void) */ static QPCIDevice *ahci_boot(void) { - qtest_boot("-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s" + qtest_boot("-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s," + "format=raw" " -M q35 " "-device ide-hd,drive=drive0 " "-global ide-hd.ver=%s", diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 9e4d20592b..2519f7d0e2 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -716,7 +716,7 @@ static void test_acpi_one(const char *params, test_data *data) int i; args = g_strdup_printf("-net none -display none %s " - "-drive id=hd0,if=none,file=%s " + "-drive id=hd0,if=none,file=%s,format=raw " "-device ide-hd,drive=hd0 ", params ? params : "", disk); diff --git a/tests/drive_del-test.c b/tests/drive_del-test.c index 53fa969260..8951f6f610 100644 --- a/tests/drive_del-test.c +++ b/tests/drive_del-test.c @@ -103,7 +103,7 @@ static void test_after_failed_device_add(void) static void test_drive_del_device_del(void) { /* Start with a drive used by a device that unplugs instantaneously */ - qtest_start("-drive if=none,id=drive0,file=/dev/null" + qtest_start("-drive if=none,id=drive0,file=/dev/null,format=raw" " -device virtio-scsi-pci" " -device scsi-hd,drive=drive0,id=dev0"); diff --git a/tests/fdc-test.c b/tests/fdc-test.c index 203074cdad..3c6c83cac4 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -291,7 +291,7 @@ static void test_media_insert(void) /* Insert media in drive. DSKCHK should not be reset until a step pulse * is sent. */ qmp_discard_response("{'execute':'change', 'arguments':{" - " 'device':'floppy0', 'target': %s }}", + " 'device':'floppy0', 'target': %s, 'arg': 'raw' }}", test_image); qmp_discard_response(""); /* ignore event (FIXME open -> open transition?!) */ diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c index c84d1e75e0..7cc8dfff16 100644 --- a/tests/hd-geo-test.c +++ b/tests/hd-geo-test.c @@ -208,7 +208,7 @@ static int setup_ide(int argc, char *argv[], int argv_sz, { char *s1, *s2, *s3; - s1 = g_strdup_printf("-drive id=drive%d,if=%s", + s1 = g_strdup_printf("-drive id=drive%d,if=%s,format=raw", ide_idx, dev ? "none" : "ide"); s2 = dev ? g_strdup("") : g_strdup_printf(",index=%d", ide_idx); diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c index ad232b561c..a3f72790ea 100644 --- a/tests/i440fx-test.c +++ b/tests/i440fx-test.c @@ -342,8 +342,9 @@ static void test_i440fx_firmware(FirmwareTestFixture *fixture, g_assert(fw_pathname != NULL); /* Better hope the user didn't put metacharacters in TMPDIR and co. */ - cmdline = g_strdup_printf("-S %s %s", - fixture->is_bios ? "-bios" : "-pflash", + cmdline = g_strdup_printf("-S %s%s", fixture->is_bios + ? "-bios " + : "-drive if=pflash,format=raw,file=", fw_pathname); g_test_message("qemu cmdline: %s", cmdline); qtest_start(cmdline); diff --git a/tests/ide-test.c b/tests/ide-test.c index b7a97e9362..29f4039bd5 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -385,7 +385,7 @@ static void test_bmdma_no_busmaster(void) static void test_bmdma_setup(void) { ide_test_start( - "-drive file=%s,if=ide,serial=%s,cache=writeback " + "-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw " "-global ide-hd.ver=%s", tmp_path, "testdisk", "version"); } @@ -414,7 +414,7 @@ static void test_identify(void) int ret; ide_test_start( - "-drive file=%s,if=ide,serial=%s,cache=writeback " + "-drive file=%s,if=ide,serial=%s,cache=writeback,format=raw " "-global ide-hd.ver=%s", tmp_path, "testdisk", "version"); @@ -458,7 +458,7 @@ static void test_flush(void) uint8_t data; ide_test_start( - "-drive file=blkdebug::%s,if=ide,cache=writeback", + "-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw", tmp_path); /* Delay the completion of the flush request until we explicitly do it */ @@ -526,7 +526,8 @@ static void test_retry_flush(void) ide_test_start( "-vnc none " - "-drive file=blkdebug:%s:%s,if=ide,cache=writeback,rerror=stop,werror=stop", + "-drive file=blkdebug:%s:%s,if=ide,cache=writeback,format=raw," + "rerror=stop,werror=stop", debug_path, tmp_path); /* FLUSH CACHE command on device 0*/ diff --git a/tests/nvme-test.c b/tests/nvme-test.c index 85768e837b..ff38b5e48f 100644 --- a/tests/nvme-test.c +++ b/tests/nvme-test.c @@ -24,7 +24,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); qtest_add_func("/nvme/nop", nop); - qtest_start("-drive id=drv0,if=none,file=/dev/null " + qtest_start("-drive id=drv0,if=none,file=/dev/null,format=raw " "-device nvme,drive=drv0,serial=foo"); ret = g_test_run(); diff --git a/tests/qemu-iotests/016 b/tests/qemu-iotests/016 index 7ea9e94b5d..52397aa80e 100755 --- a/tests/qemu-iotests/016 +++ b/tests/qemu-iotests/016 @@ -43,25 +43,28 @@ _supported_proto file sheepdog nfs _supported_os Linux +# No -f, use probing for the protocol driver +QEMU_IO_PROTO="$QEMU_IO_PROG -g --cache $CACHEMODE" + size=128M _make_test_img $size echo echo "== reading at EOF ==" -$QEMU_IO -g -c "read -P 0 $size 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO_PROTO -c "read -P 0 $size 512" "$TEST_IMG" | _filter_qemu_io echo echo "== reading far past EOF ==" -$QEMU_IO -g -c "read -P 0 256M 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO_PROTO -c "read -P 0 256M 512" "$TEST_IMG" | _filter_qemu_io echo echo "== writing at EOF ==" -$QEMU_IO -g -c "write -P 66 $size 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO_PROTO -c "write -P 66 $size 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "read -P 66 $size 512" "$TEST_IMG" | _filter_qemu_io echo echo "== writing far past EOF ==" -$QEMU_IO -g -c "write -P 66 256M 512" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO_PROTO -c "write -P 66 256M 512" "$TEST_IMG" | _filter_qemu_io $QEMU_IO -c "read -P 66 256M 512" "$TEST_IMG" | _filter_qemu_io # success, all done diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out index f7c78e712a..ad84ac2b1b 100644 --- a/tests/qemu-iotests/026.out +++ b/tests/qemu-iotests/026.out @@ -14,6 +14,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -21,6 +23,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -38,6 +42,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -45,6 +51,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -70,7 +78,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 5; imm: off; once: off; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -78,7 +90,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 5; imm: off; once: off; write -b wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error read failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -102,7 +118,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 28; imm: off; once: off; write wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -110,12 +130,17 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_load; errno: 28; imm: off; once: off; write -b wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device read failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: on; write +Failed to flush the L2 table cache: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. @@ -123,6 +148,7 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: on; write -b +Failed to flush the L2 table cache: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. @@ -130,6 +156,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. @@ -137,6 +165,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 127 leaked clusters were found on the image. @@ -144,6 +174,7 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: on; write +Failed to flush the L2 table cache: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. @@ -151,6 +182,7 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: on; write -b +Failed to flush the L2 table cache: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. @@ -158,6 +190,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. @@ -165,6 +199,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 127 leaked clusters were found on the image. @@ -182,11 +218,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -204,11 +244,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -226,11 +270,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -246,11 +294,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -266,11 +318,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -286,51 +342,67 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: on; write +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: on; write -b +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: on; write +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: on; write -b +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -346,11 +418,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -366,11 +442,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -386,11 +466,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 5; imm: off; once: off; write -b +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -406,11 +490,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: cluster_alloc; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. @@ -429,6 +517,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 55 leaked clusters were found on the image. @@ -436,6 +526,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 251 leaked clusters were found on the image. @@ -453,11 +545,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -473,6 +569,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. @@ -480,6 +578,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -497,6 +597,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. @@ -504,6 +606,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -521,6 +625,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 11 leaked clusters were found on the image. @@ -528,6 +634,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write -b +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -543,6 +651,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.alloc_table; errno: 5; imm: off; once: off +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -553,6 +663,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.alloc_table; errno: 28; imm: off; once: off +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -563,6 +675,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.write_table; errno: 5; imm: off; once: off +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -573,6 +687,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.write_table; errno: 28; imm: off; once: off +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -583,6 +699,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.activate_table; errno: 5; imm: off; once: off +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error write failed: Input/output error 96 leaked clusters were found on the image. @@ -595,6 +713,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow.activate_table; errno: 28; imm: off; once: off +Failed to flush the L2 table cache: No space left on device +Failed to flush the refcount block cache: No space left on device write failed: No space left on device 96 leaked clusters were found on the image. diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index 8ce2373cf5..952a524ec7 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -34,7 +34,7 @@ class TestSingleDrive(iotests.QMPTestCase): iotests.create_image(backing_img, TestSingleDrive.image_len) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) - qemu_io('-c', 'write -P 0x1 0 512', backing_img) + qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 512', backing_img) self.vm = iotests.VM().add_drive("blkdebug::" + test_img) self.vm.launch() @@ -55,8 +55,8 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() self.vm.shutdown() - self.assertEqual(qemu_io('-c', 'map', backing_img), - qemu_io('-c', 'map', test_img), + self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img), + qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img), 'image file map does not match backing file after streaming') def test_stream_pause(self): @@ -86,8 +86,8 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() self.vm.shutdown() - self.assertEqual(qemu_io('-c', 'map', backing_img), - qemu_io('-c', 'map', test_img), + self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img), + qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img), 'image file map does not match backing file after streaming') def test_stream_partial(self): @@ -101,8 +101,8 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() self.vm.shutdown() - self.assertEqual(qemu_io('-c', 'map', mid_img), - qemu_io('-c', 'map', test_img), + self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img), + qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img), 'image file map does not match backing file after streaming') def test_device_not_found(self): @@ -359,9 +359,9 @@ class TestStreamStop(iotests.QMPTestCase): def setUp(self): qemu_img('create', backing_img, str(TestStreamStop.image_len)) - qemu_io('-c', 'write -P 0x1 0 32M', backing_img) + qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) - qemu_io('-c', 'write -P 0x1 32M 32M', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) self.vm = iotests.VM().add_drive("blkdebug::" + test_img) self.vm.launch() @@ -388,9 +388,9 @@ class TestSetSpeed(iotests.QMPTestCase): def setUp(self): qemu_img('create', backing_img, str(TestSetSpeed.image_len)) - qemu_io('-c', 'write -P 0x1 0 32M', backing_img) + qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 32M', backing_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img) - qemu_io('-c', 'write -P 0x1 32M 32M', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 32M 32M', test_img) self.vm = iotests.VM().add_drive('blkdebug::' + test_img) self.vm.launch() diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 2b432ad7a1..ea2f98e51d 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -76,8 +76,8 @@ class TestSingleDrive(ImageCommitTestCase): iotests.create_image(backing_img, self.image_len) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) - qemu_io('-c', 'write -P 0xab 0 524288', backing_img) - qemu_io('-c', 'write -P 0xef 524288 524288', mid_img) + qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -89,8 +89,8 @@ class TestSingleDrive(ImageCommitTestCase): def test_commit(self): self.run_commit_test(mid_img, backing_img) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) def test_device_not_found(self): result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % mid_img) @@ -116,13 +116,13 @@ class TestSingleDrive(ImageCommitTestCase): def test_top_is_active(self): self.run_commit_test(test_img, backing_img, need_ready=True) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) def test_top_is_default_active(self): self.run_default_commit_test() - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) def test_top_and_base_reversed(self): self.assert_no_active_block_jobs() @@ -159,8 +159,8 @@ class TestRelativePaths(ImageCommitTestCase): qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.mid_img_abs, self.test_img) qemu_img('rebase', '-u', '-b', self.backing_img, self.mid_img_abs) qemu_img('rebase', '-u', '-b', self.mid_img, self.test_img) - qemu_io('-c', 'write -P 0xab 0 524288', self.backing_img_abs) - qemu_io('-c', 'write -P 0xef 524288 524288', self.mid_img_abs) + qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', self.backing_img_abs) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', self.mid_img_abs) self.vm = iotests.VM().add_drive(self.test_img) self.vm.launch() @@ -179,8 +179,8 @@ class TestRelativePaths(ImageCommitTestCase): def test_commit(self): self.run_commit_test(self.mid_img, self.backing_img) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) def test_device_not_found(self): result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % self.mid_img) @@ -206,8 +206,8 @@ class TestRelativePaths(ImageCommitTestCase): def test_top_is_active(self): self.run_commit_test(self.test_img, self.backing_img) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) - self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed")) + self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) def test_top_and_base_reversed(self): self.assert_no_active_block_jobs() @@ -223,8 +223,8 @@ class TestSetSpeed(ImageCommitTestCase): qemu_img('create', backing_img, str(TestSetSpeed.image_len)) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img) qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) - qemu_io('-c', 'write -P 0x1 0 512', test_img) - qemu_io('-c', 'write -P 0xef 524288 524288', mid_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 0 512', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048 index 65da46d6f5..e1eeac2a31 100755 --- a/tests/qemu-iotests/048 +++ b/tests/qemu-iotests/048 @@ -64,7 +64,7 @@ _compare _compare -q # Compare images with different size -$QEMU_IMG resize "$TEST_IMG" +512M +$QEMU_IMG resize -f $IMGFMT "$TEST_IMG" +512M _compare _compare -s diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 2c7e808765..7f161342a2 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -50,6 +50,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DI QEMU X.Y.Z monitor - type 'help' for more information (qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block ide0-hd0: TEST_DIR/t.qcow2 (qcow2) + Cache mode: writeback Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1) (qemu) qququiquit diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 index 451b67ddfb..0872444811 100755 --- a/tests/qemu-iotests/055 +++ b/tests/qemu-iotests/055 @@ -34,10 +34,10 @@ class TestSingleDrive(iotests.QMPTestCase): def setUp(self): # Write data to the image so we can compare later qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleDrive.image_len)) - qemu_io('-c', 'write -P0x5d 0 64k', test_img) - qemu_io('-c', 'write -P0xd5 1M 32k', test_img) - qemu_io('-c', 'write -P0xdc 32M 124k', test_img) - qemu_io('-c', 'write -P0xdc 67043328 64k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -115,7 +115,7 @@ class TestSetSpeed(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSetSpeed.image_len)) - qemu_io('-c', 'write -P1 0 512', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P1 0 512', test_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() @@ -186,10 +186,10 @@ class TestSingleTransaction(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, test_img, str(TestSingleTransaction.image_len)) - qemu_io('-c', 'write -P0x5d 0 64k', test_img) - qemu_io('-c', 'write -P0xd5 1M 32k', test_img) - qemu_io('-c', 'write -P0xdc 32M 124k', test_img) - qemu_io('-c', 'write -P0xdc 67043328 64k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 0 64k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xd5 1M 32k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 32M 124k', test_img) + qemu_io('-f', iotests.imgfmt, '-c', 'write -P0xdc 67043328 64k', test_img) self.vm = iotests.VM().add_drive(test_img) self.vm.launch() diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058 index 14584cdea2..2d5ca85ddc 100755 --- a/tests/qemu-iotests/058 +++ b/tests/qemu-iotests/058 @@ -89,6 +89,9 @@ _supported_fmt qcow2 _supported_proto file _require_command QEMU_NBD +# Use -f raw instead of -f $IMGFMT for the NBD connection +QEMU_IO_NBD="$QEMU_IO -f raw --cache=$CACHEMODE" + echo echo "== preparing image ==" _make_test_img 64M @@ -108,15 +111,15 @@ _export_nbd_snapshot sn1 echo echo "== verifying the exported snapshot with patterns, method 1 ==" -$QEMU_IO -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io -$QEMU_IO -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io +$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io +$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io _export_nbd_snapshot1 sn1 echo echo "== verifying the exported snapshot with patterns, method 2 ==" -$QEMU_IO -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io -$QEMU_IO -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io +$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io +$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io $QEMU_IMG convert "$TEST_IMG" -l sn1 -O qcow2 "$converted_image" diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 index 3c053c29b4..2ed1a7ffe6 100755 --- a/tests/qemu-iotests/059 +++ b/tests/qemu-iotests/059 @@ -106,8 +106,8 @@ _img_info echo echo "=== Converting to streamOptimized from image with small cluster size===" TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 IMGOPTS="cluster_size=4096" _make_test_img 1G -$QEMU_IO -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io -$QEMU_IO -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io +$QEMU_IO -f qcow2 -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io +$QEMU_IO -f qcow2 -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io $QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2" "$TEST_IMG" 2>&1 echo diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index 9772d365ae..73863bf1f6 100755 --- a/tests/qemu-iotests/060 +++ b/tests/qemu-iotests/060 @@ -77,7 +77,7 @@ $QEMU_IO -c "$OPEN_RW" -c "write -P 0x2a 0 512" | _filter_qemu_io $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features # This information should be available through qemu-img info -$QEMU_IMG info "$TEST_IMG" | _filter_testdir +_img_info --format-specific # Try to open the image R/W (which should fail) $QEMU_IO -c "$OPEN_RW" -c "read 0 512" 2>&1 | _filter_qemu_io \ diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index 9419da1b41..4cdf62bde0 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -11,10 +11,9 @@ incompatible_features 0x0 qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L1 table); further corruption events will be suppressed write failed: Input/output error incompatible_features 0x2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 64M (67108864 bytes) -disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 index d025192c83..29cd6b5aff 100755 --- a/tests/qemu-iotests/067 +++ b/tests/qemu-iotests/067 @@ -39,7 +39,7 @@ _supported_os Linux function do_run_qemu() { echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" + $QEMU -nographic -qmp-pretty stdio -serial none "$@" echo } diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out index 0f72dcf63a..7c3735f181 100644 --- a/tests/qemu-iotests/067.out +++ b/tests/qemu-iotests/067.out @@ -4,77 +4,767 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 === -drive/-device and device_del === Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0 -QMP_VERSION -{"return": {}} -{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESET"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": [ + { + "io-status": "ok", + "device": "disk", + "locked": false, + "removable": false, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "type": "unknown" + }, + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "path": "/machine/peripheral/virtio0/virtio-backend" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "device": "virtio0", + "path": "/machine/peripheral/virtio0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "RESET" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "SHUTDOWN" +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "ide1-cd0", + "tray-open": true + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "floppy0", + "tray-open": true + } +} === -drive/device_add and device_del === Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -QMP_VERSION -{"return": {}} -{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESET"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": [ + { + "device": "disk", + "locked": false, + "removable": true, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "tray_open": false, + "type": "unknown" + }, + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "path": "/machine/peripheral/virtio0/virtio-backend" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "device": "virtio0", + "path": "/machine/peripheral/virtio0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "RESET" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "SHUTDOWN" +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "ide1-cd0", + "tray-open": true + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "floppy0", + "tray-open": true + } +} === drive_add/device_add and device_del === Testing: -QMP_VERSION -{"return": {}} -{"return": "OK\r\n"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESET"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": "OK\r\n" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "disk", + "locked": false, + "removable": true, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "path": "/machine/peripheral/virtio0/virtio-backend" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "device": "virtio0", + "path": "/machine/peripheral/virtio0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "RESET" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "SHUTDOWN" +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "ide1-cd0", + "tray-open": true + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "floppy0", + "tray-open": true + } +} === blockdev_add/device_add and device_del === Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"device": "virtio0", "path": "/machine/peripheral/virtio0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESET"} -{"return": [{"io-status": "ok", "device": "ide1-cd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "floppy0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"device": "sd0", "locked": false, "removable": true, "tray_open": false, "type": "unknown"}, {"io-status": "ok", "device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false, "corrupt": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}} +{ + QMP_VERSION +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "disk", + "locked": false, + "removable": true, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "path": "/machine/peripheral/virtio0/virtio-backend" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_DELETED", + "data": { + "device": "virtio0", + "path": "/machine/peripheral/virtio0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "RESET" +} +{ + "return": [ + { + "io-status": "ok", + "device": "ide1-cd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "floppy0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "device": "sd0", + "locked": false, + "removable": true, + "tray_open": false, + "type": "unknown" + }, + { + "io-status": "ok", + "device": "disk", + "locked": false, + "removable": true, + "inserted": { + "iops_rd": 0, + "detect_zeroes": "off", + "image": { + "virtual-size": 134217728, + "filename": "TEST_DIR/t.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": SIZE, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "corrupt": false + } + }, + "dirty-flag": false + }, + "iops_wr": 0, + "ro": false, + "backing_file_depth": 0, + "drv": "qcow2", + "iops": 0, + "bps_wr": 0, + "encrypted": false, + "bps": 0, + "bps_rd": 0, + "cache": { + "no-flush": false, + "direct": false, + "writeback": true + }, + "file": "TEST_DIR/t.qcow2", + "encryption_key_missing": false + }, + "tray_open": false, + "type": "unknown" + } + ] +} +{ + "return": { + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "SHUTDOWN" +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "ide1-cd0", + "tray-open": true + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "DEVICE_TRAY_MOVED", + "data": { + "device": "floppy0", + "tray-open": true + } +} *** done diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071 index 3924e51f51..5d61ef6d81 100755 --- a/tests/qemu-iotests/071 +++ b/tests/qemu-iotests/071 @@ -63,12 +63,12 @@ echo TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\ _filter_imgfmt _make_test_img $IMG_SIZE -$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ +$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ -c 'read 0 512' -c 'write -P 42 0x38000 512' -c 'read -P 42 0x38000 512' | _filter_qemu_io $QEMU_IO -c 'write -P 42 0 512' "$TEST_IMG" | _filter_qemu_io -$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ +$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ -c 'read -P 42 0 512' | _filter_qemu_io echo @@ -78,12 +78,12 @@ echo TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\ _filter_imgfmt _make_test_img $IMG_SIZE -$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base,file.test.driver=$IMGFMT,file.test.file.filename=$TEST_IMG" \ +$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base,file.test.driver=$IMGFMT,file.test.file.filename=$TEST_IMG" \ -c 'read 0 512' -c 'write -P 42 0x38000 512' -c 'read -P 42 0x38000 512' | _filter_qemu_io $QEMU_IO -c 'write -P 42 0 512' "$TEST_IMG" | _filter_qemu_io -$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ +$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \ -c 'read -P 42 0 512' | _filter_qemu_io echo @@ -163,7 +163,7 @@ echo echo "=== Testing blkverify on existing raw block device ===" echo -run_qemu -drive "file=$TEST_IMG.base,if=none,id=drive0" <&1 | _filter_qemu_io | _filter_testdir +poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x$(printf %x $offset_ext_size)" +{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out index f7a943c7a4..33d1f71232 100644 --- a/tests/qemu-iotests/080.out +++ b/tests/qemu-iotests/080.out @@ -13,6 +13,8 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset no file open, try 'help open' qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large no file open, try 'help open' +qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large +no file open, try 'help open' == Huge refcount table size == Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081 index ed3c29e13c..9ab93ff89e 100755 --- a/tests/qemu-iotests/081 +++ b/tests/qemu-iotests/081 @@ -59,9 +59,13 @@ function run_qemu() test_quorum=$($QEMU_IMG --help|grep quorum) [ "$test_quorum" = "" ] && _supported_fmt quorum -quorum="file.driver=quorum,file.children.0.file.filename=$TEST_DIR/1.raw" +quorum="driver=raw,file.driver=quorum,file.vote-threshold=2" +quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw" quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw" -quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw,file.vote-threshold=2" +quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw" +quorum="$quorum,file.children.0.driver=raw" +quorum="$quorum,file.children.1.driver=raw" +quorum="$quorum,file.children.2.driver=raw" echo echo "== creating quorum files ==" diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out index 073515ea50..190905a084 100644 --- a/tests/qemu-iotests/081.out +++ b/tests/qemu-iotests/081.out @@ -55,5 +55,5 @@ wrote 10485760/10485760 bytes at offset 0 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == checking that quorum is broken == -qemu-io: can't open: Could not read image for determining its format: Input/output error +read failed: Input/output error *** done diff --git a/tests/qemu-iotests/082 b/tests/qemu-iotests/082 index e64de27733..c83e01e7cd 100755 --- a/tests/qemu-iotests/082 +++ b/tests/qemu-iotests/082 @@ -60,11 +60,11 @@ _img_info # Multiple -o should be merged run_qemu_img create -f $IMGFMT -o cluster_size=4k -o lazy_refcounts=on "$TEST_IMG" $size -run_qemu_img info "$TEST_IMG" +_img_info --format-specific # If the same -o key is specified more than once, the last one wins run_qemu_img create -f $IMGFMT -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k "$TEST_IMG" $size -run_qemu_img info "$TEST_IMG" +_img_info --format-specific run_qemu_img create -f $IMGFMT -o cluster_size=4k,cluster_size=8k "$TEST_IMG" $size _img_info @@ -114,11 +114,11 @@ TEST_IMG="${TEST_IMG}.base" _img_info # Multiple -o should be merged run_qemu_img convert -O $IMGFMT -o cluster_size=4k -o lazy_refcounts=on "$TEST_IMG" "$TEST_IMG".base -run_qemu_img info "$TEST_IMG".base +TEST_IMG="${TEST_IMG}.base" _img_info --format-specific # If the same -o key is specified more than once, the last one wins run_qemu_img convert -O $IMGFMT -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k "$TEST_IMG" "$TEST_IMG".base -run_qemu_img info "$TEST_IMG".base +TEST_IMG="${TEST_IMG}.base" _img_info --format-specific run_qemu_img convert -O $IMGFMT -o cluster_size=4k,cluster_size=8k "$TEST_IMG" "$TEST_IMG".base TEST_IMG="${TEST_IMG}.base" _img_info @@ -157,15 +157,15 @@ echo === amend: Options specified more than once === # Last -f should win run_qemu_img amend -f foo -f $IMGFMT -o lazy_refcounts=on "$TEST_IMG" -run_qemu_img info "$TEST_IMG" +_img_info --format-specific # Multiple -o should be merged run_qemu_img amend -f $IMGFMT -o size=130M -o lazy_refcounts=off "$TEST_IMG" -run_qemu_img info "$TEST_IMG" +_img_info --format-specific # If the same -o key is specified more than once, the last one wins run_qemu_img amend -f $IMGFMT -o size=8M -o lazy_refcounts=on -o size=132M "$TEST_IMG" -run_qemu_img info "$TEST_IMG" +_img_info --format-specific run_qemu_img amend -f $IMGFMT -o size=4M,size=148M "$TEST_IMG" _img_info diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out index 0a3ab5ac90..5adfd08f9b 100644 --- a/tests/qemu-iotests/082.out +++ b/tests/qemu-iotests/082.out @@ -11,12 +11,9 @@ cluster_size: 65536 Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=4096 lazy_refcounts=on - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 16K cluster_size: 4096 Format specific information: compat: 1.1 @@ -25,12 +22,9 @@ Format specific information: Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=on - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 28K cluster_size: 8192 Format specific information: compat: 1.1 @@ -189,12 +183,9 @@ virtual size: 128M (134217728 bytes) cluster_size: 65536 Testing: convert -O qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base - -Testing: info TEST_DIR/t.qcow2.base -image: TEST_DIR/t.qcow2.base -file format: qcow2 +image: TEST_DIR/t.IMGFMT.base +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 16K cluster_size: 4096 Format specific information: compat: 1.1 @@ -202,12 +193,9 @@ Format specific information: corrupt: false Testing: convert -O qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base - -Testing: info TEST_DIR/t.qcow2.base -image: TEST_DIR/t.qcow2.base -file format: qcow2 +image: TEST_DIR/t.IMGFMT.base +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 28K cluster_size: 8192 Format specific information: compat: 1.1 @@ -351,12 +339,9 @@ size Virtual disk size === amend: Options specified more than once === Testing: amend -f foo -f qcow2 -o lazy_refcounts=on TEST_DIR/t.qcow2 - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 128M (134217728 bytes) -disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 @@ -364,12 +349,9 @@ Format specific information: corrupt: false Testing: amend -f qcow2 -o size=130M -o lazy_refcounts=off TEST_DIR/t.qcow2 - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 130M (136314880 bytes) -disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 @@ -377,12 +359,9 @@ Format specific information: corrupt: false Testing: amend -f qcow2 -o size=8M -o lazy_refcounts=on -o size=132M TEST_DIR/t.qcow2 - -Testing: info TEST_DIR/t.qcow2 -image: TEST_DIR/t.qcow2 -file format: qcow2 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT virtual size: 132M (138412032 bytes) -disk size: 196K cluster_size: 65536 Format specific information: compat: 1.1 diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089 index dffc977e1c..6f74cecde2 100755 --- a/tests/qemu-iotests/089 +++ b/tests/qemu-iotests/089 @@ -65,7 +65,8 @@ $QEMU_IO -c 'write -P 42 0 512' -c 'write -P 23 512 512' \ $QEMU_IMG convert -f raw -O $IMGFMT "$TEST_IMG.base" "$TEST_IMG" -$QEMU_IO -c 'read -P 42 0 512' -c 'read -P 23 512 512' \ +$QEMU_IO_PROG --cache $CACHEMODE \ + -c 'read -P 42 0 512' -c 'read -P 23 512 512' \ -c 'read -P 66 1024 512' "json:{ \"driver\": \"$IMGFMT\", \"file\": { @@ -91,7 +92,8 @@ $QEMU_IO -c 'write -P 42 0x38000 512' "$TEST_IMG" | _filter_qemu_io # The "image.filename" part tests whether "a": { "b": "c" } and "a.b": "c" do # the same (which they should). -$QEMU_IO -c 'read -P 42 0x38000 512' "json:{ +$QEMU_IO_PROG --cache $CACHEMODE \ + -c 'read -P 42 0x38000 512' "json:{ \"driver\": \"$IMGFMT\", \"file\": { \"driver\": \"blkdebug\", diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out index b2b0390818..bf3b8a0aae 100644 --- a/tests/qemu-iotests/089.out +++ b/tests/qemu-iotests/089.out @@ -24,6 +24,8 @@ read 512/512 bytes at offset 0 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 512/512 bytes at offset 229376 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Failed to flush the L2 table cache: Input/output error +Failed to flush the refcount block cache: Input/output error read failed: Input/output error === Testing qemu-img info output === diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099 index ffc7ea795a..948afff28b 100755 --- a/tests/qemu-iotests/099 +++ b/tests/qemu-iotests/099 @@ -44,7 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow qcow2 qed vdi vhdx vmdk vpc _supported_proto file _supported_os Linux - +_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \ + "subformat=twoGbMaxExtentSparse" function do_run_qemu() { @@ -107,8 +108,21 @@ echo # generate a JSON object here as well test_qemu "file.driver=blkverify,file.raw.filename=$TEST_IMG.compare,file.test.file.driver=blkdebug,file.test.file.image.filename=$TEST_IMG,file.test.file.inject-error.0.event=l1_update" +echo +echo '=== Testing plain filename for blkdebug ===' +echo -rm -f "$TEST_IMG.compare" +touch "$TEST_DIR/blkdebug.conf" +test_qemu "file.driver=blkdebug,file.config=$TEST_DIR/blkdebug.conf,file.image.filename=$TEST_IMG" + +echo +echo '=== Testing plain filename for blkdebug without configuration file ===' +echo + +test_qemu "file.driver=blkdebug,file.image.filename=$TEST_IMG" + + +rm -f "$TEST_IMG.compare" "$TEST_DIR/blkdebug.conf" # success, all done echo "*** done" diff --git a/tests/qemu-iotests/099.out b/tests/qemu-iotests/099.out index 55be4d4c56..2fa06ff3a0 100644 --- a/tests/qemu-iotests/099.out +++ b/tests/qemu-iotests/099.out @@ -12,9 +12,17 @@ blkverify:TEST_DIR/t.IMGFMT.compare:TEST_DIR/t.IMGFMT === Testing JSON filename for blkdebug === -json:{"driver": "IMGFMT", "file": {"inject-error": [{"immediately": false, "once": false, "state": 0, "sector": -1, "event": "l1_update", "errno": 5}], "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug"}} +json:{"driver": "IMGFMT", "file": {"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "l1_update"}} === Testing indirectly enforced JSON filename === -json:{"driver": "raw", "file": {"test": {"driver": "IMGFMT", "file": {"inject-error": [{"immediately": false, "once": false, "state": 0, "sector": -1, "event": "l1_update", "errno": 5}], "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug"}}, "driver": "blkverify", "raw": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.compare"}}} +json:{"driver": "raw", "file": {"test": {"driver": "IMGFMT", "file": {"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "l1_update"}}, "driver": "blkverify", "raw": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.compare"}}} + +=== Testing plain filename for blkdebug === + +blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT + +=== Testing plain filename for blkdebug without configuration file === + +blkdebug::TEST_DIR/t.IMGFMT *** done diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109 new file mode 100755 index 0000000000..0b668da850 --- /dev/null +++ b/tests/qemu-iotests/109 @@ -0,0 +1,132 @@ +#!/bin/bash +# +# Test writing image headers of other formats into raw images +# +# 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() +{ + rm -f $TEST_IMG.src + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.qemu + +_supported_fmt raw +_supported_proto file +_supported_os Linux + +qemu_comm_method=qmp + +function run_qemu() +{ + local raw_img="$1" + local source_img="$2" + local qmp_format="$3" + local qmp_event="$4" + + _launch_qemu -drive file="${source_img}",format=raw,cache=${CACHEMODE},id=src + _send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" "return" + + _send_qemu_cmd $QEMU_HANDLE \ + "{'execute':'drive-mirror', 'arguments':{ + 'device': 'src', 'target': '$raw_img', $qmp_format + 'mode': 'existing', 'sync': 'full'}}" \ + "return" + + _send_qemu_cmd $QEMU_HANDLE '' "$qmp_event" + _send_qemu_cmd $QEMU_HANDLE '{"execute":"query-block-jobs"}' "return" + _cleanup_qemu +} + +for fmt in qcow qcow2 qed vdi vmdk vpc; do + + echo + echo "=== Writing a $fmt header into raw ===" + echo + + _make_test_img 64M + TEST_IMG="$TEST_IMG.src" IMGFMT=$fmt _make_test_img 64M + + # This first test should fail: The image format was probed, we may not + # write an image header at the start of the image + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" + $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io + + + # When raw was explicitly specified, the same must succeed + run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" + +done + + +for sample_img in empty.bochs iotest-dirtylog-10G-4M.vhdx parallels-v1 \ + simple-pattern.cloop; do + + echo + echo "=== Copying sample image $sample_img into raw ===" + echo + + # Can't use _use_sample_img because that isn't designed to be used multiple + # times and it overwrites $TEST_IMG (both breaks cleanup) + _make_test_img 64M + bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src" + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" + $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY" + # qemu-img compare can't handle unaligned file sizes + $QEMU_IMG resize -f raw "$TEST_IMG.src" +0 + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" +done + +echo +echo "=== Write legitimate MBR into raw ===" +echo + +for sample_img in grub_mbr.raw; do + _make_test_img 64M + bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src" + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" + + run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY" + $QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src" +done + + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out new file mode 100644 index 0000000000..7db92c9ce8 --- /dev/null +++ b/tests/qemu-iotests/109.out @@ -0,0 +1,231 @@ +QA output created by 109 + +=== Writing a qcow header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 1024, "offset": 1024, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a qcow2 header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 197120, "offset": 197120, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a qed header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 327680, "offset": 327680, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a vdi header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 1024, "offset": 1024, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a vmdk header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Writing a vpc header into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. + +=== Copying sample image empty.bochs into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Image resized. +Warning: Image size mismatch! +Images are identical. + +=== Copying sample image iotest-dirtylog-10G-4M.vhdx into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 31457280, "offset": 31457280, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Image resized. +Warning: Image size mismatch! +Images are identical. + +=== Copying sample image parallels-v1 into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 327680, "offset": 327680, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Image resized. +Warning: Image size mismatch! +Images are identical. + +=== Copying sample image simple-pattern.cloop into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"return": []} +read 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2048, "offset": 2048, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Image resized. +Warning: Image size mismatch! +Images are identical. + +=== Write legitimate MBR into raw === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +{"return": {}} +WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. +Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. +Specify the 'raw' format explicitly to remove the restrictions. +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 512, "offset": 512, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. +{"return": {}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} +{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 512, "offset": 512, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} +Warning: Image size mismatch! +Images are identical. +*** done diff --git a/tests/qemu-iotests/113 b/tests/qemu-iotests/113 new file mode 100755 index 0000000000..a2cd96b176 --- /dev/null +++ b/tests/qemu-iotests/113 @@ -0,0 +1,76 @@ +#!/bin/bash +# +# Test case for accessing creation options on image formats and +# protocols not supporting image creation +# +# 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=mreitz@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 + +# We can only test one format here because we need its sample file +_supported_fmt bochs +_supported_proto nbd +_supported_os Linux + +echo +echo '=== Unsupported image creation in qemu-img create ===' +echo + +$QEMU_IMG create -f $IMGFMT nbd://example.com 2>&1 64M | _filter_imgfmt + +echo +echo '=== Unsupported image creation in qemu-img convert ===' +echo + +# We could use any input image format here, but this is a bochs test, so just +# use the bochs image +_use_sample_img empty.bochs.bz2 +$QEMU_IMG convert -f $IMGFMT -O $IMGFMT "$TEST_IMG" nbd://example.com 2>&1 \ + | _filter_imgfmt + +echo +echo '=== Unsupported format in qemu-img amend ===' +echo + +# The protocol does not matter here +_use_sample_img empty.bochs.bz2 +$QEMU_IMG amend -f $IMGFMT -o foo=bar "$TEST_IMG" 2>&1 | _filter_imgfmt + + +# success, all done +echo +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/113.out b/tests/qemu-iotests/113.out new file mode 100644 index 0000000000..00bdfd6887 --- /dev/null +++ b/tests/qemu-iotests/113.out @@ -0,0 +1,15 @@ +QA output created by 113 + +=== Unsupported image creation in qemu-img create === + +qemu-img: nbd://example.com: Format driver 'IMGFMT' does not support image creation + +=== Unsupported image creation in qemu-img convert === + +qemu-img: Format driver 'IMGFMT' does not support image creation + +=== Unsupported format in qemu-img amend === + +qemu-img: Format driver 'IMGFMT' does not support any options to amend + +*** done diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114 new file mode 100755 index 0000000000..d02e7ffbe3 --- /dev/null +++ b/tests/qemu-iotests/114 @@ -0,0 +1,61 @@ +#!/bin/bash +# +# Test invalid backing file format in qcow2 images +# +# 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 generic +_supported_os Linux + + +TEST_IMG="$TEST_IMG.base" _make_test_img 64M +_make_test_img -b "$TEST_IMG.base" 64M + +# Set an invalid backing file format +$PYTHON qcow2.py "$TEST_IMG" add-header-ext 0xE2792ACA "foo" +_img_info + +# Try opening the image. Should fail (and not probe) in the first case, but +# overriding the backing file format should be possible. +$QEMU_IO -c "open $TEST_IMG" -c "read 0 4k" 2>&1 | _filter_qemu_io | _filter_testdir +$QEMU_IO -c "open -o backing.driver=$IMGFMT $TEST_IMG" -c "read 0 4k" | _filter_qemu_io + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/114.out b/tests/qemu-iotests/114.out new file mode 100644 index 0000000000..6c6b21085a --- /dev/null +++ b/tests/qemu-iotests/114.out @@ -0,0 +1,13 @@ +QA output created by 114 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 64M (67108864 bytes) +cluster_size: 65536 +backing file: TEST_DIR/t.IMGFMT.base +backing file format: foo +qemu-io: can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknown driver 'foo' +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index 9e12bec2bf..1e556bbb7d 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -289,10 +289,10 @@ testlist options if [ ! -z "$DISPLAY" ] then - which xdiff >/dev/null 2>&1 && diff=xdiff - which gdiff >/dev/null 2>&1 && diff=gdiff - which tkdiff >/dev/null 2>&1 && diff=tkdiff - which xxdiff >/dev/null 2>&1 && diff=xxdiff + command -v xdiff >/dev/null 2>&1 && diff=xdiff + command -v gdiff >/dev/null 2>&1 && diff=gdiff + command -v tkdiff >/dev/null 2>&1 && diff=tkdiff + command -v xxdiff >/dev/null 2>&1 && diff=xxdiff fi ;; @@ -391,7 +391,7 @@ BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \ done # Set qemu-io cache mode with $CACHEMODE we have -QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE" +QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE" # Set default options for qemu-img create -o if they were not specified _set_default_imgopts diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config index bd6790be63..91a5ef696b 100644 --- a/tests/qemu-iotests/common.config +++ b/tests/qemu-iotests/common.config @@ -47,7 +47,7 @@ export PWD=`pwd` # $1 = prog to look for, $2* = default pathnames if not found in $PATH set_prog_path() { - p=`which $1 2> /dev/null` + p=`command -v $1 2> /dev/null` if [ -n "$p" -a -x "$p" ]; then echo $p return 0 diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index 3acdb307f4..dfb9726f6c 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -167,7 +167,9 @@ _filter_qmp() { _filter_win32 | \ sed -e 's#\("\(micro\)\?seconds": \)[0-9]\+#\1 TIMESTAMP#g' \ - -e 's#^{"QMP":.*}$#QMP_VERSION#' + -e 's#^{"QMP":.*}$#QMP_VERSION#' \ + -e '/^ "QMP": {\s*$/, /^ }\s*$/ c\' \ + -e ' QMP_VERSION' } # replace driver-specific options in the "Formatting..." line diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu index ee7ebb4c1d..8e618b5149 100644 --- a/tests/qemu-iotests/common.qemu +++ b/tests/qemu-iotests/common.qemu @@ -153,8 +153,9 @@ function _launch_qemu() mkfifo "${fifo_out}" mkfifo "${fifo_in}" - "${QEMU}" -nographic -serial none ${comm} -machine accel=qtest "${@}" 2>&1 \ + "${QEMU}" -nographic -serial none ${comm} -machine accel=qtest "${@}" \ >"${fifo_out}" \ + 2>&1 \ <"${fifo_in}" & QEMU_PID[${_QEMU_HANDLE}]=$! diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 9c49deb3dd..3b14053790 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -175,7 +175,9 @@ _cleanup_test_img() case "$IMGPROTO" in nbd) - kill $QEMU_NBD_PID + if [ -n "$QEMU_NBD_PID" ]; then + kill $QEMU_NBD_PID + fi rm -f "$TEST_IMG_FILE" ;; file) @@ -213,6 +215,13 @@ _check_test_img() _img_info() { + if [[ "$1" == "--format-specific" ]]; then + local format_specific=1 + shift + else + local format_specific=0 + fi + discard=0 regex_json_spec_start='^ *"format-specific": \{' $QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \ @@ -222,7 +231,9 @@ _img_info() -e "/^disk size:/ D" \ -e "/actual-size/ D" | \ while IFS='' read line; do - if [[ $line == "Format specific information:" ]]; then + if [[ $format_specific == 1 ]]; then + discard=0 + elif [[ $line == "Format specific information:" ]]; then discard=1 elif [[ $line =~ $regex_json_spec_start ]]; then discard=2 diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 7dfe46940a..a4742c6d01 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -111,4 +111,7 @@ 105 rw auto quick 107 rw auto quick 108 rw auto quick +109 rw auto 111 rw auto quick +113 rw auto quick +114 rw auto quick diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index 2058596964..9cc4cf7d08 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -7,6 +7,10 @@ import string class QcowHeaderExtension: def __init__(self, magic, length, data): + if length % 8 != 0: + padding = 8 - (length % 8) + data += "\0" * padding + self.magic = magic self.length = length self.data = data diff --git a/tests/qemu-iotests/sample_images/grub_mbr.raw.bz2 b/tests/qemu-iotests/sample_images/grub_mbr.raw.bz2 new file mode 100644 index 0000000000..8585878bcd Binary files /dev/null and b/tests/qemu-iotests/sample_images/grub_mbr.raw.bz2 differ diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index 8cf2c5bcaa..6d631cf366 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -87,7 +87,7 @@ int main(int argc, char **argv) qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug); qtest_start("-device piix3-usb-uhci,id=uhci,addr=1d.0" - " -drive id=drive0,if=none,file=/dev/null" + " -drive id=drive0,if=none,file=/dev/null,format=raw" " -device usb-tablet,bus=uhci.0,port=1"); ret = g_test_run(); qtest_end(); diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c index b1a7dec5bb..adf261e963 100644 --- a/tests/usb-hcd-xhci-test.c +++ b/tests/usb-hcd-xhci-test.c @@ -91,7 +91,7 @@ int main(int argc, char **argv) qtest_add_func("/xhci/pci/hotplug/usb-uas", test_usb_uas_hotplug); qtest_start("-device nec-usb-xhci,id=xhci" - " -drive id=drive0,if=none,file=/dev/null"); + " -drive id=drive0,if=none,file=/dev/null,format=raw"); ret = g_test_run(); qtest_end(); diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index ead3911e28..89d7cbf919 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -68,8 +68,8 @@ static QPCIBus *test_start(void) g_assert_cmpint(ret, ==, 0); close(fd); - cmdline = g_strdup_printf("-drive if=none,id=drive0,file=%s " - "-drive if=none,id=drive1,file=/dev/null " + cmdline = g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw " + "-drive if=none,id=drive1,file=/dev/null,format=raw " "-device virtio-blk-pci,id=drv0,drive=drive0," "addr=%x.%x", tmp_path, PCI_SLOT, PCI_FN); diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c index 41f9602e44..989f8251c4 100644 --- a/tests/virtio-scsi-test.c +++ b/tests/virtio-scsi-test.c @@ -52,8 +52,8 @@ int main(int argc, char **argv) qtest_add_func("/virtio/scsi/pci/nop", pci_nop); qtest_add_func("/virtio/scsi/pci/hotplug", hotplug); - qtest_start("-drive id=drv0,if=none,file=/dev/null " - "-drive id=drv1,if=none,file=/dev/null " + qtest_start("-drive id=drv0,if=none,file=/dev/null,format=raw " + "-drive id=drv1,if=none,file=/dev/null,format=raw " "-device virtio-scsi-pci,id=vscsi0 " "-device scsi-hd,bus=vscsi0.0,drive=drv0"); ret = g_test_run(); diff --git a/vl.c b/vl.c index eb89d62906..f1a5d66cb6 100644 --- a/vl.c +++ b/vl.c @@ -2284,7 +2284,7 @@ static int mon_init_func(QemuOpts *opts, void *opaque) return 0; } -static void monitor_parse(const char *optarg, const char *mode) +static void monitor_parse(const char *optarg, const char *mode, bool pretty) { static int monitor_device_index = 0; QemuOpts *opts; @@ -2314,6 +2314,7 @@ static void monitor_parse(const char *optarg, const char *mode) } qemu_opt_set(opts, "mode", mode); qemu_opt_set(opts, "chardev", label); + qemu_opt_set_bool(opts, "pretty", pretty); if (def) qemu_opt_set(opts, "default", "on"); monitor_device_index++; @@ -3292,11 +3293,15 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_monitor: default_monitor = 0; if (strncmp(optarg, "none", 4)) { - monitor_parse(optarg, "readline"); + monitor_parse(optarg, "readline", false); } break; case QEMU_OPTION_qmp: - monitor_parse(optarg, "control"); + monitor_parse(optarg, "control", false); + default_monitor = 0; + break; + case QEMU_OPTION_qmp_pretty: + monitor_parse(optarg, "control", true); default_monitor = 0; break; case QEMU_OPTION_mon: @@ -3994,7 +3999,7 @@ int main(int argc, char **argv, char **envp) add_device_config(DEV_SCLP, "stdio"); } if (default_monitor) - monitor_parse("stdio", "readline"); + monitor_parse("stdio", "readline", false); } } else { if (default_serial) @@ -4002,7 +4007,7 @@ int main(int argc, char **argv, char **envp) if (default_parallel) add_device_config(DEV_PARALLEL, "vc:80Cx24C"); if (default_monitor) - monitor_parse("vc:80Cx24C", "readline"); + monitor_parse("vc:80Cx24C", "readline", false); if (default_virtcon) add_device_config(DEV_VIRTCON, "vc:80Cx24C"); if (default_sclp) {