Block patches:

- Drop BDRV_SECTOR_SIZE from qcow2
 - Allow Python iotests to be added to the auto group
   (and add some)
 - Fix for the backup job
 - Fix memleak in bdrv_refresh_filename()
 - Use GStrings in two places for greater efficiency (than manually
   handling string allocation)
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAl48C4YSHG1yZWl0ekBy
 ZWRoYXQuY29tAAoJEPQH2wBh1c9A1GsH/2qYR3qqZM6y3fJB0sfaARaKiTS9ac9f
 QQTAs2TEgXkzjdXUgIZu2ieJXPKDK+li7wYGVuMsaHPviscbJH3dKcDprjASHalR
 u7N913u+PB0eY3aTkHyZZwdoxCGQvMAvrHqkyAXrSdgqssodZ7Uj9/jjpGg0z3Io
 JE/eu11RdrOX7eOSZbEAYuaRg4VtrBuYIqwSihlRk0cBxjAScfW2ppa2P/Q8+VPa
 v9bTlFvWQALjG/b0uZx5EgbGztyYzy6PuhdDb+B0S9IsGRidtsxCYZ4pmwQuroJ4
 9mITIj0OAzN3Nw80SqTEmW0jtBecmiOOHrCxEREWYjNSP1MbVF5qSTI=
 =abrL
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2020-02-06' into staging

Block patches:
- Drop BDRV_SECTOR_SIZE from qcow2
- Allow Python iotests to be added to the auto group
  (and add some)
- Fix for the backup job
- Fix memleak in bdrv_refresh_filename()
- Use GStrings in two places for greater efficiency (than manually
  handling string allocation)

# gpg: Signature made Thu 06 Feb 2020 12:50:14 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-02-06:
  iotests: add test for backup-top failure on permission activation
  block/backup-top: fix failure path
  qcow2: Use BDRV_SECTOR_SIZE instead of the hardcoded value
  qcow2: Don't require aligned offsets in qcow2_co_copy_range_from()
  qcow2: Use bs->bl.request_alignment when updating an L1 entry
  qcow2: Tighten cluster_offset alignment assertions
  qcow2: Don't round the L1 table allocation up to the sector size
  iotests: Enable more tests in the 'auto' group to improve test coverage
  iotests: Skip Python-based tests if QEMU does not support virtio-blk
  iotests: Check for the availability of the required devices in 267 and 127
  iotests: Test 183 does not work on macOS and OpenBSD
  iotests: Test 041 only works on certain systems
  iotests: remove 'linux' from default supported platforms
  qcow2: Use a GString in report_unsupported_feature()
  block: fix memleaks in bdrv_refresh_filename
  block: Use a GString in bdrv_perm_names()
  qcow2: Assert that host cluster offsets fit in L2 table entries

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-02-06 16:22:05 +00:00
commit 863d2ed582
16 changed files with 220 additions and 73 deletions

12
block.c
View file

@ -1998,18 +1998,19 @@ char *bdrv_perm_names(uint64_t perm)
{ 0, NULL }
};
char *result = g_strdup("");
GString *result = g_string_sized_new(30);
struct perm_name *p;
for (p = permissions; p->name; p++) {
if (perm & p->perm) {
char *old = result;
result = g_strdup_printf("%s%s%s", old, *old ? ", " : "", p->name);
g_free(old);
if (result->len > 0) {
g_string_append(result, ", ");
}
g_string_append(result, p->name);
}
}
return result;
return g_string_free(result, FALSE);
}
/*
@ -6441,6 +6442,7 @@ void bdrv_refresh_filename(BlockDriverState *bs)
child->bs->exact_filename);
pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename);
qobject_unref(bs->full_open_options);
bs->full_open_options = qobject_ref(child->bs->full_open_options);
return;

View file

@ -190,6 +190,7 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter,
filter_node_name,
BDRV_O_RDWR, errp);
bool appended = false;
if (!top) {
return NULL;
@ -212,8 +213,9 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
bdrv_append(top, source, &local_err);
if (local_err) {
error_prepend(&local_err, "Cannot append backup-top filter: ");
goto append_failed;
goto fail;
}
appended = true;
/*
* bdrv_append() finished successfully, now we can require permissions
@ -224,14 +226,14 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
if (local_err) {
error_prepend(&local_err,
"Cannot set permissions for backup-top filter: ");
goto failed_after_append;
goto fail;
}
state->bcs = block_copy_state_new(top->backing, state->target,
cluster_size, write_flags, &local_err);
if (local_err) {
error_prepend(&local_err, "Cannot create block-copy-state: ");
goto failed_after_append;
goto fail;
}
*bcs = state->bcs;
@ -239,14 +241,15 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
return top;
failed_after_append:
state->active = false;
bdrv_backup_top_drop(top);
fail:
if (appended) {
state->active = false;
bdrv_backup_top_drop(top);
} else {
bdrv_unref(top);
}
append_failed:
bdrv_drained_end(source);
bdrv_unref_child(top, state->target);
bdrv_unref(top);
error_propagate(errp, local_err);
return NULL;

View file

@ -124,12 +124,11 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
#endif
new_l1_size2 = sizeof(uint64_t) * new_l1_size;
new_l1_table = qemu_try_blockalign(bs->file->bs,
ROUND_UP(new_l1_size2, 512));
new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_size2);
if (new_l1_table == NULL) {
return -ENOMEM;
}
memset(new_l1_table, 0, ROUND_UP(new_l1_size2, 512));
memset(new_l1_table, 0, new_l1_size2);
if (s->l1_size) {
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
@ -217,26 +216,31 @@ static int l2_load(BlockDriverState *bs, uint64_t offset,
}
/*
* Writes one sector of the L1 table to the disk (can't update single entries
* and we really don't want bdrv_pread to perform a read-modify-write)
* Writes an L1 entry to disk (note that depending on the alignment
* requirements this function may write more that just one entry in
* order to prevent bdrv_pwrite from performing a read-modify-write)
*/
#define L1_ENTRIES_PER_SECTOR (512 / 8)
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
{
BDRVQcow2State *s = bs->opaque;
uint64_t buf[L1_ENTRIES_PER_SECTOR] = { 0 };
int l1_start_index;
int i, ret;
int bufsize = MAX(sizeof(uint64_t),
MIN(bs->file->bs->bl.request_alignment, s->cluster_size));
int nentries = bufsize / sizeof(uint64_t);
g_autofree uint64_t *buf = g_try_new0(uint64_t, nentries);
l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
for (i = 0; i < L1_ENTRIES_PER_SECTOR && l1_start_index + i < s->l1_size;
i++)
{
if (buf == NULL) {
return -ENOMEM;
}
l1_start_index = QEMU_ALIGN_DOWN(l1_index, nentries);
for (i = 0; i < MIN(nentries, s->l1_size - l1_start_index); i++) {
buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
}
ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1,
s->l1_table_offset + 8 * l1_start_index, sizeof(buf), false);
s->l1_table_offset + 8 * l1_start_index, bufsize, false);
if (ret < 0) {
return ret;
}
@ -244,7 +248,7 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
ret = bdrv_pwrite_sync(bs->file,
s->l1_table_offset + 8 * l1_start_index,
buf, sizeof(buf));
buf, bufsize);
if (ret < 0) {
return ret;
}
@ -777,6 +781,10 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
(cluster_offset + compressed_size - 1) / QCOW2_COMPRESSED_SECTOR_SIZE -
(cluster_offset / QCOW2_COMPRESSED_SECTOR_SIZE);
/* The offset and size must fit in their fields of the L2 table entry */
assert((cluster_offset & s->cluster_offset_mask) == cluster_offset);
assert((nb_csectors & s->csize_mask) == nb_csectors);
cluster_offset |= QCOW_OFLAG_COMPRESSED |
((uint64_t)nb_csectors << s->csize_shift);
@ -972,6 +980,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
assert(l2_index + m->nb_clusters <= s->l2_slice_size);
for (i = 0; i < m->nb_clusters; i++) {
uint64_t offset = cluster_offset + (i << s->cluster_bits);
/* if two concurrent writes happen to the same unallocated cluster
* each write allocates separate cluster and writes data concurrently.
* The first one to complete updates l2 table with pointer to its
@ -982,8 +991,10 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
old_cluster[j++] = l2_slice[l2_index + i];
}
l2_slice[l2_index + i] = cpu_to_be64((cluster_offset +
(i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
/* The offset must fit in the offset field of the L2 table entry */
assert((offset & L2E_OFFSET_MASK) == offset);
l2_slice[l2_index + i] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
}
@ -1913,6 +1924,9 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
goto fail;
}
/* The offset must fit in the offset field */
assert((offset & L2E_OFFSET_MASK) == offset);
if (l2_refcount > 1) {
/* For shared L2 tables, set the refcount accordingly
* (it is already 1 and needs to be l2_refcount) */

View file

@ -1262,7 +1262,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
* l1_table_offset when it is the current s->l1_table_offset! Be careful
* when changing this! */
if (l1_table_offset != s->l1_table_offset) {
l1_table = g_try_malloc0(ROUND_UP(l1_size2, 512));
l1_table = g_try_malloc0(l1_size2);
if (l1_size2 && l1_table == NULL) {
ret = -ENOMEM;
goto fail;

View file

@ -1024,8 +1024,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
return ret;
}
new_l1_bytes = sn->l1_size * sizeof(uint64_t);
new_l1_table = qemu_try_blockalign(bs->file->bs,
ROUND_UP(new_l1_bytes, 512));
new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_bytes);
if (new_l1_table == NULL) {
return -ENOMEM;
}

View file

@ -453,16 +453,15 @@ static void cleanup_unknown_header_ext(BlockDriverState *bs)
static void report_unsupported_feature(Error **errp, Qcow2Feature *table,
uint64_t mask)
{
char *features = g_strdup("");
char *old;
g_autoptr(GString) features = g_string_sized_new(60);
while (table && table->name[0] != '\0') {
if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) {
if (mask & (1ULL << table->bit)) {
old = features;
features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "",
table->name);
g_free(old);
if (features->len > 0) {
g_string_append(features, ", ");
}
g_string_append_printf(features, "%.46s", table->name);
mask &= ~(1ULL << table->bit);
}
}
@ -470,14 +469,14 @@ static void report_unsupported_feature(Error **errp, Qcow2Feature *table,
}
if (mask) {
old = features;
features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64,
old, *old ? ", " : "", mask);
g_free(old);
if (features->len > 0) {
g_string_append(features, ", ");
}
g_string_append_printf(features,
"Unknown incompatible feature: %" PRIx64, mask);
}
error_setg(errp, "Unsupported qcow2 feature(s): %s", features);
g_free(features);
error_setg(errp, "Unsupported qcow2 feature(s): %s", features->str);
}
/*
@ -1492,7 +1491,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
if (s->l1_size > 0) {
s->l1_table = qemu_try_blockalign(bs->file->bs,
ROUND_UP(s->l1_size * sizeof(uint64_t), 512));
s->l1_size * sizeof(uint64_t));
if (s->l1_table == NULL) {
error_setg(errp, "Could not allocate L1 table");
ret = -ENOMEM;
@ -2168,10 +2167,7 @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
offset, bytes, qiov, qiov_offset);
case QCOW2_CLUSTER_NORMAL:
if ((file_cluster_offset & 511) != 0) {
return -EIO;
}
assert(offset_into_cluster(s, file_cluster_offset) == 0);
if (bs->encrypted) {
return qcow2_co_preadv_encrypted(bs, file_cluster_offset,
offset, bytes, qiov, qiov_offset);
@ -2507,7 +2503,7 @@ static coroutine_fn int qcow2_co_pwritev_part(
goto out_locked;
}
assert((cluster_offset & 511) == 0);
assert(offset_into_cluster(s, cluster_offset) == 0);
ret = qcow2_pre_write_overlap_check(bs, 0,
cluster_offset + offset_in_cluster,
@ -3276,7 +3272,8 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
/* Validate options and set default values */
if (!QEMU_IS_ALIGNED(qcow2_opts->size, BDRV_SECTOR_SIZE)) {
error_setg(errp, "Image size must be a multiple of 512 bytes");
error_setg(errp, "Image size must be a multiple of %u bytes",
(unsigned) BDRV_SECTOR_SIZE);
ret = -EINVAL;
goto out;
}
@ -3832,10 +3829,6 @@ qcow2_co_copy_range_from(BlockDriverState *bs,
case QCOW2_CLUSTER_NORMAL:
child = s->data_file;
copy_offset += offset_into_cluster(s, src_offset);
if ((copy_offset & 511) != 0) {
ret = -EIO;
goto out;
}
break;
default:
@ -3897,7 +3890,7 @@ qcow2_co_copy_range_to(BlockDriverState *bs,
goto fail;
}
assert((cluster_offset & 511) == 0);
assert(offset_into_cluster(s, cluster_offset) == 0);
ret = qcow2_pre_write_overlap_check(bs, 0,
cluster_offset + offset_in_cluster, cur_bytes, true);
@ -3954,8 +3947,9 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
return -ENOTSUP;
}
if (offset & 511) {
error_setg(errp, "The new size must be a multiple of 512");
if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
error_setg(errp, "The new size must be a multiple of %u",
(unsigned) BDRV_SECTOR_SIZE);
return -EINVAL;
}

View file

@ -1134,4 +1134,5 @@ class TestOrphanedSource(iotests.QMPTestCase):
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'],
supported_protocols=['file'])
supported_protocols=['file'],
supported_platforms=['linux', 'freebsd', 'netbsd', 'openbsd'])

View file

@ -43,6 +43,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file
_require_devices virtio-scsi scsi-hd
IMG_SIZE=64K
_make_test_img $IMG_SIZE

View file

@ -42,6 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.filter
. ./common.qemu
_supported_os Linux FreeBSD NetBSD
_supported_fmt qcow2 raw qed quorum
_supported_proto file

View file

@ -46,6 +46,8 @@ _require_drivers copy-on-read
# and generally impossible with external data files
_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
_require_devices virtio-blk
do_run_qemu()
{
echo Testing: "$@"

92
tests/qemu-iotests/283 Normal file
View file

@ -0,0 +1,92 @@
#!/usr/bin/env python
#
# Test for backup-top filter permission activation failure
#
# Copyright (c) 2019 Virtuozzo International GmbH.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import iotests
# The test is unrelated to formats, restrict it to qcow2 to avoid extra runs
iotests.verify_image_format(supported_fmts=['qcow2'])
size = 1024 * 1024
""" Test description
When performing a backup, all writes on the source subtree must go through the
backup-top filter so it can copy all data to the target before it is changed.
backup-top filter is appended above source node, to achieve this thing, so all
parents of source node are handled. A configuration with side parents of source
sub-tree with write permission is unsupported (we'd have append several
backup-top filter like nodes to handle such parents). The test create an
example of such configuration and checks that a backup is then not allowed
(blockdev-backup command should fail).
The configuration:
┌────────┐ target ┌─────────────┐
│ target │ ◀─────── │ backup_top │
└────────┘ └─────────────┘
│ backing
┌─────────────┐
│ source │
└─────────────┘
│ file
┌─────────────┐ write perm ┌───────┐
│ base │ ◀──────────── │ other │
└─────────────┘ └───────┘
On activation (see .active field of backup-top state in block/backup-top.c),
backup-top is going to unshare write permission on its source child. Write
unsharing will be propagated to the "source->base" link and will conflict with
other node write permission. So permission update will fail and backup job will
not be started.
Note, that the only thing which prevents backup of running on such
configuration is default permission propagation scheme. It may be altered by
different block drivers, so backup will run in invalid configuration. But
something is better than nothing. Also, before the previous commit (commit
preceding this test creation), starting backup on such configuration led to
crash, so current "something" is a lot better, and this test actual goal is
to check that crash is fixed :)
"""
vm = iotests.VM()
vm.launch()
vm.qmp_log('blockdev-add', **{'node-name': 'target', 'driver': 'null-co'})
vm.qmp_log('blockdev-add', **{
'node-name': 'source',
'driver': 'blkdebug',
'image': {'node-name': 'base', 'driver': 'null-co', 'size': size}
})
vm.qmp_log('blockdev-add', **{
'node-name': 'other',
'driver': 'blkdebug',
'image': 'base',
'take-child-perms': ['write']
})
vm.qmp_log('blockdev-backup', sync='full', device='source', target='target')
vm.shutdown()

View file

@ -0,0 +1,8 @@
{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "target"}}
{"return": {}}
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": {"driver": "null-co", "node-name": "base", "size": 1048576}, "node-name": "source"}}
{"return": {}}
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
{"return": {}}
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
{"error": {"class": "GenericError", "desc": "Cannot set permissions for backup-top filter: Conflicts with use by other as 'image', which uses 'write' on base"}}

View file

@ -655,7 +655,15 @@ fi
python_usable=false
if $PYTHON -c 'import sys; sys.exit(0 if sys.version_info >= (3,6) else 1)'
then
python_usable=true
# Our python framework also requires virtio-blk
if "$QEMU_PROG" -M none -device help | grep -q virtio-blk >/dev/null 2>&1
then
python_usable=true
else
python_unusable_because="Missing virtio-blk in QEMU binary"
fi
else
python_unusable_because="Unsupported Python version"
fi
default_machine=$($QEMU_PROG -machine help | sed -n '/(default)/ s/ .*//p')
@ -843,7 +851,7 @@ do
run_command="$PYTHON $seq"
else
run_command="false"
echo "Unsupported Python version" > $seq.notrun
echo "$python_unusable_because" > $seq.notrun
fi
else
run_command="./$seq"

View file

@ -713,5 +713,19 @@ _require_large_file()
rm "$TEST_IMG"
}
# Check that a set of devices is available in the QEMU binary
#
_require_devices()
{
available=$($QEMU -M none -device help | \
grep ^name | sed -e 's/^name "//' -e 's/".*$//')
for device
do
if ! echo "$available" | grep -q "$device" ; then
_notrun "$device not available"
fi
done
}
# make sure this script returns success
true

View file

@ -51,7 +51,7 @@
027 rw auto quick
028 rw backing quick
029 rw auto quick
030 rw backing
030 rw auto backing
031 rw auto quick
032 rw auto quick
033 rw auto quick
@ -61,8 +61,8 @@
037 rw auto backing quick
038 rw auto backing quick
039 rw auto quick
040 rw
041 rw backing
040 rw auto
041 rw auto backing
042 rw auto quick
043 rw auto backing
044 rw
@ -148,7 +148,7 @@
124 rw backing
125 rw
126 rw auto backing
127 rw backing quick
127 rw auto backing quick
128 rw quick
129 rw quick
130 rw quick
@ -197,7 +197,7 @@
177 rw auto quick
178 img
179 rw auto quick
181 rw migration
181 rw auto migration
182 rw quick
183 rw migration
184 rw auto quick
@ -218,7 +218,7 @@
200 rw
201 rw migration
202 rw quick
203 rw migration
203 rw auto migration
204 rw quick
205 rw quick
206 rw
@ -270,7 +270,7 @@
253 rw quick
254 rw backing quick
255 rw quick
256 rw quick
256 rw auto quick
257 rw
258 rw quick
260 rw quick
@ -289,3 +289,4 @@
279 rw backing quick
280 rw migration quick
281 rw quick
283 auto quick

View file

@ -931,9 +931,14 @@ def verify_protocol(supported=[], unsupported=[]):
if not_sup or (imgproto in unsupported):
notrun('not suitable for this protocol: %s' % imgproto)
def verify_platform(supported_oses=['linux']):
if True not in [sys.platform.startswith(x) for x in supported_oses]:
notrun('not suitable for this OS: %s' % sys.platform)
def verify_platform(supported=None, unsupported=None):
if unsupported is not None:
if any((sys.platform.startswith(x) for x in unsupported)):
notrun('not suitable for this OS: %s' % sys.platform)
if supported is not None:
if not any((sys.platform.startswith(x) for x in supported)):
notrun('not suitable for this OS: %s' % sys.platform)
def verify_cache_mode(supported_cache_modes=[]):
if supported_cache_modes and (cachemode not in supported_cache_modes):
@ -1028,7 +1033,8 @@ def execute_unittest(output, verbosity, debug):
sys.stderr.write(out)
def execute_test(test_function=None,
supported_fmts=[], supported_oses=['linux'],
supported_fmts=[],
supported_platforms=None,
supported_cache_modes=[], supported_aio_modes={},
unsupported_fmts=[], supported_protocols=[],
unsupported_protocols=[]):
@ -1046,7 +1052,7 @@ def execute_test(test_function=None,
verbosity = 1
verify_image_format(supported_fmts, unsupported_fmts)
verify_protocol(supported_protocols, unsupported_protocols)
verify_platform(supported_oses)
verify_platform(supported=supported_platforms)
verify_cache_mode(supported_cache_modes)
verify_aio_mode(supported_aio_modes)