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

38
block.c
View File

@ -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);

View File

@ -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)
{

View File

@ -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,

View File

@ -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;

View File

@ -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)
{

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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)
{

View File

@ -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;

View File

@ -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;

View File

@ -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)
{

View File

@ -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);

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);
}
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)
{

View File

@ -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,

View File

@ -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;

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);
}
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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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 */

View File

@ -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) {

View File

@ -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:

View File

@ -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 ===

View File

@ -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

View File

@ -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 ==="

View File

@ -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

View File

@ -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

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.
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

View File

@ -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()
{