diff options
44 files changed, 285 insertions, 91 deletions
diff --git a/block.c b/block.c index cccae5add9..af3faf664e 100644 --- a/block.c +++ b/block.c @@ -483,7 +483,8 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque) CreateCo *cco = opaque; assert(cco->drv); - ret = cco->drv->bdrv_co_create_opts(cco->filename, cco->opts, &local_err); + ret = cco->drv->bdrv_co_create_opts(cco->drv, + cco->filename, cco->opts, &local_err); error_propagate(&cco->err, local_err); cco->ret = ret; } @@ -597,8 +598,15 @@ static int create_file_fallback_zero_first_sector(BlockBackend *blk, return 0; } -static int bdrv_create_file_fallback(const char *filename, BlockDriver *drv, - QemuOpts *opts, Error **errp) +/** + * Simple implementation of bdrv_co_create_opts for protocol drivers + * which only support creation via opening a file + * (usually existing raw storage device) + */ +int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv, + const char *filename, + QemuOpts *opts, + Error **errp) { BlockBackend *blk; QDict *options; @@ -662,11 +670,7 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp) return -ENOENT; } - if (drv->bdrv_co_create_opts) { - return bdrv_create(drv, filename, opts, errp); - } else { - return bdrv_create_file_fallback(filename, drv, opts, errp); - } + return bdrv_create(drv, filename, opts, errp); } int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) @@ -1591,9 +1595,9 @@ QemuOptsList bdrv_runtime_opts = { }, }; -static QemuOptsList fallback_create_opts = { - .name = "fallback-create-opts", - .head = QTAILQ_HEAD_INITIALIZER(fallback_create_opts.head), +QemuOptsList bdrv_create_opts_simple = { + .name = "simple-create-opts", + .head = QTAILQ_HEAD_INITIALIZER(bdrv_create_opts_simple.head), .desc = { { .name = BLOCK_OPT_SIZE, @@ -5962,13 +5966,15 @@ void bdrv_img_create(const char *filename, const char *fmt, return; } + if (!proto_drv->create_opts) { + error_setg(errp, "Protocol driver '%s' does not support image creation", + proto_drv->format_name); + return; + } + /* Create parameter list */ create_opts = qemu_opts_append(create_opts, drv->create_opts); - if (proto_drv->create_opts) { - create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); - } else { - create_opts = qemu_opts_append(create_opts, &fallback_create_opts); - } + create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); diff --git a/block/crypto.c b/block/crypto.c index 4425ebeb47..d577f89659 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -601,7 +601,8 @@ fail: return ret; } -static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename, +static int coroutine_fn block_crypto_co_create_opts_luks(BlockDriver *drv, + const char *filename, QemuOpts *opts, Error **errp) { diff --git a/block/file-posix.c b/block/file-posix.c index 9bc3838b2a..7e19bbff5f 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -2405,7 +2405,9 @@ out: return result; } -static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts, +static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions options; @@ -3511,6 +3513,8 @@ static BlockDriver bdrv_host_device = { .bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_abort = raw_reopen_abort, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, .mutable_opts = mutable_opts, .bdrv_co_invalidate_cache = raw_co_invalidate_cache, .bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes, @@ -3637,10 +3641,11 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_abort = raw_reopen_abort, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, .mutable_opts = mutable_opts, .bdrv_co_invalidate_cache = raw_co_invalidate_cache, - .bdrv_co_preadv = raw_co_preadv, .bdrv_co_pwritev = raw_co_pwritev, .bdrv_co_flush_to_disk = raw_co_flush_to_disk, @@ -3769,6 +3774,8 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_abort = raw_reopen_abort, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, .mutable_opts = mutable_opts, .bdrv_co_preadv = raw_co_preadv, diff --git a/block/file-win32.c b/block/file-win32.c index 77e8ff7b68..15859839a1 100644 --- a/block/file-win32.c +++ b/block/file-win32.c @@ -588,7 +588,9 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp) return 0; } -static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts, +static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions options; diff --git a/block/gluster.c b/block/gluster.c index 4fa4a77a47..0aa1f2cda4 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -1130,7 +1130,8 @@ out: return ret; } -static int coroutine_fn qemu_gluster_co_create_opts(const char *filename, +static int coroutine_fn qemu_gluster_co_create_opts(BlockDriver *drv, + const char *filename, QemuOpts *opts, Error **errp) { diff --git a/block/iscsi.c b/block/iscsi.c index 682abd8e09..14680a436a 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -2399,18 +2399,6 @@ out_unlock: return r; } -static QemuOptsList iscsi_create_opts = { - .name = "iscsi-create-opts", - .head = QTAILQ_HEAD_INITIALIZER(iscsi_create_opts.head), - .desc = { - { - .name = BLOCK_OPT_SIZE, - .type = QEMU_OPT_SIZE, - .help = "Virtual disk size" - }, - { /* end of list */ } - } -}; static const char *const iscsi_strong_runtime_opts[] = { "transport", @@ -2434,6 +2422,8 @@ static BlockDriver bdrv_iscsi = { .bdrv_parse_filename = iscsi_parse_filename, .bdrv_file_open = iscsi_open, .bdrv_close = iscsi_close, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, .bdrv_reopen_prepare = iscsi_reopen_prepare, .bdrv_reopen_commit = iscsi_reopen_commit, .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, @@ -2471,6 +2461,8 @@ static BlockDriver bdrv_iser = { .bdrv_parse_filename = iscsi_parse_filename, .bdrv_file_open = iscsi_open, .bdrv_close = iscsi_close, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, .bdrv_reopen_prepare = iscsi_reopen_prepare, .bdrv_reopen_commit = iscsi_reopen_commit, .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, diff --git a/block/mirror.c b/block/mirror.c index 447051dbc6..6203e5946e 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -678,6 +678,7 @@ static int mirror_exit_common(Job *job) bdrv_set_backing_hd(target_bs, backing, &local_err); if (local_err) { error_report_err(local_err); + local_err = NULL; ret = -EPERM; } } diff --git a/block/nbd.c b/block/nbd.c index 976be76647..2160859f64 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -2038,6 +2038,8 @@ static BlockDriver bdrv_nbd = { .protocol_name = "nbd", .instance_size = sizeof(BDRVNBDState), .bdrv_parse_filename = nbd_parse_filename, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, .bdrv_file_open = nbd_open, .bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_co_preadv = nbd_client_co_preadv, @@ -2063,6 +2065,8 @@ static BlockDriver bdrv_nbd_tcp = { .protocol_name = "nbd+tcp", .instance_size = sizeof(BDRVNBDState), .bdrv_parse_filename = nbd_parse_filename, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, .bdrv_file_open = nbd_open, .bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_co_preadv = nbd_client_co_preadv, @@ -2088,6 +2092,8 @@ static BlockDriver bdrv_nbd_unix = { .protocol_name = "nbd+unix", .instance_size = sizeof(BDRVNBDState), .bdrv_parse_filename = nbd_parse_filename, + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, .bdrv_file_open = nbd_open, .bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_co_preadv = nbd_client_co_preadv, diff --git a/block/nfs.c b/block/nfs.c index 9a6311e270..cc2413d5ab 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -662,7 +662,9 @@ out: return ret; } -static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts, +static int coroutine_fn nfs_file_co_create_opts(BlockDriver *drv, + const char *url, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options; diff --git a/block/nvme.c b/block/nvme.c index d41c4bda6e..7b7c0cc5d6 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -1333,6 +1333,9 @@ static BlockDriver bdrv_nvme = { .protocol_name = "nvme", .instance_size = sizeof(BDRVNVMeState), + .bdrv_co_create_opts = bdrv_co_create_opts_simple, + .create_opts = &bdrv_create_opts_simple, + .bdrv_parse_filename = nvme_parse_filename, .bdrv_file_open = nvme_file_open, .bdrv_close = nvme_close, diff --git a/block/parallels.c b/block/parallels.c index 7a01997659..6d4ed77f16 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -609,7 +609,8 @@ exit: goto out; } -static int coroutine_fn parallels_co_create_opts(const char *filename, +static int coroutine_fn parallels_co_create_opts(BlockDriver *drv, + const char *filename, QemuOpts *opts, Error **errp) { diff --git a/block/qcow.c b/block/qcow.c index fce8989868..8973e4e565 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -934,7 +934,8 @@ exit: return ret; } -static int coroutine_fn qcow_co_create_opts(const char *filename, +static int coroutine_fn qcow_co_create_opts(BlockDriver *drv, + const char *filename, QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; diff --git a/block/qcow2.c b/block/qcow2.c index d1da3d91db..2bb536b014 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -177,7 +177,7 @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset, } -/* +/* * read qcow2 extension and fill bs * start reading from start_offset * finish reading upon magic of value 0 or when end_offset reached @@ -2823,9 +2823,16 @@ int qcow2_update_header(BlockDriverState *bs) buflen -= ret; } - /* Feature table */ - if (s->qcow_version >= 3) { - Qcow2Feature features[] = { + /* + * Feature table. A mere 8 feature names occupies 392 bytes, and + * when coupled with the v3 minimum header of 104 bytes plus the + * 8-byte end-of-extension marker, that would leave only 8 bytes + * for a backing file name in an image with 512-byte clusters. + * Thus, we choose to omit this header for cluster sizes 4k and + * smaller. + */ + if (s->qcow_version >= 3 && s->cluster_size > 4096) { + static const Qcow2Feature features[] = { { .type = QCOW2_FEAT_TYPE_INCOMPATIBLE, .bit = QCOW2_INCOMPAT_DIRTY_BITNR, @@ -2846,6 +2853,16 @@ int qcow2_update_header(BlockDriverState *bs) .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, .name = "lazy refcounts", }, + { + .type = QCOW2_FEAT_TYPE_AUTOCLEAR, + .bit = QCOW2_AUTOCLEAR_BITMAPS_BITNR, + .name = "bitmaps", + }, + { + .type = QCOW2_FEAT_TYPE_AUTOCLEAR, + .bit = QCOW2_AUTOCLEAR_DATA_FILE_RAW_BITNR, + .name = "raw external data", + }, }; ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE, @@ -3255,7 +3272,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) * inconsistency later. * * We do need a refcount table because growing the refcount table means - * allocating two new refcount blocks - the seconds of which would be at + * allocating two new refcount blocks - the second of which would be at * 2 GB for 64k clusters, and we don't want to have a 2 GB initial file * size for any qcow2 image. */ @@ -3500,7 +3517,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) goto out; } - /* Want a backing file? There you go.*/ + /* Want a backing file? There you go. */ if (qcow2_opts->has_backing_file) { const char *backing_format = NULL; @@ -3558,7 +3575,9 @@ out: return ret; } -static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opts, +static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; diff --git a/block/qed.c b/block/qed.c index d8c4e5fb1e..1af9b3cb1d 100644 --- a/block/qed.c +++ b/block/qed.c @@ -720,7 +720,8 @@ out: return ret; } -static int coroutine_fn bdrv_qed_co_create_opts(const char *filename, +static int coroutine_fn bdrv_qed_co_create_opts(BlockDriver *drv, + const char *filename, QemuOpts *opts, Error **errp) { diff --git a/block/raw-format.c b/block/raw-format.c index 3a76ec7dd2..93b25e1b6b 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -419,7 +419,9 @@ static int raw_has_zero_init_truncate(BlockDriverState *bs) return bdrv_has_zero_init_truncate(bs->file->bs); } -static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts, +static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, Error **errp) { return bdrv_create_file(filename, opts, errp); diff --git a/block/rbd.c b/block/rbd.c index 84115d34b4..e637639a07 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -437,7 +437,8 @@ static int qemu_rbd_co_create(BlockdevCreateOptions *options, Error **errp) return qemu_rbd_do_create(options, NULL, NULL, errp); } -static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, +static int coroutine_fn qemu_rbd_co_create_opts(BlockDriver *drv, + const char *filename, QemuOpts *opts, Error **errp) { diff --git a/block/sheepdog.c b/block/sheepdog.c index cfa84338a2..59f7ebb171 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -2157,7 +2157,9 @@ out: return ret; } -static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts, +static int coroutine_fn sd_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options = NULL; @@ -3269,6 +3271,7 @@ static BlockDriver bdrv_sheepdog_tcp = { .bdrv_co_create = sd_co_create, .bdrv_co_create_opts = sd_co_create_opts, .bdrv_has_zero_init = bdrv_has_zero_init_1, + .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, .bdrv_getlength = sd_getlength, .bdrv_get_allocated_file_size = sd_get_allocated_file_size, .bdrv_co_truncate = sd_co_truncate, @@ -3307,6 +3310,7 @@ static BlockDriver bdrv_sheepdog_unix = { .bdrv_co_create = sd_co_create, .bdrv_co_create_opts = sd_co_create_opts, .bdrv_has_zero_init = bdrv_has_zero_init_1, + .bdrv_has_zero_init_truncate = bdrv_has_zero_init_1, .bdrv_getlength = sd_getlength, .bdrv_get_allocated_file_size = sd_get_allocated_file_size, .bdrv_co_truncate = sd_co_truncate, diff --git a/block/ssh.c b/block/ssh.c index b4375cf7d2..84e92821c0 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -963,7 +963,9 @@ fail: return ret; } -static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts, +static int coroutine_fn ssh_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options; diff --git a/block/vdi.c b/block/vdi.c index 0142da7233..e1a11f2aa0 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -896,7 +896,9 @@ static int coroutine_fn vdi_co_create(BlockdevCreateOptions *create_options, return vdi_co_do_create(create_options, DEFAULT_CLUSTER_SIZE, errp); } -static int coroutine_fn vdi_co_create_opts(const char *filename, QemuOpts *opts, +static int coroutine_fn vdi_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, Error **errp) { QDict *qdict = NULL; diff --git a/block/vhdx.c b/block/vhdx.c index f02d2611be..33e57cd656 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -2046,7 +2046,8 @@ delete_and_exit: return ret; } -static int coroutine_fn vhdx_co_create_opts(const char *filename, +static int coroutine_fn vhdx_co_create_opts(BlockDriver *drv, + const char *filename, QemuOpts *opts, Error **errp) { diff --git a/block/vmdk.c b/block/vmdk.c index 8466051bc9..218d9c9800 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -2588,7 +2588,9 @@ exit: return blk; } -static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts, +static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, Error **errp) { Error *local_err = NULL; diff --git a/block/vpc.c b/block/vpc.c index a65550298e..6df75e22dc 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -1089,8 +1089,10 @@ out: return ret; } -static int coroutine_fn vpc_co_create_opts(const char *filename, - QemuOpts *opts, Error **errp) +static int coroutine_fn vpc_co_create_opts(BlockDriver *drv, + const char *filename, + QemuOpts *opts, + Error **errp) { BlockdevCreateOptions *create_options = NULL; QDict *qdict; diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt index 5597e24474..640e0eca40 100644 --- a/docs/interop/qcow2.txt +++ b/docs/interop/qcow2.txt @@ -143,7 +143,8 @@ the next fields through header_length. bit is unset, the bitmaps extension data must be considered inconsistent. - Bit 1: If this bit is set, the external data file can + Bit 1: Raw external data bit + If this bit is set, the external data file can be read as a consistent standalone raw image without looking at the qcow2 metadata. diff --git a/docs/xbzrle.txt b/docs/xbzrle.txt index c0a7dfd44c..b431bdaf0f 100644 --- a/docs/xbzrle.txt +++ b/docs/xbzrle.txt @@ -92,6 +92,11 @@ Usage power of 2. The cache default value is 64MBytes. (on source only) {qemu} migrate_set_cache_size 256m +Commit 73af8dd8d7 "migration: Make xbzrle_cache_size a migration parameter" +(v2.11.0) deprecated migrate-set-cache-size, therefore, the new parameter +is recommended. + {qemu} migrate_set_parameter xbzrle-cache-size 256m + 4. Start outgoing migration {qemu} migrate -d tcp:destination.host:4444 {qemu} info migrate @@ -108,7 +113,7 @@ power of 2. The cache default value is 64MBytes. (on source only) xbzrle transferred: I kbytes xbzrle pages: J pages xbzrle cache miss: K - xbzrle overflow : L + xbzrle overflow: L xbzrle cache-miss: the number of cache misses to date - high cache-miss rate indicates that the cache size is set too low. diff --git a/hw/audio/fmopl.c b/hw/audio/fmopl.c index 356d4dfbca..8a71a569fa 100644 --- a/hw/audio/fmopl.c +++ b/hw/audio/fmopl.c @@ -627,6 +627,7 @@ static int OPLOpenTable( void ) free(AMS_TABLE); return 0; } + ENV_CURVE = g_new(int32_t, 2 * EG_ENT + 1); /* make total level table */ for (t = 0;t < EG_ENT-1 ;t++){ rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20); /* dB -> voltage */ @@ -694,6 +695,7 @@ static int OPLOpenTable( void ) static void OPLCloseTable( void ) { + g_free(ENV_CURVE); free(TL_TABLE); free(SIN_TABLE); free(AMS_TABLE); @@ -1090,7 +1092,6 @@ FM_OPL *OPLCreate(int clock, int rate) OPL->clock = clock; OPL->rate = rate; OPL->max_ch = max_ch; - ENV_CURVE = g_new(int32_t, 2 * EG_ENT + 1); /* init grobal tables */ OPL_initialize(OPL); /* reset chip */ @@ -1128,7 +1129,6 @@ void OPLDestroy(FM_OPL *OPL) #endif OPL_UnLockTable(); free(OPL); - g_free(ENV_CURVE); } /* ---------- Option handlers ---------- */ diff --git a/include/block/block.h b/include/block/block.h index e569a4d747..b05995fe9c 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -283,6 +283,7 @@ BlockDriver *bdrv_find_format(const char *format_name); int bdrv_create(BlockDriver *drv, const char* filename, QemuOpts *opts, Error **errp); int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp); + BlockDriverState *bdrv_new(void); void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, Error **errp); diff --git a/include/block/block_int.h b/include/block/block_int.h index ae9c4da4d0..4c3587ea19 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -135,7 +135,8 @@ struct BlockDriver { void (*bdrv_close)(BlockDriverState *bs); int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts, Error **errp); - int coroutine_fn (*bdrv_co_create_opts)(const char *filename, + int coroutine_fn (*bdrv_co_create_opts)(BlockDriver *drv, + const char *filename, QemuOpts *opts, Error **errp); int (*bdrv_make_empty)(BlockDriverState *bs); @@ -1330,4 +1331,15 @@ int refresh_total_sectors(BlockDriverState *bs, int64_t hint); void bdrv_set_monitor_owned(BlockDriverState *bs); BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp); +/** + * Simple implementation of bdrv_co_create_opts for protocol drivers + * which only support creation via opening a file + * (usually existing raw storage device) + */ +int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv, + const char *filename, + QemuOpts *opts, + Error **errp); +extern QemuOptsList bdrv_create_opts_simple; + #endif /* BLOCK_INT_H */ diff --git a/migration/colo.c b/migration/colo.c index 44942c4e23..a54ac84f41 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -93,6 +93,7 @@ static void secondary_vm_do_failover(void) replication_stop_all(true, &local_err); if (local_err) { error_report_err(local_err); + local_err = NULL; } /* Notify all filters of all NIC to do checkpoint */ diff --git a/migration/migration.c b/migration/migration.c index c1d88ace7f..c4c9aee15e 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -790,7 +790,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) params->has_tls_hostname = true; params->tls_hostname = g_strdup(s->parameters.tls_hostname); params->has_tls_authz = true; - params->tls_authz = g_strdup(s->parameters.tls_authz); + params->tls_authz = g_strdup(s->parameters.tls_authz ? + s->parameters.tls_authz : ""); params->has_max_bandwidth = true; params->max_bandwidth = s->parameters.max_bandwidth; params->has_downtime_limit = true; @@ -1243,7 +1244,7 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "xbzrle_cache_size", "is invalid, it should be bigger than target page size" - " and a power of two"); + " and a power of 2"); return false; } diff --git a/migration/ram.c b/migration/ram.c index c12cfdbe26..04f13feb2e 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -980,6 +980,7 @@ static void migration_bitmap_sync_precopy(RAMState *rs) */ if (precopy_notify(PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC, &local_err)) { error_report_err(local_err); + local_err = NULL; } migration_bitmap_sync(rs); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 58724031ea..9b94e67879 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -303,7 +303,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) info->xbzrle_cache->cache_miss); monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n", info->xbzrle_cache->cache_miss_rate); - monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n", + monitor_printf(mon, "xbzrle overflow: %" PRIu64 "\n", info->xbzrle_cache->overflow); } @@ -459,9 +459,9 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) monitor_printf(mon, "%s: %" PRIu64 "\n", MigrationParameter_str(MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH), params->max_postcopy_bandwidth); - monitor_printf(mon, " %s: '%s'\n", + monitor_printf(mon, "%s: '%s'\n", MigrationParameter_str(MIGRATION_PARAMETER_TLS_AUTHZ), - params->has_tls_authz ? params->tls_authz : ""); + params->tls_authz); } qapi_free_MigrationParameters(params); @@ -527,10 +527,11 @@ static void hmp_info_vnc_servers(Monitor *mon, VncServerInfo2List *server) void hmp_info_vnc(Monitor *mon, const QDict *qdict) { - VncInfo2List *info2l; + VncInfo2List *info2l, *info2l_head; Error *err = NULL; info2l = qmp_query_vnc_servers(&err); + info2l_head = info2l; if (err) { hmp_handle_error(mon, err); return; @@ -559,7 +560,7 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict) info2l = info2l->next; } - qapi_free_VncInfo2List(info2l); + qapi_free_VncInfo2List(info2l_head); } #endif @@ -1261,6 +1262,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) case MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD: p->has_throttle_trigger_threshold = true; visit_type_int(v, param, &p->throttle_trigger_threshold, &err); + break; case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL: p->has_cpu_throttle_initial = true; visit_type_int(v, param, &p->cpu_throttle_initial, &err); diff --git a/qemu-img.c b/qemu-img.c index afddf33f08..b167376bd7 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -647,9 +647,9 @@ static int collect_image_check(BlockDriverState *bs, check->leaks = result.leaks; check->has_leaks = result.leaks != 0; check->corruptions_fixed = result.corruptions_fixed; - check->has_corruptions_fixed = result.corruptions != 0; + check->has_corruptions_fixed = result.corruptions_fixed != 0; check->leaks_fixed = result.leaks_fixed; - check->has_leaks_fixed = result.leaks != 0; + check->has_leaks_fixed = result.leaks_fixed != 0; check->image_end_offset = result.image_end_offset; check->has_image_end_offset = result.image_end_offset != 0; check->total_clusters = result.bfi.total_clusters; @@ -803,9 +803,12 @@ static int img_check(int argc, char **argv) if (check->corruptions_fixed || check->leaks_fixed) { int corruptions_fixed, leaks_fixed; + bool has_leaks_fixed, has_corruptions_fixed; leaks_fixed = check->leaks_fixed; + has_leaks_fixed = check->has_leaks_fixed; corruptions_fixed = check->corruptions_fixed; + has_corruptions_fixed = check->has_corruptions_fixed; if (output_format == OFORMAT_HUMAN) { qprintf(quiet, @@ -822,7 +825,9 @@ static int img_check(int argc, char **argv) ret = collect_image_check(bs, check, filename, fmt, 0); check->leaks_fixed = leaks_fixed; + check->has_leaks_fixed = has_leaks_fixed; check->corruptions_fixed = corruptions_fixed; + check->has_corruptions_fixed = has_corruptions_fixed; } if (!ret) { diff --git a/softmmu/vl.c b/softmmu/vl.c index 1d33a28340..814537bb42 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2801,6 +2801,9 @@ static void create_default_memdev(MachineState *ms, const char *path) object_property_set_int(obj, ms->ram_size, "size", &error_fatal); object_property_add_child(object_get_objects_root(), mc->default_ram_id, obj, &error_fatal); + /* Ensure backend's memory region name is equal to mc->default_ram_id */ + object_property_set_bool(obj, false, "x-use-canonical-path-for-ramblock-id", + &error_fatal); user_creatable_complete(USER_CREATABLE(obj), &error_fatal); object_unref(obj); object_property_set_str(OBJECT(ms), mc->default_ram_id, "memory-backend", diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out index d535e407bc..46f97c5a4e 100644 --- a/tests/qemu-iotests/031.out +++ b/tests/qemu-iotests/031.out @@ -117,7 +117,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> Header extension: @@ -150,7 +150,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> Header extension: @@ -164,7 +164,7 @@ No errors were found on the image. magic 0x514649fb version 3 -backing_file_offset 0x178 +backing_file_offset 0x1d8 backing_file_size 0x17 cluster_bits 16 size 67108864 @@ -188,7 +188,7 @@ data 'host_device' Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> Header extension: diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036 index 512598421c..cf522de7a1 100755 --- a/tests/qemu-iotests/036 +++ b/tests/qemu-iotests/036 @@ -44,8 +44,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file # Only qcow2v3 and later supports feature bits; -# qcow2.py does not support external data files -_unsupported_imgopts 'compat=0.10' data_file +# qcow2.py does not support external data files; +# this test requires a cluster size large enough for the feature table +_unsupported_imgopts 'compat=0.10' data_file \ + 'cluster_size=\(512\|1024\|2048\|4096\)' echo echo === Image with unknown incompatible feature bit === diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out index 0b52b934e1..23b699ce06 100644 --- a/tests/qemu-iotests/036.out +++ b/tests/qemu-iotests/036.out @@ -26,7 +26,7 @@ compatible_features [] autoclear_features [63] Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> @@ -38,7 +38,7 @@ compatible_features [] autoclear_features [] Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> *** done diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 index 36b040491f..ce285d3084 100755 --- a/tests/qemu-iotests/061 +++ b/tests/qemu-iotests/061 @@ -44,8 +44,10 @@ _supported_os Linux # Conversion between different compat versions can only really work # with refcount_bits=16; # we have explicit tests for data_file here, but the whole test does -# not work with it -_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file +# not work with it; +# we have explicit tests for various cluster sizes, the remaining tests +# require the default 64k cluster +_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file cluster_size echo echo "=== Testing version downgrade with zero expansion ===" diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out index 8b3091a412..413cc4e0f4 100644 --- a/tests/qemu-iotests/061.out +++ b/tests/qemu-iotests/061.out @@ -26,7 +26,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> magic 0x514649fb @@ -84,7 +84,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> magic 0x514649fb @@ -140,7 +140,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> ERROR cluster 5 refcount=0 reference=1 @@ -195,7 +195,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> magic 0x514649fb @@ -264,7 +264,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> read 65536/65536 bytes at offset 44040192 @@ -298,7 +298,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> ERROR cluster 5 refcount=0 reference=1 @@ -327,7 +327,7 @@ header_length 104 Header extension: magic 0x6803f857 -length 192 +length 288 data <binary> read 131072/131072 bytes at offset 0 diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138 index 54b01046ad..1d5b0bed6d 100755 --- a/tests/qemu-iotests/138 +++ b/tests/qemu-iotests/138 @@ -41,8 +41,10 @@ _supported_fmt qcow2 _supported_proto file _supported_os Linux # With an external data file, data clusters are not refcounted -# (and so qemu-img check does not check their refcount) -_unsupported_imgopts data_file +# (so qemu-img check would not do much); +# we want to modify the refcounts, so we need them to have a specific +# format (namely u16) +_unsupported_imgopts data_file 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' echo echo '=== Check on an image with a multiple of 2^32 clusters ===' @@ -65,6 +67,41 @@ poke_file "$TEST_IMG" $((2048 + 8)) "\x00\x80\x00\x00\x00\x00\x00\x00" # allocate memory", we have an error showing that l2 entry is invalid. _check_test_img +echo +echo '=== Check leaks-fixed/corruptions-fixed report' +echo + +# After leaks and corruptions were fixed, those numbers should be +# reported by qemu-img check +_make_test_img 64k + +# Allocate data cluster +$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io + +reftable_ofs=$(peek_file_be "$TEST_IMG" 48 8) +refblock_ofs=$(peek_file_be "$TEST_IMG" $reftable_ofs 8) + +# Introduce a leak: Make the image header's refcount 2 +poke_file_be "$TEST_IMG" "$refblock_ofs" 2 2 + +l1_ofs=$(peek_file_be "$TEST_IMG" 40 8) + +# Introduce a corruption: Drop the COPIED flag from the (first) L1 entry +l1_entry=$(peek_file_be "$TEST_IMG" $l1_ofs 8) +l1_entry=$((l1_entry & ~(1 << 63))) +poke_file_be "$TEST_IMG" $l1_ofs 8 $l1_entry + +echo +# Should print the number of corruptions and leaks fixed +# (Filter out all JSON fields (recognizable by their four-space +# indentation), but keep the "-fixed" fields (by removing two spaces +# from their indentation)) +# (Also filter out the L1 entry, because why not) +_check_test_img -r all --output=json \ + | sed -e 's/^ \(.*\)-fixed"/\1-fixed"/' \ + -e '/^ /d' \ + -e "s/\\([^0-9a-f]\\)$(printf %x $l1_entry)\\([^0-9a-f]\\)/\1L1_ENTRY_VALUE\2/" + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/138.out b/tests/qemu-iotests/138.out index aca7d47a80..79681e7cc9 100644 --- a/tests/qemu-iotests/138.out +++ b/tests/qemu-iotests/138.out @@ -9,4 +9,18 @@ ERROR: counting reference for region exceeding the end of the file by one cluste 1 errors were found on the image. Data may be corrupted, or further writes to the image may corrupt it. + +=== Check leaks-fixed/corruptions-fixed report + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +Leaked cluster 0 refcount=2 reference=1 +Repairing cluster 0 refcount=2 reference=1 +Repairing OFLAG_COPIED L2 cluster: l1_index=0 l1_entry=L1_ENTRY_VALUE refcount=1 +{ + "corruptions-fixed": 1, + "leaks-fixed": 1, +} *** done diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 4c246c0450..bf3b9fdea0 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -53,6 +53,30 @@ poke_file() printf "$3" | dd "of=$1" bs=1 "seek=$2" conv=notrunc &>/dev/null } +# poke_file_le $img_filename $offset $byte_width $value +# Example: poke_file_le "$TEST_IMG" 512 2 65534 +poke_file_le() +{ + local img=$1 ofs=$2 len=$3 val=$4 str='' + + while ((len--)); do + str+=$(printf '\\x%02x' $((val & 0xff))) + val=$((val >> 8)) + done + + poke_file "$img" "$ofs" "$str" +} + +# poke_file_be $img_filename $offset $byte_width $value +# Example: poke_file_be "$TEST_IMG" 512 2 65279 +poke_file_be() +{ + local img=$1 ofs=$2 len=$3 val=$4 + local str=$(printf "%0$((len * 2))x\n" $val | sed 's/\(..\)/\\x\1/g') + + poke_file "$img" "$ofs" "$str" +} + # peek_file_le 'test.img' 512 2 => 65534 peek_file_le() { diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 3d6cc83b88..2568c9529c 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -1211,7 +1211,7 @@ static void test_migrate_auto_converge(void) * without throttling. */ migrate_set_parameter_int(from, "downtime-limit", 1); - migrate_set_parameter_int(from, "max-bandwidth", 100000000); /* ~100Mb/s */ + migrate_set_parameter_int(from, "max-bandwidth", 1000000); /* ~1Mb/s */ /* To check remaining size after precopy */ migrate_set_capability(from, "pause-before-switchover", true); diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 4f259aac70..4c35c95b25 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -1520,8 +1520,7 @@ out_err: if (d) { if (d->dp) { closedir(d->dp); - } - if (fd != -1) { + } else if (fd != -1) { close(fd); } free(d); diff --git a/ui/input-linux.c b/ui/input-linux.c index a7b280b25b..ef37b14d6f 100644 --- a/ui/input-linux.c +++ b/ui/input-linux.c @@ -334,13 +334,15 @@ static void input_linux_complete(UserCreatable *uc, Error **errp) rc = ioctl(il->fd, EVIOCGBIT(0, sizeof(evtmap)), &evtmap); if (rc < 0) { - error_setg(errp, "%s: failed to read event bits", il->evdev); - goto err_close; + goto err_read_event_bits; } if (evtmap & (1 << EV_REL)) { relmap = 0; rc = ioctl(il->fd, EVIOCGBIT(EV_REL, sizeof(relmap)), &relmap); + if (rc < 0) { + goto err_read_event_bits; + } if (relmap & (1 << REL_X)) { il->has_rel_x = true; } @@ -349,12 +351,25 @@ static void input_linux_complete(UserCreatable *uc, Error **errp) if (evtmap & (1 << EV_ABS)) { absmap = 0; rc = ioctl(il->fd, EVIOCGBIT(EV_ABS, sizeof(absmap)), &absmap); + if (rc < 0) { + goto err_read_event_bits; + } if (absmap & (1 << ABS_X)) { il->has_abs_x = true; rc = ioctl(il->fd, EVIOCGABS(ABS_X), &absinfo); + if (rc < 0) { + error_setg(errp, "%s: failed to get get absolute X value", + il->evdev); + goto err_close; + } il->abs_x_min = absinfo.minimum; il->abs_x_max = absinfo.maximum; rc = ioctl(il->fd, EVIOCGABS(ABS_Y), &absinfo); + if (rc < 0) { + error_setg(errp, "%s: failed to get get absolute Y value", + il->evdev); + goto err_close; + } il->abs_y_min = absinfo.minimum; il->abs_y_max = absinfo.maximum; } @@ -363,7 +378,14 @@ static void input_linux_complete(UserCreatable *uc, Error **errp) if (evtmap & (1 << EV_KEY)) { memset(keymap, 0, sizeof(keymap)); rc = ioctl(il->fd, EVIOCGBIT(EV_KEY, sizeof(keymap)), keymap); + if (rc < 0) { + goto err_read_event_bits; + } rc = ioctl(il->fd, EVIOCGKEY(sizeof(keystate)), keystate); + if (rc < 0) { + error_setg(errp, "%s: failed to get global key state", il->evdev); + goto err_close; + } for (i = 0; i < KEY_CNT; i++) { if (keymap[i / 8] & (1 << (i % 8))) { if (linux_is_button(i)) { @@ -390,6 +412,9 @@ static void input_linux_complete(UserCreatable *uc, Error **errp) il->initialized = true; return; +err_read_event_bits: + error_setg(errp, "%s: failed to read event bits", il->evdev); + err_close: close(il->fd); return; |