1 | The following changes since commit e4ae62b802cec437f877f2cadc4ef059cc0eca76: | 1 | The following changes since commit 418fa86dd465b4fd8394373cf83db8fa65d7611c: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging (2018-03-09 17:28:16 +0000) | 3 | Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-040220-1' into staging (2020-02-04 18:55:06 +0000) |
4 | 4 | ||
5 | are available in the Git repository at: | 5 | are available in the Git repository at: |
6 | 6 | ||
7 | git://github.com/stefanha/qemu.git tags/block-pull-request | 7 | https://github.com/XanClic/qemu.git tags/pull-block-2020-02-06 |
8 | 8 | ||
9 | for you to fetch changes up to 7376eda7c2e0451e819e81bd05fabc56a9deb946: | 9 | for you to fetch changes up to a541fcc27c98b96da187c7d4573f3270f3ddd283: |
10 | 10 | ||
11 | block: make BDRV_POLL_WHILE() re-entrancy safe (2018-03-12 11:07:37 +0000) | 11 | iotests: add test for backup-top failure on permission activation (2020-02-06 13:47:45 +0100) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block patches: | ||
15 | - Drop BDRV_SECTOR_SIZE from qcow2 | ||
16 | - Allow Python iotests to be added to the auto group | ||
17 | (and add some) | ||
18 | - Fix for the backup job | ||
19 | - Fix memleak in bdrv_refresh_filename() | ||
20 | - Use GStrings in two places for greater efficiency (than manually | ||
21 | handling string allocation) | ||
14 | 22 | ||
15 | ---------------------------------------------------------------- | 23 | ---------------------------------------------------------------- |
24 | Alberto Garcia (8): | ||
25 | qcow2: Assert that host cluster offsets fit in L2 table entries | ||
26 | block: Use a GString in bdrv_perm_names() | ||
27 | qcow2: Use a GString in report_unsupported_feature() | ||
28 | qcow2: Don't round the L1 table allocation up to the sector size | ||
29 | qcow2: Tighten cluster_offset alignment assertions | ||
30 | qcow2: Use bs->bl.request_alignment when updating an L1 entry | ||
31 | qcow2: Don't require aligned offsets in qcow2_co_copy_range_from() | ||
32 | qcow2: Use BDRV_SECTOR_SIZE instead of the hardcoded value | ||
16 | 33 | ||
17 | Stefan Hajnoczi (1): | 34 | John Snow (1): |
18 | block: make BDRV_POLL_WHILE() re-entrancy safe | 35 | iotests: remove 'linux' from default supported platforms |
19 | 36 | ||
20 | include/block/aio-wait.h | 61 ++++++++++++++++++++++++------------------------ | 37 | Pan Nengyuan (1): |
21 | util/aio-wait.c | 2 +- | 38 | block: fix memleaks in bdrv_refresh_filename |
22 | 2 files changed, 31 insertions(+), 32 deletions(-) | 39 | |
40 | Thomas Huth (5): | ||
41 | iotests: Test 041 only works on certain systems | ||
42 | iotests: Test 183 does not work on macOS and OpenBSD | ||
43 | iotests: Check for the availability of the required devices in 267 and | ||
44 | 127 | ||
45 | iotests: Skip Python-based tests if QEMU does not support virtio-blk | ||
46 | iotests: Enable more tests in the 'auto' group to improve test | ||
47 | coverage | ||
48 | |||
49 | Vladimir Sementsov-Ogievskiy (2): | ||
50 | block/backup-top: fix failure path | ||
51 | iotests: add test for backup-top failure on permission activation | ||
52 | |||
53 | block.c | 12 +++-- | ||
54 | block/backup-top.c | 21 ++++---- | ||
55 | block/qcow2-cluster.c | 44 +++++++++++------ | ||
56 | block/qcow2-refcount.c | 2 +- | ||
57 | block/qcow2-snapshot.c | 3 +- | ||
58 | block/qcow2.c | 46 ++++++++---------- | ||
59 | tests/qemu-iotests/041 | 3 +- | ||
60 | tests/qemu-iotests/127 | 2 + | ||
61 | tests/qemu-iotests/183 | 1 + | ||
62 | tests/qemu-iotests/267 | 2 + | ||
63 | tests/qemu-iotests/283 | 92 +++++++++++++++++++++++++++++++++++ | ||
64 | tests/qemu-iotests/283.out | 8 +++ | ||
65 | tests/qemu-iotests/check | 12 ++++- | ||
66 | tests/qemu-iotests/common.rc | 14 ++++++ | ||
67 | tests/qemu-iotests/group | 15 +++--- | ||
68 | tests/qemu-iotests/iotests.py | 16 ++++-- | ||
69 | 16 files changed, 220 insertions(+), 73 deletions(-) | ||
70 | create mode 100644 tests/qemu-iotests/283 | ||
71 | create mode 100644 tests/qemu-iotests/283.out | ||
23 | 72 | ||
24 | -- | 73 | -- |
25 | 2.14.3 | 74 | 2.24.1 |
26 | 75 | ||
27 | 76 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
1 | 2 | ||
3 | The standard cluster descriptor in L2 table entries has a field to | ||
4 | store the host cluster offset. When we need to get that offset from an | ||
5 | entry we use L2E_OFFSET_MASK to ensure that we only use the bits that | ||
6 | belong to that field. | ||
7 | |||
8 | But while that mask is used every time we read from an L2 entry, it | ||
9 | is never used when we write to it. Due to the QCOW_MAX_CLUSTER_OFFSET | ||
10 | limit set in the cluster allocation code QEMU can never produce | ||
11 | offsets that don't fit in that field so any such offset would indicate | ||
12 | a bug in QEMU. | ||
13 | |||
14 | Compressed cluster descriptors contain two fields (host cluster offset | ||
15 | and size of the compressed data) and the situation with them is | ||
16 | similar. In this case the masks are not constant but are stored in the | ||
17 | csize_mask and cluster_offset_mask fields of BDRVQcow2State. | ||
18 | |||
19 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
20 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
21 | Message-id: 20200113161146.20099-1-berto@igalia.com | ||
22 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
23 | --- | ||
24 | block/qcow2-cluster.c | 14 ++++++++++++-- | ||
25 | 1 file changed, 12 insertions(+), 2 deletions(-) | ||
26 | |||
27 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/block/qcow2-cluster.c | ||
30 | +++ b/block/qcow2-cluster.c | ||
31 | @@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, | ||
32 | (cluster_offset + compressed_size - 1) / QCOW2_COMPRESSED_SECTOR_SIZE - | ||
33 | (cluster_offset / QCOW2_COMPRESSED_SECTOR_SIZE); | ||
34 | |||
35 | + /* The offset and size must fit in their fields of the L2 table entry */ | ||
36 | + assert((cluster_offset & s->cluster_offset_mask) == cluster_offset); | ||
37 | + assert((nb_csectors & s->csize_mask) == nb_csectors); | ||
38 | + | ||
39 | cluster_offset |= QCOW_OFLAG_COMPRESSED | | ||
40 | ((uint64_t)nb_csectors << s->csize_shift); | ||
41 | |||
42 | @@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) | ||
43 | |||
44 | assert(l2_index + m->nb_clusters <= s->l2_slice_size); | ||
45 | for (i = 0; i < m->nb_clusters; i++) { | ||
46 | + uint64_t offset = cluster_offset + (i << s->cluster_bits); | ||
47 | /* if two concurrent writes happen to the same unallocated cluster | ||
48 | * each write allocates separate cluster and writes data concurrently. | ||
49 | * The first one to complete updates l2 table with pointer to its | ||
50 | @@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) | ||
51 | old_cluster[j++] = l2_slice[l2_index + i]; | ||
52 | } | ||
53 | |||
54 | - l2_slice[l2_index + i] = cpu_to_be64((cluster_offset + | ||
55 | - (i << s->cluster_bits)) | QCOW_OFLAG_COPIED); | ||
56 | + /* The offset must fit in the offset field of the L2 table entry */ | ||
57 | + assert((offset & L2E_OFFSET_MASK) == offset); | ||
58 | + | ||
59 | + l2_slice[l2_index + i] = cpu_to_be64(offset | QCOW_OFLAG_COPIED); | ||
60 | } | ||
61 | |||
62 | |||
63 | @@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, | ||
64 | goto fail; | ||
65 | } | ||
66 | |||
67 | + /* The offset must fit in the offset field */ | ||
68 | + assert((offset & L2E_OFFSET_MASK) == offset); | ||
69 | + | ||
70 | if (l2_refcount > 1) { | ||
71 | /* For shared L2 tables, set the refcount accordingly | ||
72 | * (it is already 1 and needs to be l2_refcount) */ | ||
73 | -- | ||
74 | 2.24.1 | ||
75 | |||
76 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
1 | 2 | ||
3 | This is a bit more efficient than having to allocate and free memory | ||
4 | for each new permission. | ||
5 | |||
6 | The default size (30) is enough for "consistent read, write, resize". | ||
7 | |||
8 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
9 | Message-id: 20200110171518.22168-1-berto@igalia.com | ||
10 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
11 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
12 | --- | ||
13 | block.c | 11 ++++++----- | ||
14 | 1 file changed, 6 insertions(+), 5 deletions(-) | ||
15 | |||
16 | diff --git a/block.c b/block.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/block.c | ||
19 | +++ b/block.c | ||
20 | @@ -XXX,XX +XXX,XX @@ char *bdrv_perm_names(uint64_t perm) | ||
21 | { 0, NULL } | ||
22 | }; | ||
23 | |||
24 | - char *result = g_strdup(""); | ||
25 | + GString *result = g_string_sized_new(30); | ||
26 | struct perm_name *p; | ||
27 | |||
28 | for (p = permissions; p->name; p++) { | ||
29 | if (perm & p->perm) { | ||
30 | - char *old = result; | ||
31 | - result = g_strdup_printf("%s%s%s", old, *old ? ", " : "", p->name); | ||
32 | - g_free(old); | ||
33 | + if (result->len > 0) { | ||
34 | + g_string_append(result, ", "); | ||
35 | + } | ||
36 | + g_string_append(result, p->name); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | - return result; | ||
41 | + return g_string_free(result, FALSE); | ||
42 | } | ||
43 | |||
44 | /* | ||
45 | -- | ||
46 | 2.24.1 | ||
47 | |||
48 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Pan Nengyuan <pannengyuan@huawei.com> | ||
1 | 2 | ||
3 | If we call the qmp 'query-block' while qemu is working on | ||
4 | 'block-commit', it will cause memleaks, the memory leak stack is as | ||
5 | follow: | ||
6 | |||
7 | Indirect leak of 12360 byte(s) in 3 object(s) allocated from: | ||
8 | #0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) | ||
9 | #1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) | ||
10 | #2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu-4.2.0-rc0/qobject/qdict.c:29 | ||
11 | #3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6427 | ||
12 | #4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | ||
13 | #5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | ||
14 | #6 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | ||
15 | #7 0x55ea958818ea in bdrv_block_device_info /mnt/sdb/qemu-4.2.0-rc0/block/qapi.c:56 | ||
16 | #8 0x55ea958879de in bdrv_query_info /mnt/sdb/qemu-4.2.0-rc0/block/qapi.c:392 | ||
17 | #9 0x55ea9588b58f in qmp_query_block /mnt/sdb/qemu-4.2.0-rc0/block/qapi.c:578 | ||
18 | #10 0x55ea95567392 in qmp_marshal_query_block qapi/qapi-commands-block-core.c:95 | ||
19 | |||
20 | Indirect leak of 4120 byte(s) in 1 object(s) allocated from: | ||
21 | #0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) | ||
22 | #1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) | ||
23 | #2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu-4.2.0-rc0/qobject/qdict.c:29 | ||
24 | #3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6427 | ||
25 | #4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | ||
26 | #5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | ||
27 | #6 0x55ea9569f301 in bdrv_backing_attach /mnt/sdb/qemu-4.2.0-rc0/block.c:1064 | ||
28 | #7 0x55ea956a99dd in bdrv_replace_child_noperm /mnt/sdb/qemu-4.2.0-rc0/block.c:2283 | ||
29 | #8 0x55ea956b9b53 in bdrv_replace_node /mnt/sdb/qemu-4.2.0-rc0/block.c:4196 | ||
30 | #9 0x55ea956b9e49 in bdrv_append /mnt/sdb/qemu-4.2.0-rc0/block.c:4236 | ||
31 | #10 0x55ea958c3472 in commit_start /mnt/sdb/qemu-4.2.0-rc0/block/commit.c:306 | ||
32 | #11 0x55ea94b68ab0 in qmp_block_commit /mnt/sdb/qemu-4.2.0-rc0/blockdev.c:3459 | ||
33 | #12 0x55ea9556a7a7 in qmp_marshal_block_commit qapi/qapi-commands-block-core.c:407 | ||
34 | |||
35 | Fixes: bb808d5f5c0978828a974d547e6032402c339555 | ||
36 | Reported-by: Euler Robot <euler.robot@huawei.com> | ||
37 | Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com> | ||
38 | Message-id: 20200116085600.24056-1-pannengyuan@huawei.com | ||
39 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
40 | --- | ||
41 | block.c | 1 + | ||
42 | 1 file changed, 1 insertion(+) | ||
43 | |||
44 | diff --git a/block.c b/block.c | ||
45 | index XXXXXXX..XXXXXXX 100644 | ||
46 | --- a/block.c | ||
47 | +++ b/block.c | ||
48 | @@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs) | ||
49 | child->bs->exact_filename); | ||
50 | pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename); | ||
51 | |||
52 | + qobject_unref(bs->full_open_options); | ||
53 | bs->full_open_options = qobject_ref(child->bs->full_open_options); | ||
54 | |||
55 | return; | ||
56 | -- | ||
57 | 2.24.1 | ||
58 | |||
59 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
1 | 2 | ||
3 | This is a bit more efficient than having to allocate and free memory | ||
4 | for each item. | ||
5 | |||
6 | The default size (60) is enough for all the existing incompatible | ||
7 | features or the "Unknown incompatible feature" message. | ||
8 | |||
9 | Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
10 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
11 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
12 | Message-id: 20200115135626.19442-1-berto@igalia.com | ||
13 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
14 | Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> | ||
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
16 | --- | ||
17 | block/qcow2.c | 23 +++++++++++------------ | ||
18 | 1 file changed, 11 insertions(+), 12 deletions(-) | ||
19 | |||
20 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/block/qcow2.c | ||
23 | +++ b/block/qcow2.c | ||
24 | @@ -XXX,XX +XXX,XX @@ static void cleanup_unknown_header_ext(BlockDriverState *bs) | ||
25 | static void report_unsupported_feature(Error **errp, Qcow2Feature *table, | ||
26 | uint64_t mask) | ||
27 | { | ||
28 | - char *features = g_strdup(""); | ||
29 | - char *old; | ||
30 | + g_autoptr(GString) features = g_string_sized_new(60); | ||
31 | |||
32 | while (table && table->name[0] != '\0') { | ||
33 | if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) { | ||
34 | if (mask & (1ULL << table->bit)) { | ||
35 | - old = features; | ||
36 | - features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "", | ||
37 | - table->name); | ||
38 | - g_free(old); | ||
39 | + if (features->len > 0) { | ||
40 | + g_string_append(features, ", "); | ||
41 | + } | ||
42 | + g_string_append_printf(features, "%.46s", table->name); | ||
43 | mask &= ~(1ULL << table->bit); | ||
44 | } | ||
45 | } | ||
46 | @@ -XXX,XX +XXX,XX @@ static void report_unsupported_feature(Error **errp, Qcow2Feature *table, | ||
47 | } | ||
48 | |||
49 | if (mask) { | ||
50 | - old = features; | ||
51 | - features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64, | ||
52 | - old, *old ? ", " : "", mask); | ||
53 | - g_free(old); | ||
54 | + if (features->len > 0) { | ||
55 | + g_string_append(features, ", "); | ||
56 | + } | ||
57 | + g_string_append_printf(features, | ||
58 | + "Unknown incompatible feature: %" PRIx64, mask); | ||
59 | } | ||
60 | |||
61 | - error_setg(errp, "Unsupported qcow2 feature(s): %s", features); | ||
62 | - g_free(features); | ||
63 | + error_setg(errp, "Unsupported qcow2 feature(s): %s", features->str); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | -- | ||
68 | 2.24.1 | ||
69 | |||
70 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: John Snow <jsnow@redhat.com> | ||
1 | 2 | ||
3 | verify_platform will check an explicit whitelist and blacklist instead. | ||
4 | The default will now be assumed to be allowed to run anywhere. | ||
5 | |||
6 | For tests that do not specify their platforms explicitly, this has the effect of | ||
7 | enabling these tests on non-linux platforms. For tests that always specified | ||
8 | linux explicitly, there is no change. | ||
9 | |||
10 | For Python tests on FreeBSD at least; only seven python tests fail: | ||
11 | 045 147 149 169 194 199 211 | ||
12 | |||
13 | 045 and 149 appear to be misconfigurations, | ||
14 | 147 and 194 are the AF_UNIX path too long error, | ||
15 | 169 and 199 are bitmap migration bugs, and | ||
16 | 211 is a bug that shows up on Linux platforms, too. | ||
17 | |||
18 | This is at least good evidence that these tests are not Linux-only. If | ||
19 | they aren't suitable for other platforms, they should be disabled on a | ||
20 | per-platform basis as appropriate. | ||
21 | |||
22 | Therefore, let's switch these on and deal with the failures. | ||
23 | |||
24 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
25 | Signed-off-by: John Snow <jsnow@redhat.com> | ||
26 | Message-id: 20200121095205.26323-2-thuth@redhat.com | ||
27 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
28 | --- | ||
29 | tests/qemu-iotests/iotests.py | 16 +++++++++++----- | ||
30 | 1 file changed, 11 insertions(+), 5 deletions(-) | ||
31 | |||
32 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
33 | index XXXXXXX..XXXXXXX 100644 | ||
34 | --- a/tests/qemu-iotests/iotests.py | ||
35 | +++ b/tests/qemu-iotests/iotests.py | ||
36 | @@ -XXX,XX +XXX,XX @@ def verify_protocol(supported=[], unsupported=[]): | ||
37 | if not_sup or (imgproto in unsupported): | ||
38 | notrun('not suitable for this protocol: %s' % imgproto) | ||
39 | |||
40 | -def verify_platform(supported_oses=['linux']): | ||
41 | - if True not in [sys.platform.startswith(x) for x in supported_oses]: | ||
42 | - notrun('not suitable for this OS: %s' % sys.platform) | ||
43 | +def verify_platform(supported=None, unsupported=None): | ||
44 | + if unsupported is not None: | ||
45 | + if any((sys.platform.startswith(x) for x in unsupported)): | ||
46 | + notrun('not suitable for this OS: %s' % sys.platform) | ||
47 | + | ||
48 | + if supported is not None: | ||
49 | + if not any((sys.platform.startswith(x) for x in supported)): | ||
50 | + notrun('not suitable for this OS: %s' % sys.platform) | ||
51 | |||
52 | def verify_cache_mode(supported_cache_modes=[]): | ||
53 | if supported_cache_modes and (cachemode not in supported_cache_modes): | ||
54 | @@ -XXX,XX +XXX,XX @@ def execute_unittest(output, verbosity, debug): | ||
55 | sys.stderr.write(out) | ||
56 | |||
57 | def execute_test(test_function=None, | ||
58 | - supported_fmts=[], supported_oses=['linux'], | ||
59 | + supported_fmts=[], | ||
60 | + supported_platforms=None, | ||
61 | supported_cache_modes=[], supported_aio_modes={}, | ||
62 | unsupported_fmts=[], supported_protocols=[], | ||
63 | unsupported_protocols=[]): | ||
64 | @@ -XXX,XX +XXX,XX @@ def execute_test(test_function=None, | ||
65 | verbosity = 1 | ||
66 | verify_image_format(supported_fmts, unsupported_fmts) | ||
67 | verify_protocol(supported_protocols, unsupported_protocols) | ||
68 | - verify_platform(supported_oses) | ||
69 | + verify_platform(supported=supported_platforms) | ||
70 | verify_cache_mode(supported_cache_modes) | ||
71 | verify_aio_mode(supported_aio_modes) | ||
72 | |||
73 | -- | ||
74 | 2.24.1 | ||
75 | |||
76 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
1 | 2 | ||
3 | 041 works fine on Linux, FreeBSD, NetBSD and OpenBSD, but fails on macOS. | ||
4 | Let's mark it as only supported on the systems where we know that it is | ||
5 | working fine. | ||
6 | |||
7 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
8 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
9 | Message-id: 20200121095205.26323-3-thuth@redhat.com | ||
10 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
11 | --- | ||
12 | tests/qemu-iotests/041 | 3 ++- | ||
13 | 1 file changed, 2 insertions(+), 1 deletion(-) | ||
14 | |||
15 | diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 | ||
16 | index XXXXXXX..XXXXXXX 100755 | ||
17 | --- a/tests/qemu-iotests/041 | ||
18 | +++ b/tests/qemu-iotests/041 | ||
19 | @@ -XXX,XX +XXX,XX @@ class TestOrphanedSource(iotests.QMPTestCase): | ||
20 | |||
21 | if __name__ == '__main__': | ||
22 | iotests.main(supported_fmts=['qcow2', 'qed'], | ||
23 | - supported_protocols=['file']) | ||
24 | + supported_protocols=['file'], | ||
25 | + supported_platforms=['linux', 'freebsd', 'netbsd', 'openbsd']) | ||
26 | -- | ||
27 | 2.24.1 | ||
28 | |||
29 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
1 | 2 | ||
3 | In the long run, we might want to add test 183 to the "auto" group | ||
4 | (but it still fails occasionally, so we cannot do that yet). However, | ||
5 | when running 183 in Cirrus-CI on macOS, or with our vm-build-openbsd | ||
6 | target, it currently always fails with an "Timeout waiting for return | ||
7 | on handle 0" error. | ||
8 | |||
9 | Let's mark it as supported only on systems where the test is working | ||
10 | most of the time (i.e. Linux, FreeBSD and NetBSD). | ||
11 | |||
12 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
13 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
14 | Message-id: 20200121095205.26323-4-thuth@redhat.com | ||
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
16 | --- | ||
17 | tests/qemu-iotests/183 | 1 + | ||
18 | 1 file changed, 1 insertion(+) | ||
19 | |||
20 | diff --git a/tests/qemu-iotests/183 b/tests/qemu-iotests/183 | ||
21 | index XXXXXXX..XXXXXXX 100755 | ||
22 | --- a/tests/qemu-iotests/183 | ||
23 | +++ b/tests/qemu-iotests/183 | ||
24 | @@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
25 | . ./common.filter | ||
26 | . ./common.qemu | ||
27 | |||
28 | +_supported_os Linux FreeBSD NetBSD | ||
29 | _supported_fmt qcow2 raw qed quorum | ||
30 | _supported_proto file | ||
31 | |||
32 | -- | ||
33 | 2.24.1 | ||
34 | |||
35 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
1 | 2 | ||
3 | We are going to enable 127 in the "auto" group, but it only works if | ||
4 | virtio-scsi and scsi-hd are available - which is not the case with | ||
5 | QEMU binaries like qemu-system-tricore for example, so we need a | ||
6 | proper check for the availability of these devices here. | ||
7 | |||
8 | A very similar problem exists in iotest 267 - it has been added to | ||
9 | the "auto" group already, but requires virtio-blk and thus currently | ||
10 | fails with qemu-system-tricore for example. Let's also add aproper | ||
11 | check there. | ||
12 | |||
13 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
14 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
15 | Message-id: 20200121095205.26323-5-thuth@redhat.com | ||
16 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
17 | --- | ||
18 | tests/qemu-iotests/127 | 2 ++ | ||
19 | tests/qemu-iotests/267 | 2 ++ | ||
20 | tests/qemu-iotests/common.rc | 14 ++++++++++++++ | ||
21 | 3 files changed, 18 insertions(+) | ||
22 | |||
23 | diff --git a/tests/qemu-iotests/127 b/tests/qemu-iotests/127 | ||
24 | index XXXXXXX..XXXXXXX 100755 | ||
25 | --- a/tests/qemu-iotests/127 | ||
26 | +++ b/tests/qemu-iotests/127 | ||
27 | @@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
28 | _supported_fmt qcow2 | ||
29 | _supported_proto file | ||
30 | |||
31 | +_require_devices virtio-scsi scsi-hd | ||
32 | + | ||
33 | IMG_SIZE=64K | ||
34 | |||
35 | _make_test_img $IMG_SIZE | ||
36 | diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267 | ||
37 | index XXXXXXX..XXXXXXX 100755 | ||
38 | --- a/tests/qemu-iotests/267 | ||
39 | +++ b/tests/qemu-iotests/267 | ||
40 | @@ -XXX,XX +XXX,XX @@ _require_drivers copy-on-read | ||
41 | # and generally impossible with external data files | ||
42 | _unsupported_imgopts 'refcount_bits=1[^0-9]' data_file | ||
43 | |||
44 | +_require_devices virtio-blk | ||
45 | + | ||
46 | do_run_qemu() | ||
47 | { | ||
48 | echo Testing: "$@" | ||
49 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc | ||
50 | index XXXXXXX..XXXXXXX 100644 | ||
51 | --- a/tests/qemu-iotests/common.rc | ||
52 | +++ b/tests/qemu-iotests/common.rc | ||
53 | @@ -XXX,XX +XXX,XX @@ _require_large_file() | ||
54 | rm "$TEST_IMG" | ||
55 | } | ||
56 | |||
57 | +# Check that a set of devices is available in the QEMU binary | ||
58 | +# | ||
59 | +_require_devices() | ||
60 | +{ | ||
61 | + available=$($QEMU -M none -device help | \ | ||
62 | + grep ^name | sed -e 's/^name "//' -e 's/".*$//') | ||
63 | + for device | ||
64 | + do | ||
65 | + if ! echo "$available" | grep -q "$device" ; then | ||
66 | + _notrun "$device not available" | ||
67 | + fi | ||
68 | + done | ||
69 | +} | ||
70 | + | ||
71 | # make sure this script returns success | ||
72 | true | ||
73 | -- | ||
74 | 2.24.1 | ||
75 | |||
76 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
1 | 2 | ||
3 | We are going to enable some of the python-based tests in the "auto" group, | ||
4 | and these tests require virtio-blk to work properly. Running iotests | ||
5 | without virtio-blk likely does not make too much sense anyway, so instead | ||
6 | of adding a check for the availability of virtio-blk to each and every | ||
7 | test (which does not sound very appealing), let's rather add a check for | ||
8 | this a central spot in the "check" script instead (so that it is still | ||
9 | possible to run "make check" for qemu-system-tricore for example). | ||
10 | |||
11 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
12 | Message-id: 20200121095205.26323-6-thuth@redhat.com | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | tests/qemu-iotests/check | 12 ++++++++++-- | ||
16 | 1 file changed, 10 insertions(+), 2 deletions(-) | ||
17 | |||
18 | diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check | ||
19 | index XXXXXXX..XXXXXXX 100755 | ||
20 | --- a/tests/qemu-iotests/check | ||
21 | +++ b/tests/qemu-iotests/check | ||
22 | @@ -XXX,XX +XXX,XX @@ fi | ||
23 | python_usable=false | ||
24 | if $PYTHON -c 'import sys; sys.exit(0 if sys.version_info >= (3,6) else 1)' | ||
25 | then | ||
26 | - python_usable=true | ||
27 | + # Our python framework also requires virtio-blk | ||
28 | + if "$QEMU_PROG" -M none -device help | grep -q virtio-blk >/dev/null 2>&1 | ||
29 | + then | ||
30 | + python_usable=true | ||
31 | + else | ||
32 | + python_unusable_because="Missing virtio-blk in QEMU binary" | ||
33 | + fi | ||
34 | +else | ||
35 | + python_unusable_because="Unsupported Python version" | ||
36 | fi | ||
37 | |||
38 | default_machine=$($QEMU_PROG -machine help | sed -n '/(default)/ s/ .*//p') | ||
39 | @@ -XXX,XX +XXX,XX @@ do | ||
40 | run_command="$PYTHON $seq" | ||
41 | else | ||
42 | run_command="false" | ||
43 | - echo "Unsupported Python version" > $seq.notrun | ||
44 | + echo "$python_unusable_because" > $seq.notrun | ||
45 | fi | ||
46 | else | ||
47 | run_command="./$seq" | ||
48 | -- | ||
49 | 2.24.1 | ||
50 | |||
51 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
1 | 2 | ||
3 | According to Kevin, tests 030, 040 and 041 are among the most valuable | ||
4 | tests that we have, so we should always run them if possible, even if | ||
5 | they take a little bit longer. | ||
6 | |||
7 | According to Max, it would be good to have a test for iothreads and | ||
8 | migration. 127 and 256 seem to be good candidates for iothreads. For | ||
9 | migration, let's enable 181 and 203 (which also tests iothreads). | ||
10 | (091 would be a good candidate for migration, too, but Alex Bennée | ||
11 | reported that this test fails on ZFS file systems, so it can't be | ||
12 | included yet) | ||
13 | |||
14 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
15 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
16 | Message-id: 20200121095205.26323-7-thuth@redhat.com | ||
17 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
18 | --- | ||
19 | tests/qemu-iotests/group | 14 +++++++------- | ||
20 | 1 file changed, 7 insertions(+), 7 deletions(-) | ||
21 | |||
22 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/tests/qemu-iotests/group | ||
25 | +++ b/tests/qemu-iotests/group | ||
26 | @@ -XXX,XX +XXX,XX @@ | ||
27 | 027 rw auto quick | ||
28 | 028 rw backing quick | ||
29 | 029 rw auto quick | ||
30 | -030 rw backing | ||
31 | +030 rw auto backing | ||
32 | 031 rw auto quick | ||
33 | 032 rw auto quick | ||
34 | 033 rw auto quick | ||
35 | @@ -XXX,XX +XXX,XX @@ | ||
36 | 037 rw auto backing quick | ||
37 | 038 rw auto backing quick | ||
38 | 039 rw auto quick | ||
39 | -040 rw | ||
40 | -041 rw backing | ||
41 | +040 rw auto | ||
42 | +041 rw auto backing | ||
43 | 042 rw auto quick | ||
44 | 043 rw auto backing | ||
45 | 044 rw | ||
46 | @@ -XXX,XX +XXX,XX @@ | ||
47 | 124 rw backing | ||
48 | 125 rw | ||
49 | 126 rw auto backing | ||
50 | -127 rw backing quick | ||
51 | +127 rw auto backing quick | ||
52 | 128 rw quick | ||
53 | 129 rw quick | ||
54 | 130 rw quick | ||
55 | @@ -XXX,XX +XXX,XX @@ | ||
56 | 177 rw auto quick | ||
57 | 178 img | ||
58 | 179 rw auto quick | ||
59 | -181 rw migration | ||
60 | +181 rw auto migration | ||
61 | 182 rw quick | ||
62 | 183 rw migration | ||
63 | 184 rw auto quick | ||
64 | @@ -XXX,XX +XXX,XX @@ | ||
65 | 200 rw | ||
66 | 201 rw migration | ||
67 | 202 rw quick | ||
68 | -203 rw migration | ||
69 | +203 rw auto migration | ||
70 | 204 rw quick | ||
71 | 205 rw quick | ||
72 | 206 rw | ||
73 | @@ -XXX,XX +XXX,XX @@ | ||
74 | 253 rw quick | ||
75 | 254 rw backing quick | ||
76 | 255 rw quick | ||
77 | -256 rw quick | ||
78 | +256 rw auto quick | ||
79 | 257 rw | ||
80 | 258 rw quick | ||
81 | 260 rw quick | ||
82 | -- | ||
83 | 2.24.1 | ||
84 | |||
85 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
1 | 2 | ||
3 | The L1 table is read from disk using the byte-based bdrv_pread() and | ||
4 | is never accessed beyond its last element, so there's no need to | ||
5 | allocate more memory than that. | ||
6 | |||
7 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
8 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
9 | Message-id: b2e27214ec7b03a585931bcf383ee1ac3a641a10.1579374329.git.berto@igalia.com | ||
10 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
11 | --- | ||
12 | block/qcow2-cluster.c | 5 ++--- | ||
13 | block/qcow2-refcount.c | 2 +- | ||
14 | block/qcow2-snapshot.c | 3 +-- | ||
15 | block/qcow2.c | 2 +- | ||
16 | 4 files changed, 5 insertions(+), 7 deletions(-) | ||
17 | |||
18 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/qcow2-cluster.c | ||
21 | +++ b/block/qcow2-cluster.c | ||
22 | @@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | ||
23 | #endif | ||
24 | |||
25 | new_l1_size2 = sizeof(uint64_t) * new_l1_size; | ||
26 | - new_l1_table = qemu_try_blockalign(bs->file->bs, | ||
27 | - ROUND_UP(new_l1_size2, 512)); | ||
28 | + new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_size2); | ||
29 | if (new_l1_table == NULL) { | ||
30 | return -ENOMEM; | ||
31 | } | ||
32 | - memset(new_l1_table, 0, ROUND_UP(new_l1_size2, 512)); | ||
33 | + memset(new_l1_table, 0, new_l1_size2); | ||
34 | |||
35 | if (s->l1_size) { | ||
36 | memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); | ||
37 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/block/qcow2-refcount.c | ||
40 | +++ b/block/qcow2-refcount.c | ||
41 | @@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, | ||
42 | * l1_table_offset when it is the current s->l1_table_offset! Be careful | ||
43 | * when changing this! */ | ||
44 | if (l1_table_offset != s->l1_table_offset) { | ||
45 | - l1_table = g_try_malloc0(ROUND_UP(l1_size2, 512)); | ||
46 | + l1_table = g_try_malloc0(l1_size2); | ||
47 | if (l1_size2 && l1_table == NULL) { | ||
48 | ret = -ENOMEM; | ||
49 | goto fail; | ||
50 | diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c | ||
51 | index XXXXXXX..XXXXXXX 100644 | ||
52 | --- a/block/qcow2-snapshot.c | ||
53 | +++ b/block/qcow2-snapshot.c | ||
54 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, | ||
55 | return ret; | ||
56 | } | ||
57 | new_l1_bytes = sn->l1_size * sizeof(uint64_t); | ||
58 | - new_l1_table = qemu_try_blockalign(bs->file->bs, | ||
59 | - ROUND_UP(new_l1_bytes, 512)); | ||
60 | + new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_bytes); | ||
61 | if (new_l1_table == NULL) { | ||
62 | return -ENOMEM; | ||
63 | } | ||
64 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
65 | index XXXXXXX..XXXXXXX 100644 | ||
66 | --- a/block/qcow2.c | ||
67 | +++ b/block/qcow2.c | ||
68 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, | ||
69 | |||
70 | if (s->l1_size > 0) { | ||
71 | s->l1_table = qemu_try_blockalign(bs->file->bs, | ||
72 | - ROUND_UP(s->l1_size * sizeof(uint64_t), 512)); | ||
73 | + s->l1_size * sizeof(uint64_t)); | ||
74 | if (s->l1_table == NULL) { | ||
75 | error_setg(errp, "Could not allocate L1 table"); | ||
76 | ret = -ENOMEM; | ||
77 | -- | ||
78 | 2.24.1 | ||
79 | |||
80 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
1 | 2 | ||
3 | qcow2_alloc_cluster_offset() and qcow2_get_cluster_offset() always | ||
4 | return offsets that are cluster-aligned so don't just check that they | ||
5 | are sector-aligned. | ||
6 | |||
7 | The check in qcow2_co_preadv_task() is also replaced by an assertion | ||
8 | for the same reason. | ||
9 | |||
10 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
11 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
12 | Message-id: 558ba339965f858bede4c73ce3f50f0c0493597d.1579374329.git.berto@igalia.com | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | block/qcow2.c | 9 +++------ | ||
16 | 1 file changed, 3 insertions(+), 6 deletions(-) | ||
17 | |||
18 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/qcow2.c | ||
21 | +++ b/block/qcow2.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs, | ||
23 | offset, bytes, qiov, qiov_offset); | ||
24 | |||
25 | case QCOW2_CLUSTER_NORMAL: | ||
26 | - if ((file_cluster_offset & 511) != 0) { | ||
27 | - return -EIO; | ||
28 | - } | ||
29 | - | ||
30 | + assert(offset_into_cluster(s, file_cluster_offset) == 0); | ||
31 | if (bs->encrypted) { | ||
32 | return qcow2_co_preadv_encrypted(bs, file_cluster_offset, | ||
33 | offset, bytes, qiov, qiov_offset); | ||
34 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part( | ||
35 | goto out_locked; | ||
36 | } | ||
37 | |||
38 | - assert((cluster_offset & 511) == 0); | ||
39 | + assert(offset_into_cluster(s, cluster_offset) == 0); | ||
40 | |||
41 | ret = qcow2_pre_write_overlap_check(bs, 0, | ||
42 | cluster_offset + offset_in_cluster, | ||
43 | @@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs, | ||
44 | goto fail; | ||
45 | } | ||
46 | |||
47 | - assert((cluster_offset & 511) == 0); | ||
48 | + assert(offset_into_cluster(s, cluster_offset) == 0); | ||
49 | |||
50 | ret = qcow2_pre_write_overlap_check(bs, 0, | ||
51 | cluster_offset + offset_in_cluster, cur_bytes, true); | ||
52 | -- | ||
53 | 2.24.1 | ||
54 | |||
55 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
1 | 2 | ||
3 | When updating an L1 entry the qcow2 driver writes a (512-byte) sector | ||
4 | worth of data to avoid a read-modify-write cycle. Instead of always | ||
5 | writing 512 bytes we should follow the alignment requirements of the | ||
6 | storage backend. | ||
7 | |||
8 | (the only exception is when the alignment is larger than the cluster | ||
9 | size because then we could be overwriting data after the L1 table) | ||
10 | |||
11 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
12 | Message-id: 71f34d4ae4b367b32fb36134acbf4f4f7ee681f4.1579374329.git.berto@igalia.com | ||
13 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
14 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
15 | --- | ||
16 | block/qcow2-cluster.c | 25 +++++++++++++++---------- | ||
17 | 1 file changed, 15 insertions(+), 10 deletions(-) | ||
18 | |||
19 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/block/qcow2-cluster.c | ||
22 | +++ b/block/qcow2-cluster.c | ||
23 | @@ -XXX,XX +XXX,XX @@ static int l2_load(BlockDriverState *bs, uint64_t offset, | ||
24 | } | ||
25 | |||
26 | /* | ||
27 | - * Writes one sector of the L1 table to the disk (can't update single entries | ||
28 | - * and we really don't want bdrv_pread to perform a read-modify-write) | ||
29 | + * Writes an L1 entry to disk (note that depending on the alignment | ||
30 | + * requirements this function may write more that just one entry in | ||
31 | + * order to prevent bdrv_pwrite from performing a read-modify-write) | ||
32 | */ | ||
33 | -#define L1_ENTRIES_PER_SECTOR (512 / 8) | ||
34 | int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) | ||
35 | { | ||
36 | BDRVQcow2State *s = bs->opaque; | ||
37 | - uint64_t buf[L1_ENTRIES_PER_SECTOR] = { 0 }; | ||
38 | int l1_start_index; | ||
39 | int i, ret; | ||
40 | + int bufsize = MAX(sizeof(uint64_t), | ||
41 | + MIN(bs->file->bs->bl.request_alignment, s->cluster_size)); | ||
42 | + int nentries = bufsize / sizeof(uint64_t); | ||
43 | + g_autofree uint64_t *buf = g_try_new0(uint64_t, nentries); | ||
44 | |||
45 | - l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1); | ||
46 | - for (i = 0; i < L1_ENTRIES_PER_SECTOR && l1_start_index + i < s->l1_size; | ||
47 | - i++) | ||
48 | - { | ||
49 | + if (buf == NULL) { | ||
50 | + return -ENOMEM; | ||
51 | + } | ||
52 | + | ||
53 | + l1_start_index = QEMU_ALIGN_DOWN(l1_index, nentries); | ||
54 | + for (i = 0; i < MIN(nentries, s->l1_size - l1_start_index); i++) { | ||
55 | buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]); | ||
56 | } | ||
57 | |||
58 | ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1, | ||
59 | - s->l1_table_offset + 8 * l1_start_index, sizeof(buf), false); | ||
60 | + s->l1_table_offset + 8 * l1_start_index, bufsize, false); | ||
61 | if (ret < 0) { | ||
62 | return ret; | ||
63 | } | ||
64 | @@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) | ||
65 | BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); | ||
66 | ret = bdrv_pwrite_sync(bs->file, | ||
67 | s->l1_table_offset + 8 * l1_start_index, | ||
68 | - buf, sizeof(buf)); | ||
69 | + buf, bufsize); | ||
70 | if (ret < 0) { | ||
71 | return ret; | ||
72 | } | ||
73 | -- | ||
74 | 2.24.1 | ||
75 | |||
76 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
1 | 2 | ||
3 | qemu-img's convert_co_copy_range() operates at the sector level and | ||
4 | block_copy() operates at the cluster level so this condition is always | ||
5 | true, but it is not necessary to restrict this here, so let's leave it | ||
6 | to the driver implementation return an error if there is any. | ||
7 | |||
8 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
9 | Message-id: a4264aaee656910c84161a2965f7a501437379ca.1579374329.git.berto@igalia.com | ||
10 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
11 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
12 | --- | ||
13 | block/qcow2.c | 4 ---- | ||
14 | 1 file changed, 4 deletions(-) | ||
15 | |||
16 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/block/qcow2.c | ||
19 | +++ b/block/qcow2.c | ||
20 | @@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs, | ||
21 | case QCOW2_CLUSTER_NORMAL: | ||
22 | child = s->data_file; | ||
23 | copy_offset += offset_into_cluster(s, src_offset); | ||
24 | - if ((copy_offset & 511) != 0) { | ||
25 | - ret = -EIO; | ||
26 | - goto out; | ||
27 | - } | ||
28 | break; | ||
29 | |||
30 | default: | ||
31 | -- | ||
32 | 2.24.1 | ||
33 | |||
34 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alberto Garcia <berto@igalia.com> | ||
1 | 2 | ||
3 | This replaces all remaining instances in the qcow2 code. | ||
4 | |||
5 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
6 | Message-id: b5f74b606c2d9873b12d29acdb7fd498029c4025.1579374329.git.berto@igalia.com | ||
7 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | ||
10 | block/qcow2.c | 8 +++++--- | ||
11 | 1 file changed, 5 insertions(+), 3 deletions(-) | ||
12 | |||
13 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/block/qcow2.c | ||
16 | +++ b/block/qcow2.c | ||
17 | @@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) | ||
18 | |||
19 | /* Validate options and set default values */ | ||
20 | if (!QEMU_IS_ALIGNED(qcow2_opts->size, BDRV_SECTOR_SIZE)) { | ||
21 | - error_setg(errp, "Image size must be a multiple of 512 bytes"); | ||
22 | + error_setg(errp, "Image size must be a multiple of %u bytes", | ||
23 | + (unsigned) BDRV_SECTOR_SIZE); | ||
24 | ret = -EINVAL; | ||
25 | goto out; | ||
26 | } | ||
27 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, | ||
28 | return -ENOTSUP; | ||
29 | } | ||
30 | |||
31 | - if (offset & 511) { | ||
32 | - error_setg(errp, "The new size must be a multiple of 512"); | ||
33 | + if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) { | ||
34 | + error_setg(errp, "The new size must be a multiple of %u", | ||
35 | + (unsigned) BDRV_SECTOR_SIZE); | ||
36 | return -EINVAL; | ||
37 | } | ||
38 | |||
39 | -- | ||
40 | 2.24.1 | ||
41 | |||
42 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
1 | 2 | ||
3 | We can't access top after call bdrv_backup_top_drop, as it is already | ||
4 | freed at this time. | ||
5 | |||
6 | Also, no needs to unref target child by hand, it will be unrefed on | ||
7 | bdrv_close() automatically. | ||
8 | |||
9 | So, just do bdrv_backup_top_drop if append succeed and one bdrv_unref | ||
10 | otherwise. | ||
11 | |||
12 | Note, that in !appended case bdrv_unref(top) moved into drained section | ||
13 | on source. It doesn't really matter, but just for code simplicity. | ||
14 | |||
15 | Fixes: 7df7868b96404 | ||
16 | Cc: qemu-stable@nongnu.org # v4.2.0 | ||
17 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
18 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
19 | Message-id: 20200121142802.21467-2-vsementsov@virtuozzo.com | ||
20 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
21 | --- | ||
22 | block/backup-top.c | 21 ++++++++++++--------- | ||
23 | 1 file changed, 12 insertions(+), 9 deletions(-) | ||
24 | |||
25 | diff --git a/block/backup-top.c b/block/backup-top.c | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/block/backup-top.c | ||
28 | +++ b/block/backup-top.c | ||
29 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | ||
30 | BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter, | ||
31 | filter_node_name, | ||
32 | BDRV_O_RDWR, errp); | ||
33 | + bool appended = false; | ||
34 | |||
35 | if (!top) { | ||
36 | return NULL; | ||
37 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | ||
38 | bdrv_append(top, source, &local_err); | ||
39 | if (local_err) { | ||
40 | error_prepend(&local_err, "Cannot append backup-top filter: "); | ||
41 | - goto append_failed; | ||
42 | + goto fail; | ||
43 | } | ||
44 | + appended = true; | ||
45 | |||
46 | /* | ||
47 | * bdrv_append() finished successfully, now we can require permissions | ||
48 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | ||
49 | if (local_err) { | ||
50 | error_prepend(&local_err, | ||
51 | "Cannot set permissions for backup-top filter: "); | ||
52 | - goto failed_after_append; | ||
53 | + goto fail; | ||
54 | } | ||
55 | |||
56 | state->bcs = block_copy_state_new(top->backing, state->target, | ||
57 | cluster_size, write_flags, &local_err); | ||
58 | if (local_err) { | ||
59 | error_prepend(&local_err, "Cannot create block-copy-state: "); | ||
60 | - goto failed_after_append; | ||
61 | + goto fail; | ||
62 | } | ||
63 | *bcs = state->bcs; | ||
64 | |||
65 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | ||
66 | |||
67 | return top; | ||
68 | |||
69 | -failed_after_append: | ||
70 | - state->active = false; | ||
71 | - bdrv_backup_top_drop(top); | ||
72 | +fail: | ||
73 | + if (appended) { | ||
74 | + state->active = false; | ||
75 | + bdrv_backup_top_drop(top); | ||
76 | + } else { | ||
77 | + bdrv_unref(top); | ||
78 | + } | ||
79 | |||
80 | -append_failed: | ||
81 | bdrv_drained_end(source); | ||
82 | - bdrv_unref_child(top, state->target); | ||
83 | - bdrv_unref(top); | ||
84 | error_propagate(errp, local_err); | ||
85 | |||
86 | return NULL; | ||
87 | -- | ||
88 | 2.24.1 | ||
89 | |||
90 | diff view generated by jsdifflib |
1 | Nested BDRV_POLL_WHILE() calls can occur. Currently | 1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
---|---|---|---|
2 | assert(!wait_->wakeup) fails in AIO_WAIT_WHILE() when this happens. | ||
3 | 2 | ||
4 | This patch converts the bool wait_->need_kick flag to an unsigned | 3 | This test checks that bug is really fixed by previous commit. |
5 | wait_->num_waiters counter. | ||
6 | 4 | ||
7 | Nesting works correctly because outer AIO_WAIT_WHILE() callers evaluate | 5 | Cc: qemu-stable@nongnu.org # v4.2.0 |
8 | the condition again after the inner caller completes (invoking the inner | 6 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
9 | caller counts as aio_poll() progress). | 7 | Message-id: 20200121142802.21467-3-vsementsov@virtuozzo.com |
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | ||
10 | tests/qemu-iotests/283 | 92 ++++++++++++++++++++++++++++++++++++++ | ||
11 | tests/qemu-iotests/283.out | 8 ++++ | ||
12 | tests/qemu-iotests/group | 1 + | ||
13 | 3 files changed, 101 insertions(+) | ||
14 | create mode 100644 tests/qemu-iotests/283 | ||
15 | create mode 100644 tests/qemu-iotests/283.out | ||
10 | 16 | ||
11 | Reported-by: "fuweiwei (C)" <fuweiwei2@huawei.com> | 17 | diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283 |
12 | Reviewed-by: Eric Blake <eblake@redhat.com> | 18 | new file mode 100644 |
13 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 19 | index XXXXXXX..XXXXXXX |
14 | Message-id: 20180307124619.6218-1-stefanha@redhat.com | 20 | --- /dev/null |
15 | Cc: Paolo Bonzini <pbonzini@redhat.com> | 21 | +++ b/tests/qemu-iotests/283 |
16 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 22 | @@ -XXX,XX +XXX,XX @@ |
17 | --- | 23 | +#!/usr/bin/env python |
18 | include/block/aio-wait.h | 61 ++++++++++++++++++++++++------------------------ | 24 | +# |
19 | util/aio-wait.c | 2 +- | 25 | +# Test for backup-top filter permission activation failure |
20 | 2 files changed, 31 insertions(+), 32 deletions(-) | 26 | +# |
21 | 27 | +# Copyright (c) 2019 Virtuozzo International GmbH. | |
22 | diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h | 28 | +# |
29 | +# This program is free software; you can redistribute it and/or modify | ||
30 | +# it under the terms of the GNU General Public License as published by | ||
31 | +# the Free Software Foundation; either version 2 of the License, or | ||
32 | +# (at your option) any later version. | ||
33 | +# | ||
34 | +# This program is distributed in the hope that it will be useful, | ||
35 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
36 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
37 | +# GNU General Public License for more details. | ||
38 | +# | ||
39 | +# You should have received a copy of the GNU General Public License | ||
40 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
41 | +# | ||
42 | + | ||
43 | +import iotests | ||
44 | + | ||
45 | +# The test is unrelated to formats, restrict it to qcow2 to avoid extra runs | ||
46 | +iotests.verify_image_format(supported_fmts=['qcow2']) | ||
47 | + | ||
48 | +size = 1024 * 1024 | ||
49 | + | ||
50 | +""" Test description | ||
51 | + | ||
52 | +When performing a backup, all writes on the source subtree must go through the | ||
53 | +backup-top filter so it can copy all data to the target before it is changed. | ||
54 | +backup-top filter is appended above source node, to achieve this thing, so all | ||
55 | +parents of source node are handled. A configuration with side parents of source | ||
56 | +sub-tree with write permission is unsupported (we'd have append several | ||
57 | +backup-top filter like nodes to handle such parents). The test create an | ||
58 | +example of such configuration and checks that a backup is then not allowed | ||
59 | +(blockdev-backup command should fail). | ||
60 | + | ||
61 | +The configuration: | ||
62 | + | ||
63 | + ┌────────┐ target ┌─────────────┐ | ||
64 | + │ target │ ◀─────── │ backup_top │ | ||
65 | + └────────┘ └─────────────┘ | ||
66 | + │ | ||
67 | + │ backing | ||
68 | + ▼ | ||
69 | + ┌─────────────┐ | ||
70 | + │ source │ | ||
71 | + └─────────────┘ | ||
72 | + │ | ||
73 | + │ file | ||
74 | + ▼ | ||
75 | + ┌─────────────┐ write perm ┌───────┐ | ||
76 | + │ base │ ◀──────────── │ other │ | ||
77 | + └─────────────┘ └───────┘ | ||
78 | + | ||
79 | +On activation (see .active field of backup-top state in block/backup-top.c), | ||
80 | +backup-top is going to unshare write permission on its source child. Write | ||
81 | +unsharing will be propagated to the "source->base" link and will conflict with | ||
82 | +other node write permission. So permission update will fail and backup job will | ||
83 | +not be started. | ||
84 | + | ||
85 | +Note, that the only thing which prevents backup of running on such | ||
86 | +configuration is default permission propagation scheme. It may be altered by | ||
87 | +different block drivers, so backup will run in invalid configuration. But | ||
88 | +something is better than nothing. Also, before the previous commit (commit | ||
89 | +preceding this test creation), starting backup on such configuration led to | ||
90 | +crash, so current "something" is a lot better, and this test actual goal is | ||
91 | +to check that crash is fixed :) | ||
92 | +""" | ||
93 | + | ||
94 | +vm = iotests.VM() | ||
95 | +vm.launch() | ||
96 | + | ||
97 | +vm.qmp_log('blockdev-add', **{'node-name': 'target', 'driver': 'null-co'}) | ||
98 | + | ||
99 | +vm.qmp_log('blockdev-add', **{ | ||
100 | + 'node-name': 'source', | ||
101 | + 'driver': 'blkdebug', | ||
102 | + 'image': {'node-name': 'base', 'driver': 'null-co', 'size': size} | ||
103 | +}) | ||
104 | + | ||
105 | +vm.qmp_log('blockdev-add', **{ | ||
106 | + 'node-name': 'other', | ||
107 | + 'driver': 'blkdebug', | ||
108 | + 'image': 'base', | ||
109 | + 'take-child-perms': ['write'] | ||
110 | +}) | ||
111 | + | ||
112 | +vm.qmp_log('blockdev-backup', sync='full', device='source', target='target') | ||
113 | + | ||
114 | +vm.shutdown() | ||
115 | diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out | ||
116 | new file mode 100644 | ||
117 | index XXXXXXX..XXXXXXX | ||
118 | --- /dev/null | ||
119 | +++ b/tests/qemu-iotests/283.out | ||
120 | @@ -XXX,XX +XXX,XX @@ | ||
121 | +{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "target"}} | ||
122 | +{"return": {}} | ||
123 | +{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": {"driver": "null-co", "node-name": "base", "size": 1048576}, "node-name": "source"}} | ||
124 | +{"return": {}} | ||
125 | +{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}} | ||
126 | +{"return": {}} | ||
127 | +{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}} | ||
128 | +{"error": {"class": "GenericError", "desc": "Cannot set permissions for backup-top filter: Conflicts with use by other as 'image', which uses 'write' on base"}} | ||
129 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
23 | index XXXXXXX..XXXXXXX 100644 | 130 | index XXXXXXX..XXXXXXX 100644 |
24 | --- a/include/block/aio-wait.h | 131 | --- a/tests/qemu-iotests/group |
25 | +++ b/include/block/aio-wait.h | 132 | +++ b/tests/qemu-iotests/group |
26 | @@ -XXX,XX +XXX,XX @@ | 133 | @@ -XXX,XX +XXX,XX @@ |
27 | * } | 134 | 279 rw backing quick |
28 | */ | 135 | 280 rw migration quick |
29 | typedef struct { | 136 | 281 rw quick |
30 | - /* Is the main loop waiting for a kick? Accessed with atomic ops. */ | 137 | +283 auto quick |
31 | - bool need_kick; | ||
32 | + /* Number of waiting AIO_WAIT_WHILE() callers. Accessed with atomic ops. */ | ||
33 | + unsigned num_waiters; | ||
34 | } AioWait; | ||
35 | |||
36 | /** | ||
37 | @@ -XXX,XX +XXX,XX @@ typedef struct { | ||
38 | * wait on conditions between two IOThreads since that could lead to deadlock, | ||
39 | * go via the main loop instead. | ||
40 | */ | ||
41 | -#define AIO_WAIT_WHILE(wait, ctx, cond) ({ \ | ||
42 | - bool waited_ = false; \ | ||
43 | - bool busy_ = true; \ | ||
44 | - AioWait *wait_ = (wait); \ | ||
45 | - AioContext *ctx_ = (ctx); \ | ||
46 | - if (in_aio_context_home_thread(ctx_)) { \ | ||
47 | - while ((cond) || busy_) { \ | ||
48 | - busy_ = aio_poll(ctx_, (cond)); \ | ||
49 | - waited_ |= !!(cond) | busy_; \ | ||
50 | - } \ | ||
51 | - } else { \ | ||
52 | - assert(qemu_get_current_aio_context() == \ | ||
53 | - qemu_get_aio_context()); \ | ||
54 | - assert(!wait_->need_kick); \ | ||
55 | - /* Set wait_->need_kick before evaluating cond. */ \ | ||
56 | - atomic_mb_set(&wait_->need_kick, true); \ | ||
57 | - while (busy_) { \ | ||
58 | - if ((cond)) { \ | ||
59 | - waited_ = busy_ = true; \ | ||
60 | - aio_context_release(ctx_); \ | ||
61 | - aio_poll(qemu_get_aio_context(), true); \ | ||
62 | - aio_context_acquire(ctx_); \ | ||
63 | - } else { \ | ||
64 | - busy_ = aio_poll(ctx_, false); \ | ||
65 | - waited_ |= busy_; \ | ||
66 | - } \ | ||
67 | - } \ | ||
68 | - atomic_set(&wait_->need_kick, false); \ | ||
69 | - } \ | ||
70 | +#define AIO_WAIT_WHILE(wait, ctx, cond) ({ \ | ||
71 | + bool waited_ = false; \ | ||
72 | + bool busy_ = true; \ | ||
73 | + AioWait *wait_ = (wait); \ | ||
74 | + AioContext *ctx_ = (ctx); \ | ||
75 | + if (in_aio_context_home_thread(ctx_)) { \ | ||
76 | + while ((cond) || busy_) { \ | ||
77 | + busy_ = aio_poll(ctx_, (cond)); \ | ||
78 | + waited_ |= !!(cond) | busy_; \ | ||
79 | + } \ | ||
80 | + } else { \ | ||
81 | + assert(qemu_get_current_aio_context() == \ | ||
82 | + qemu_get_aio_context()); \ | ||
83 | + /* Increment wait_->num_waiters before evaluating cond. */ \ | ||
84 | + atomic_inc(&wait_->num_waiters); \ | ||
85 | + while (busy_) { \ | ||
86 | + if ((cond)) { \ | ||
87 | + waited_ = busy_ = true; \ | ||
88 | + aio_context_release(ctx_); \ | ||
89 | + aio_poll(qemu_get_aio_context(), true); \ | ||
90 | + aio_context_acquire(ctx_); \ | ||
91 | + } else { \ | ||
92 | + busy_ = aio_poll(ctx_, false); \ | ||
93 | + waited_ |= busy_; \ | ||
94 | + } \ | ||
95 | + } \ | ||
96 | + atomic_dec(&wait_->num_waiters); \ | ||
97 | + } \ | ||
98 | waited_; }) | ||
99 | |||
100 | /** | ||
101 | diff --git a/util/aio-wait.c b/util/aio-wait.c | ||
102 | index XXXXXXX..XXXXXXX 100644 | ||
103 | --- a/util/aio-wait.c | ||
104 | +++ b/util/aio-wait.c | ||
105 | @@ -XXX,XX +XXX,XX @@ static void dummy_bh_cb(void *opaque) | ||
106 | void aio_wait_kick(AioWait *wait) | ||
107 | { | ||
108 | /* The barrier (or an atomic op) is in the caller. */ | ||
109 | - if (atomic_read(&wait->need_kick)) { | ||
110 | + if (atomic_read(&wait->num_waiters)) { | ||
111 | aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL); | ||
112 | } | ||
113 | } | ||
114 | -- | 138 | -- |
115 | 2.14.3 | 139 | 2.24.1 |
116 | 140 | ||
117 | 141 | diff view generated by jsdifflib |