Block patches for 5.0-rc1:

- Fix qemu-img convert with a host device or iscsi target
 - Use-after-free fix in mirror
 - Some minor qcow2 fixes
 - Minor sheepdog fix
 - Minor qemu-img check report fix
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAl58vAoSHG1yZWl0ekBy
 ZWRoYXQuY29tAAoJEPQH2wBh1c9AXDAH/R6PSji88+u3Cu4sVOtc2b73rknfGgTZ
 o4iETRYMr3/guC/lff5ckEfWN8zqnlrZeymZ5r4pwBrpDZlpP7JKYYihiJGXWCze
 NLZ1JCASWnP7OGbcEqgbODP988b8Ik/X42Re3Q7UPvaunhSh5SRDm2J2RgsObLuU
 vu+VPwm8Y+voipbtMcJrRwwF0MxS1b43DaTtwI9Aq6GwHz6beej5CeFa9eP7xXo9
 vxQxXQdRpPxjqEdIQk29gcGYvgfJDBIxt12ILlBiGuQWYh3f+bfxpcAcJUb+DTIN
 GnrcTTlfsX+Ll9RYpBCtIOaRdfpYai59YP63KrSYmh5D78RbawLkMi0=
 =zSv1
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2020-03-26' into staging

Block patches for 5.0-rc1:
- Fix qemu-img convert with a host device or iscsi target
- Use-after-free fix in mirror
- Some minor qcow2 fixes
- Minor sheepdog fix
- Minor qemu-img check report fix

# gpg: Signature made Thu 26 Mar 2020 14:28:26 GMT
# gpg:                using RSA key 91BEB60A30DB3E8857D11829F407DB0061D5CF40
# gpg:                issuer "mreitz@redhat.com"
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>" [full]
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* remotes/maxreitz/tags/pull-block-2020-03-26:
  iotests/138: Test leaks/corruptions fixed report
  iotests: Add poke_file_[bl]e functions
  qemu-img: Fix check's leak/corruption fix report
  sheepdog: Consistently set bdrv_has_zero_init_truncate
  qcow2: Avoid feature name extension on small cluster size
  qcow2: List autoclear bit names in header
  qcow2: Comment typo fixes
  block: trickle down the fallback image creation function use to the block drivers
  block: pass BlockDriver reference to the .bdrv_co_create
  block/mirror: fix use after free of local_err

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-03-26 15:44:26 +00:00
commit 762fa6d79a
34 changed files with 233 additions and 76 deletions

34
block.c
View File

@ -483,7 +483,8 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
CreateCo *cco = opaque; CreateCo *cco = opaque;
assert(cco->drv); 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); error_propagate(&cco->err, local_err);
cco->ret = ret; cco->ret = ret;
} }
@ -597,8 +598,15 @@ static int create_file_fallback_zero_first_sector(BlockBackend *blk,
return 0; 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; BlockBackend *blk;
QDict *options; QDict *options;
@ -662,11 +670,7 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
return -ENOENT; return -ENOENT;
} }
if (drv->bdrv_co_create_opts) {
return bdrv_create(drv, filename, opts, errp); return bdrv_create(drv, filename, opts, errp);
} else {
return bdrv_create_file_fallback(filename, drv, opts, errp);
}
} }
int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **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 = { QemuOptsList bdrv_create_opts_simple = {
.name = "fallback-create-opts", .name = "simple-create-opts",
.head = QTAILQ_HEAD_INITIALIZER(fallback_create_opts.head), .head = QTAILQ_HEAD_INITIALIZER(bdrv_create_opts_simple.head),
.desc = { .desc = {
{ {
.name = BLOCK_OPT_SIZE, .name = BLOCK_OPT_SIZE,
@ -5962,13 +5966,15 @@ void bdrv_img_create(const char *filename, const char *fmt,
return; 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 parameter list */
create_opts = qemu_opts_append(create_opts, drv->create_opts); 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); create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
} else {
create_opts = qemu_opts_append(create_opts, &fallback_create_opts);
}
opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);

View File

@ -601,7 +601,8 @@ fail:
return ret; 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, QemuOpts *opts,
Error **errp) Error **errp)
{ {

View File

@ -2405,7 +2405,9 @@ out:
return result; 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) Error **errp)
{ {
BlockdevCreateOptions options; BlockdevCreateOptions options;
@ -3511,6 +3513,8 @@ static BlockDriver bdrv_host_device = {
.bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort, .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, .mutable_opts = mutable_opts,
.bdrv_co_invalidate_cache = raw_co_invalidate_cache, .bdrv_co_invalidate_cache = raw_co_invalidate_cache,
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes, .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_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort, .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, .mutable_opts = mutable_opts,
.bdrv_co_invalidate_cache = raw_co_invalidate_cache, .bdrv_co_invalidate_cache = raw_co_invalidate_cache,
.bdrv_co_preadv = raw_co_preadv, .bdrv_co_preadv = raw_co_preadv,
.bdrv_co_pwritev = raw_co_pwritev, .bdrv_co_pwritev = raw_co_pwritev,
.bdrv_co_flush_to_disk = raw_co_flush_to_disk, .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_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort, .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, .mutable_opts = mutable_opts,
.bdrv_co_preadv = raw_co_preadv, .bdrv_co_preadv = raw_co_preadv,

View File

@ -588,7 +588,9 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
return 0; 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) Error **errp)
{ {
BlockdevCreateOptions options; BlockdevCreateOptions options;

View File

@ -1130,7 +1130,8 @@ out:
return ret; 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, QemuOpts *opts,
Error **errp) Error **errp)
{ {

View File

@ -2399,18 +2399,6 @@ out_unlock:
return r; 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[] = { static const char *const iscsi_strong_runtime_opts[] = {
"transport", "transport",
@ -2434,6 +2422,8 @@ static BlockDriver bdrv_iscsi = {
.bdrv_parse_filename = iscsi_parse_filename, .bdrv_parse_filename = iscsi_parse_filename,
.bdrv_file_open = iscsi_open, .bdrv_file_open = iscsi_open,
.bdrv_close = iscsi_close, .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_prepare = iscsi_reopen_prepare,
.bdrv_reopen_commit = iscsi_reopen_commit, .bdrv_reopen_commit = iscsi_reopen_commit,
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
@ -2471,6 +2461,8 @@ static BlockDriver bdrv_iser = {
.bdrv_parse_filename = iscsi_parse_filename, .bdrv_parse_filename = iscsi_parse_filename,
.bdrv_file_open = iscsi_open, .bdrv_file_open = iscsi_open,
.bdrv_close = iscsi_close, .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_prepare = iscsi_reopen_prepare,
.bdrv_reopen_commit = iscsi_reopen_commit, .bdrv_reopen_commit = iscsi_reopen_commit,
.bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,

View File

@ -678,6 +678,7 @@ static int mirror_exit_common(Job *job)
bdrv_set_backing_hd(target_bs, backing, &local_err); bdrv_set_backing_hd(target_bs, backing, &local_err);
if (local_err) { if (local_err) {
error_report_err(local_err); error_report_err(local_err);
local_err = NULL;
ret = -EPERM; ret = -EPERM;
} }
} }

View File

@ -2038,6 +2038,8 @@ static BlockDriver bdrv_nbd = {
.protocol_name = "nbd", .protocol_name = "nbd",
.instance_size = sizeof(BDRVNBDState), .instance_size = sizeof(BDRVNBDState),
.bdrv_parse_filename = nbd_parse_filename, .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_file_open = nbd_open,
.bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_reopen_prepare = nbd_client_reopen_prepare,
.bdrv_co_preadv = nbd_client_co_preadv, .bdrv_co_preadv = nbd_client_co_preadv,
@ -2063,6 +2065,8 @@ static BlockDriver bdrv_nbd_tcp = {
.protocol_name = "nbd+tcp", .protocol_name = "nbd+tcp",
.instance_size = sizeof(BDRVNBDState), .instance_size = sizeof(BDRVNBDState),
.bdrv_parse_filename = nbd_parse_filename, .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_file_open = nbd_open,
.bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_reopen_prepare = nbd_client_reopen_prepare,
.bdrv_co_preadv = nbd_client_co_preadv, .bdrv_co_preadv = nbd_client_co_preadv,
@ -2088,6 +2092,8 @@ static BlockDriver bdrv_nbd_unix = {
.protocol_name = "nbd+unix", .protocol_name = "nbd+unix",
.instance_size = sizeof(BDRVNBDState), .instance_size = sizeof(BDRVNBDState),
.bdrv_parse_filename = nbd_parse_filename, .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_file_open = nbd_open,
.bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_reopen_prepare = nbd_client_reopen_prepare,
.bdrv_co_preadv = nbd_client_co_preadv, .bdrv_co_preadv = nbd_client_co_preadv,

View File

@ -662,7 +662,9 @@ out:
return ret; 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) Error **errp)
{ {
BlockdevCreateOptions *create_options; BlockdevCreateOptions *create_options;

View File

@ -1333,6 +1333,9 @@ static BlockDriver bdrv_nvme = {
.protocol_name = "nvme", .protocol_name = "nvme",
.instance_size = sizeof(BDRVNVMeState), .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_parse_filename = nvme_parse_filename,
.bdrv_file_open = nvme_file_open, .bdrv_file_open = nvme_file_open,
.bdrv_close = nvme_close, .bdrv_close = nvme_close,

View File

@ -609,7 +609,8 @@ exit:
goto out; 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, QemuOpts *opts,
Error **errp) Error **errp)
{ {

View File

@ -934,7 +934,8 @@ exit:
return ret; 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) QemuOpts *opts, Error **errp)
{ {
BlockdevCreateOptions *create_options = NULL; BlockdevCreateOptions *create_options = NULL;

View File

@ -2823,9 +2823,16 @@ int qcow2_update_header(BlockDriverState *bs)
buflen -= ret; buflen -= ret;
} }
/* Feature table */ /*
if (s->qcow_version >= 3) { * Feature table. A mere 8 feature names occupies 392 bytes, and
Qcow2Feature features[] = { * 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, .type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
.bit = QCOW2_INCOMPAT_DIRTY_BITNR, .bit = QCOW2_INCOMPAT_DIRTY_BITNR,
@ -2846,6 +2853,16 @@ int qcow2_update_header(BlockDriverState *bs)
.bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
.name = "lazy refcounts", .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, ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,
@ -3255,7 +3272,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
* inconsistency later. * inconsistency later.
* *
* We do need a refcount table because growing the refcount table means * 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 * 2 GB for 64k clusters, and we don't want to have a 2 GB initial file
* size for any qcow2 image. * size for any qcow2 image.
*/ */
@ -3558,7 +3575,9 @@ out:
return ret; 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) Error **errp)
{ {
BlockdevCreateOptions *create_options = NULL; BlockdevCreateOptions *create_options = NULL;

View File

@ -720,7 +720,8 @@ out:
return ret; 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, QemuOpts *opts,
Error **errp) Error **errp)
{ {

View File

@ -419,7 +419,9 @@ static int raw_has_zero_init_truncate(BlockDriverState *bs)
return bdrv_has_zero_init_truncate(bs->file->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) Error **errp)
{ {
return bdrv_create_file(filename, opts, errp); return bdrv_create_file(filename, opts, errp);

View File

@ -437,7 +437,8 @@ static int qemu_rbd_co_create(BlockdevCreateOptions *options, Error **errp)
return qemu_rbd_do_create(options, NULL, NULL, 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, QemuOpts *opts,
Error **errp) Error **errp)
{ {

View File

@ -2157,7 +2157,9 @@ out:
return ret; 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) Error **errp)
{ {
BlockdevCreateOptions *create_options = NULL; BlockdevCreateOptions *create_options = NULL;
@ -3269,6 +3271,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
.bdrv_co_create = sd_co_create, .bdrv_co_create = sd_co_create,
.bdrv_co_create_opts = sd_co_create_opts, .bdrv_co_create_opts = sd_co_create_opts,
.bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength, .bdrv_getlength = sd_getlength,
.bdrv_get_allocated_file_size = sd_get_allocated_file_size, .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
.bdrv_co_truncate = sd_co_truncate, .bdrv_co_truncate = sd_co_truncate,
@ -3307,6 +3310,7 @@ static BlockDriver bdrv_sheepdog_unix = {
.bdrv_co_create = sd_co_create, .bdrv_co_create = sd_co_create,
.bdrv_co_create_opts = sd_co_create_opts, .bdrv_co_create_opts = sd_co_create_opts,
.bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength, .bdrv_getlength = sd_getlength,
.bdrv_get_allocated_file_size = sd_get_allocated_file_size, .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
.bdrv_co_truncate = sd_co_truncate, .bdrv_co_truncate = sd_co_truncate,

View File

@ -963,7 +963,9 @@ fail:
return ret; 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) Error **errp)
{ {
BlockdevCreateOptions *create_options; BlockdevCreateOptions *create_options;

View File

@ -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); 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) Error **errp)
{ {
QDict *qdict = NULL; QDict *qdict = NULL;

View File

@ -2046,7 +2046,8 @@ delete_and_exit:
return ret; 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, QemuOpts *opts,
Error **errp) Error **errp)
{ {

View File

@ -2588,7 +2588,9 @@ exit:
return blk; 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 **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;

View File

@ -1089,8 +1089,10 @@ out:
return ret; return ret;
} }
static int coroutine_fn vpc_co_create_opts(const char *filename, static int coroutine_fn vpc_co_create_opts(BlockDriver *drv,
QemuOpts *opts, Error **errp) const char *filename,
QemuOpts *opts,
Error **errp)
{ {
BlockdevCreateOptions *create_options = NULL; BlockdevCreateOptions *create_options = NULL;
QDict *qdict; QDict *qdict;

View File

@ -143,7 +143,8 @@ the next fields through header_length.
bit is unset, the bitmaps extension data must be bit is unset, the bitmaps extension data must be
considered inconsistent. 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 be read as a consistent standalone raw image
without looking at the qcow2 metadata. without looking at the qcow2 metadata.

View File

@ -283,6 +283,7 @@ BlockDriver *bdrv_find_format(const char *format_name);
int bdrv_create(BlockDriver *drv, const char* filename, int bdrv_create(BlockDriver *drv, const char* filename,
QemuOpts *opts, Error **errp); QemuOpts *opts, Error **errp);
int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp); int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
BlockDriverState *bdrv_new(void); BlockDriverState *bdrv_new(void);
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
Error **errp); Error **errp);

View File

@ -135,7 +135,8 @@ struct BlockDriver {
void (*bdrv_close)(BlockDriverState *bs); void (*bdrv_close)(BlockDriverState *bs);
int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts, int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts,
Error **errp); 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, QemuOpts *opts,
Error **errp); Error **errp);
int (*bdrv_make_empty)(BlockDriverState *bs); 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); void bdrv_set_monitor_owned(BlockDriverState *bs);
BlockDriverState *bds_tree_init(QDict *bs_opts, Error **errp); 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 */ #endif /* BLOCK_INT_H */

View File

@ -647,9 +647,9 @@ static int collect_image_check(BlockDriverState *bs,
check->leaks = result.leaks; check->leaks = result.leaks;
check->has_leaks = result.leaks != 0; check->has_leaks = result.leaks != 0;
check->corruptions_fixed = result.corruptions_fixed; 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->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->image_end_offset = result.image_end_offset;
check->has_image_end_offset = result.image_end_offset != 0; check->has_image_end_offset = result.image_end_offset != 0;
check->total_clusters = result.bfi.total_clusters; 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) { if (check->corruptions_fixed || check->leaks_fixed) {
int corruptions_fixed, leaks_fixed; int corruptions_fixed, leaks_fixed;
bool has_leaks_fixed, has_corruptions_fixed;
leaks_fixed = check->leaks_fixed; leaks_fixed = check->leaks_fixed;
has_leaks_fixed = check->has_leaks_fixed;
corruptions_fixed = check->corruptions_fixed; corruptions_fixed = check->corruptions_fixed;
has_corruptions_fixed = check->has_corruptions_fixed;
if (output_format == OFORMAT_HUMAN) { if (output_format == OFORMAT_HUMAN) {
qprintf(quiet, qprintf(quiet,
@ -822,7 +825,9 @@ static int img_check(int argc, char **argv)
ret = collect_image_check(bs, check, filename, fmt, 0); ret = collect_image_check(bs, check, filename, fmt, 0);
check->leaks_fixed = leaks_fixed; check->leaks_fixed = leaks_fixed;
check->has_leaks_fixed = has_leaks_fixed;
check->corruptions_fixed = corruptions_fixed; check->corruptions_fixed = corruptions_fixed;
check->has_corruptions_fixed = has_corruptions_fixed;
} }
if (!ret) { if (!ret) {

View File

@ -117,7 +117,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
Header extension: Header extension:
@ -150,7 +150,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
Header extension: Header extension:
@ -164,7 +164,7 @@ No errors were found on the image.
magic 0x514649fb magic 0x514649fb
version 3 version 3
backing_file_offset 0x178 backing_file_offset 0x1d8
backing_file_size 0x17 backing_file_size 0x17
cluster_bits 16 cluster_bits 16
size 67108864 size 67108864
@ -188,7 +188,7 @@ data 'host_device'
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
Header extension: Header extension:

View File

@ -44,8 +44,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2 _supported_fmt qcow2
_supported_proto file _supported_proto file
# Only qcow2v3 and later supports feature bits; # Only qcow2v3 and later supports feature bits;
# qcow2.py does not support external data files # qcow2.py does not support external data files;
_unsupported_imgopts 'compat=0.10' data_file # 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
echo === Image with unknown incompatible feature bit === echo === Image with unknown incompatible feature bit ===

View File

@ -26,7 +26,7 @@ compatible_features []
autoclear_features [63] autoclear_features [63]
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
@ -38,7 +38,7 @@ compatible_features []
autoclear_features [] autoclear_features []
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
*** done *** done

View File

@ -44,8 +44,10 @@ _supported_os Linux
# Conversion between different compat versions can only really work # Conversion between different compat versions can only really work
# with refcount_bits=16; # with refcount_bits=16;
# we have explicit tests for data_file here, but the whole test does # we have explicit tests for data_file here, but the whole test does
# not work with it # not work with it;
_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file # 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
echo "=== Testing version downgrade with zero expansion ===" echo "=== Testing version downgrade with zero expansion ==="

View File

@ -26,7 +26,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
magic 0x514649fb magic 0x514649fb
@ -84,7 +84,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
magic 0x514649fb magic 0x514649fb
@ -140,7 +140,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
ERROR cluster 5 refcount=0 reference=1 ERROR cluster 5 refcount=0 reference=1
@ -195,7 +195,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
magic 0x514649fb magic 0x514649fb
@ -264,7 +264,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
read 65536/65536 bytes at offset 44040192 read 65536/65536 bytes at offset 44040192
@ -298,7 +298,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
ERROR cluster 5 refcount=0 reference=1 ERROR cluster 5 refcount=0 reference=1
@ -327,7 +327,7 @@ header_length 104
Header extension: Header extension:
magic 0x6803f857 magic 0x6803f857
length 192 length 288
data <binary> data <binary>
read 131072/131072 bytes at offset 0 read 131072/131072 bytes at offset 0

View File

@ -41,8 +41,10 @@ _supported_fmt qcow2
_supported_proto file _supported_proto file
_supported_os Linux _supported_os Linux
# With an external data file, data clusters are not refcounted # With an external data file, data clusters are not refcounted
# (and so qemu-img check does not check their refcount) # (so qemu-img check would not do much);
_unsupported_imgopts data_file # 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
echo '=== Check on an image with a multiple of 2^32 clusters ===' 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. # allocate memory", we have an error showing that l2 entry is invalid.
_check_test_img _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 # success, all done
echo "*** done" echo "*** done"
rm -f $seq.full rm -f $seq.full

View File

@ -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. 1 errors were found on the image.
Data may be corrupted, or further writes to the image may corrupt it. 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 *** done

View File

@ -53,6 +53,30 @@ poke_file()
printf "$3" | dd "of=$1" bs=1 "seek=$2" conv=notrunc &>/dev/null 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 'test.img' 512 2 => 65534
peek_file_le() peek_file_le()
{ {