1 | The following changes since commit 98b2faeaee96ab084d0b1669918688d8895c155f: | 1 | The following changes since commit 672f9d0df10a68a5c5f2b32cbc8284abf9f5ee18: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging (2017-02-10 18:07:02 +0000) | 3 | Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2020-02-18 14:23:43 +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/XanClic/qemu.git tags/pull-block-2017-02-12 | 7 | https://github.com/XanClic/qemu.git tags/pull-block-2020-02-20 |
8 | 8 | ||
9 | for you to fetch changes up to 10d6eda1926804a09aa0710ca62933087813de0b: | 9 | for you to fetch changes up to dff8d44c96f128480430b0c59ed8760917dbd427: |
10 | 10 | ||
11 | qemu-img: Avoid setting ret to unused value in img_convert() (2017-02-12 00:56:32 +0100) | 11 | iotests: Test snapshot -l field separation (2020-02-20 16:43:42 +0100) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block patches | 14 | Block patches: |
15 | - qemu-img convert: New --target-is-zero parameter | ||
16 | - qcow2: Specify non-default compression type flag | ||
17 | - optionally flat output for query-named-block-nodes | ||
18 | - some fixes | ||
19 | - pseudo-creation of images on block devices is now done by a generic | ||
20 | block layer function | ||
15 | 21 | ||
16 | ---------------------------------------------------------------- | 22 | ---------------------------------------------------------------- |
17 | Alberto Garcia (2): | 23 | Daniel P. Berrangé (1): |
18 | qcow2: Optimize the refcount-block overlap check | 24 | block: always fill entire LUKS header space with zeros |
19 | qemu-io: don't allow I/O operations larger than BDRV_REQUEST_MAX_BYTES | ||
20 | 25 | ||
21 | Daniel P. Berrange (1): | 26 | David Edmondson (1): |
22 | iotests: record separate timings per format,protocol pair | 27 | qemu-img: Add --target-is-zero to convert |
23 | 28 | ||
24 | Dou Liyang (2): | 29 | Max Reitz (11): |
25 | block/qapi: reduce the coupling between the bdrv_query_stats and bdrv_query_bds_stats | 30 | iotests/147: Fix drive parameters |
26 | block/qapi: reduce the execution time of qmp_query_blockstats | 31 | iotests/279: Fix for non-qcow2 formats |
32 | block/nbd: Fix hang in .bdrv_close() | ||
33 | block: Generic file creation fallback | ||
34 | file-posix: Drop hdev_co_create_opts() | ||
35 | iscsi: Drop iscsi_co_create_opts() | ||
36 | iotests: Add test for image creation fallback | ||
37 | qemu-img: Fix convert -n -B for backing-less targets | ||
38 | iotests: Test convert -n -B to backing-less target | ||
39 | block: Fix VM size field width in snapshot dump | ||
40 | iotests: Test snapshot -l field separation | ||
27 | 41 | ||
28 | Fam Zheng (2): | 42 | Peter Krempa (1): |
29 | qapi: Tweak error message of bdrv_query_image_info | 43 | qapi: Allow getting flat output from 'query-named-block-nodes' |
30 | iotests: Fix reference output for 059 | ||
31 | 44 | ||
32 | Jeff Cody (3): | 45 | Thomas Huth (1): |
33 | block: check full backing filename when searching protocol filenames | 46 | iotests: Remove the superfluous 2nd check for the availability of |
34 | qemu-iotests: Don't create fifos / pidfiles with protocol paths | 47 | quorum |
35 | qemu-iotest: test to lookup protocol-based image with relative backing | ||
36 | 48 | ||
37 | Max Reitz (1): | 49 | Vladimir Sementsov-Ogievskiy (3): |
38 | qemu-img: Improve commit invalid base message | 50 | docs: improve qcow2 spec about extending image header |
51 | docs: qcow2: introduce compression type feature | ||
52 | block/backup-top: fix flags handling | ||
39 | 53 | ||
40 | Nir Soffer (3): | 54 | block.c | 164 +++++++++++++++++++++++++++++++++---- |
41 | qemu-io: Return non-zero exit code on failure | 55 | block/backup-top.c | 31 ++++--- |
42 | qemu-iotests: Add _unsupported_fmt helper | 56 | block/file-posix.c | 67 --------------- |
43 | qemu-io: Add failure regression tests | 57 | block/iscsi.c | 56 ------------- |
58 | block/nbd.c | 14 +++- | ||
59 | block/qapi.c | 15 +++- | ||
60 | block/qcow2.c | 11 ++- | ||
61 | blockdev.c | 8 +- | ||
62 | docs/interop/qcow2.txt | 64 ++++++++++++++- | ||
63 | docs/interop/qemu-img.rst | 9 +- | ||
64 | include/block/block.h | 2 +- | ||
65 | include/block/qapi.h | 4 +- | ||
66 | monitor/hmp-cmds.c | 2 +- | ||
67 | qapi/block-core.json | 7 +- | ||
68 | qemu-img-cmds.hx | 4 +- | ||
69 | qemu-img.c | 28 ++++++- | ||
70 | tests/qemu-iotests/122 | 14 ++++ | ||
71 | tests/qemu-iotests/122.out | 5 ++ | ||
72 | tests/qemu-iotests/139 | 3 - | ||
73 | tests/qemu-iotests/147 | 2 +- | ||
74 | tests/qemu-iotests/259 | 62 ++++++++++++++ | ||
75 | tests/qemu-iotests/259.out | 14 ++++ | ||
76 | tests/qemu-iotests/279 | 7 +- | ||
77 | tests/qemu-iotests/284 | 97 ++++++++++++++++++++++ | ||
78 | tests/qemu-iotests/284.out | 62 ++++++++++++++ | ||
79 | tests/qemu-iotests/286 | 76 +++++++++++++++++ | ||
80 | tests/qemu-iotests/286.out | 8 ++ | ||
81 | tests/qemu-iotests/group | 3 + | ||
82 | 28 files changed, 659 insertions(+), 180 deletions(-) | ||
83 | create mode 100755 tests/qemu-iotests/259 | ||
84 | create mode 100644 tests/qemu-iotests/259.out | ||
85 | create mode 100755 tests/qemu-iotests/284 | ||
86 | create mode 100644 tests/qemu-iotests/284.out | ||
87 | create mode 100755 tests/qemu-iotests/286 | ||
88 | create mode 100644 tests/qemu-iotests/286.out | ||
44 | 89 | ||
45 | Peter Lieven (2): | 90 | -- |
46 | block/nfs: fix NULL pointer dereference in URI parsing | 91 | 2.24.1 |
47 | block/nfs: fix naming of runtime opts | ||
48 | 92 | ||
49 | Peter Maydell (2): | ||
50 | qemu-img: Use qemu_strtoul() rather than raw strtoul() | ||
51 | qemu-img: Avoid setting ret to unused value in img_convert() | ||
52 | 93 | ||
53 | QingFeng Hao (2): | ||
54 | iotests: Fix a problem in common.filter | ||
55 | block/vmdk: Fix the endian problem of buf_len and lba | ||
56 | |||
57 | Vladimir Sementsov-Ogievskiy (1): | ||
58 | block: bdrv_invalidate_cache: invalidate children first | ||
59 | |||
60 | tests/qemu-iotests/Makefile | 2 +- | ||
61 | block/qcow2.h | 1 + | ||
62 | block.c | 24 +++++++--- | ||
63 | block/nfs.c | 49 ++++++++++---------- | ||
64 | block/qapi.c | 99 +++++++++++++++++----------------------- | ||
65 | block/qcow2-refcount.c | 24 +++++++++- | ||
66 | block/qcow2.c | 1 + | ||
67 | block/vmdk.c | 4 +- | ||
68 | qemu-img.c | 44 +++++++++--------- | ||
69 | qemu-io-cmds.c | 20 +++++--- | ||
70 | qemu-io.c | 8 +++- | ||
71 | tests/qemu-iotests/.gitignore | 2 +- | ||
72 | tests/qemu-iotests/059.out | 5 +- | ||
73 | tests/qemu-iotests/070.out | 1 - | ||
74 | tests/qemu-iotests/075.out | 7 --- | ||
75 | tests/qemu-iotests/076.out | 3 -- | ||
76 | tests/qemu-iotests/078.out | 6 --- | ||
77 | tests/qemu-iotests/080.out | 18 -------- | ||
78 | tests/qemu-iotests/083.out | 17 ------- | ||
79 | tests/qemu-iotests/088.out | 6 --- | ||
80 | tests/qemu-iotests/092.out | 12 ----- | ||
81 | tests/qemu-iotests/116.out | 7 --- | ||
82 | tests/qemu-iotests/131.out | 1 - | ||
83 | tests/qemu-iotests/140.out | 1 - | ||
84 | tests/qemu-iotests/173 | 97 +++++++++++++++++++++++++++++++++++++++ | ||
85 | tests/qemu-iotests/173.out | 12 +++++ | ||
86 | tests/qemu-iotests/174 | 59 ++++++++++++++++++++++++ | ||
87 | tests/qemu-iotests/174.out | 7 +++ | ||
88 | tests/qemu-iotests/check | 12 +++-- | ||
89 | tests/qemu-iotests/common.config | 6 ++- | ||
90 | tests/qemu-iotests/common.filter | 2 +- | ||
91 | tests/qemu-iotests/common.qemu | 10 ++-- | ||
92 | tests/qemu-iotests/common.rc | 17 +++++-- | ||
93 | tests/qemu-iotests/group | 2 + | ||
94 | 34 files changed, 366 insertions(+), 220 deletions(-) | ||
95 | create mode 100755 tests/qemu-iotests/173 | ||
96 | create mode 100644 tests/qemu-iotests/173.out | ||
97 | create mode 100755 tests/qemu-iotests/174 | ||
98 | create mode 100644 tests/qemu-iotests/174.out | ||
99 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
1 | 2 | ||
3 | Make it more obvious how to add new fields to the version 3 header and | ||
4 | how to interpret them. | ||
5 | |||
6 | The specification is adjusted so that for new defined optional fields: | ||
7 | |||
8 | 1. Software may support some of these optional fields and ignore the | ||
9 | others, which means that features may be backported to downstream | ||
10 | Qemu independently. | ||
11 | 2. If we want to add incompatible field (or a field, for which some of | ||
12 | its values would be incompatible), it must be accompanied by | ||
13 | incompatible feature bit. | ||
14 | |||
15 | Also the concept of "default is zero" is clarified, as it's strange to | ||
16 | say that the value of the field is assumed to be zero for the software | ||
17 | version which don't know about the field at all and don't know how to | ||
18 | treat it be it zero or not. | ||
19 | |||
20 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
21 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
22 | Message-Id: <20200131142219.3264-2-vsementsov@virtuozzo.com> | ||
23 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
24 | [mreitz: s/some its/some of its/] | ||
25 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
26 | --- | ||
27 | docs/interop/qcow2.txt | 45 +++++++++++++++++++++++++++++++++++++++--- | ||
28 | 1 file changed, 42 insertions(+), 3 deletions(-) | ||
29 | |||
30 | diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt | ||
31 | index XXXXXXX..XXXXXXX 100644 | ||
32 | --- a/docs/interop/qcow2.txt | ||
33 | +++ b/docs/interop/qcow2.txt | ||
34 | @@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header: | ||
35 | Offset into the image file at which the snapshot table | ||
36 | starts. Must be aligned to a cluster boundary. | ||
37 | |||
38 | -If the version is 3 or higher, the header has the following additional fields. | ||
39 | -For version 2, the values are assumed to be zero, unless specified otherwise | ||
40 | -in the description of a field. | ||
41 | +For version 2, the header is exactly 72 bytes in length, and finishes here. | ||
42 | +For version 3 or higher, the header length is at least 104 bytes, including | ||
43 | +the next fields through header_length. | ||
44 | |||
45 | 72 - 79: incompatible_features | ||
46 | Bitmask of incompatible features. An implementation must | ||
47 | @@ -XXX,XX +XXX,XX @@ in the description of a field. | ||
48 | 100 - 103: header_length | ||
49 | Length of the header structure in bytes. For version 2 | ||
50 | images, the length is always assumed to be 72 bytes. | ||
51 | + For version 3 it's at least 104 bytes and must be a multiple | ||
52 | + of 8. | ||
53 | + | ||
54 | + | ||
55 | +=== Additional fields (version 3 and higher) === | ||
56 | + | ||
57 | +In general, these fields are optional and may be safely ignored by the software, | ||
58 | +as well as filled by zeros (which is equal to field absence), if software needs | ||
59 | +to set field B, but does not care about field A which precedes B. More | ||
60 | +formally, additional fields have the following compatibility rules: | ||
61 | + | ||
62 | +1. If the value of the additional field must not be ignored for correct | ||
63 | +handling of the file, it will be accompanied by a corresponding incompatible | ||
64 | +feature bit. | ||
65 | + | ||
66 | +2. If there are no unrecognized incompatible feature bits set, an unknown | ||
67 | +additional field may be safely ignored other than preserving its value when | ||
68 | +rewriting the image header. | ||
69 | + | ||
70 | +3. An explicit value of 0 will have the same behavior as when the field is not | ||
71 | +present*, if not altered by a specific incompatible bit. | ||
72 | + | ||
73 | +*. A field is considered not present when header_length is less than or equal | ||
74 | +to the field's offset. Also, all additional fields are not present for | ||
75 | +version 2. | ||
76 | + | ||
77 | + < ... No additional fields in the header currently ... > | ||
78 | + | ||
79 | + | ||
80 | +=== Header padding === | ||
81 | + | ||
82 | +@header_length must be a multiple of 8, which means that if the end of the last | ||
83 | +additional field is not aligned, some padding is needed. This padding must be | ||
84 | +zeroed, so that if some existing (or future) additional field will fall into | ||
85 | +the padding, it will be interpreted accordingly to point [3.] of the previous | ||
86 | +paragraph, i.e. in the same manner as when this field is not present. | ||
87 | + | ||
88 | + | ||
89 | +=== Header extensions === | ||
90 | |||
91 | Directly after the image header, optional sections called header extensions can | ||
92 | be stored. Each extension has a structure like the following: | ||
93 | -- | ||
94 | 2.24.1 | ||
95 | |||
96 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
1 | 2 | ||
3 | The patch adds a new additional field to the qcow2 header: compression_type, | ||
4 | which specifies compression type. If field is absent or zero, default | ||
5 | compression type is set: ZLIB, which corresponds to current behavior. | ||
6 | |||
7 | New compression type (ZSTD) is to be added in further commit. | ||
8 | |||
9 | Suggested-by: Denis Plotnikov <dplotnikov@virtuozzo.com> | ||
10 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
11 | Message-Id: <20200131142219.3264-3-vsementsov@virtuozzo.com> | ||
12 | [mreitz: s/Bits 3-63: Reserved/Bits 4-63: Reserved/] | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | docs/interop/qcow2.txt | 21 +++++++++++++++++++-- | ||
16 | 1 file changed, 19 insertions(+), 2 deletions(-) | ||
17 | |||
18 | diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/docs/interop/qcow2.txt | ||
21 | +++ b/docs/interop/qcow2.txt | ||
22 | @@ -XXX,XX +XXX,XX @@ the next fields through header_length. | ||
23 | An External Data File Name header extension may | ||
24 | be present if this bit is set. | ||
25 | |||
26 | - Bits 3-63: Reserved (set to 0) | ||
27 | + Bit 3: Compression type bit. If this bit is set, | ||
28 | + a non-default compression is used for compressed | ||
29 | + clusters. The compression_type field must be | ||
30 | + present and not zero. | ||
31 | + | ||
32 | + Bits 4-63: Reserved (set to 0) | ||
33 | |||
34 | 80 - 87: compatible_features | ||
35 | Bitmask of compatible features. An implementation can | ||
36 | @@ -XXX,XX +XXX,XX @@ present*, if not altered by a specific incompatible bit. | ||
37 | to the field's offset. Also, all additional fields are not present for | ||
38 | version 2. | ||
39 | |||
40 | - < ... No additional fields in the header currently ... > | ||
41 | + 104: compression_type | ||
42 | + | ||
43 | + Defines the compression method used for compressed clusters. | ||
44 | + All compressed clusters in an image use the same compression | ||
45 | + type. | ||
46 | + | ||
47 | + If the incompatible bit "Compression type" is set: the field | ||
48 | + must be present and non-zero (which means non-zlib | ||
49 | + compression type). Otherwise, this field must not be present | ||
50 | + or must be zero (which means zlib). | ||
51 | + | ||
52 | + Available compression type values: | ||
53 | + 0: zlib <https://www.zlib.net/> | ||
54 | |||
55 | |||
56 | === Header padding === | ||
57 | -- | ||
58 | 2.24.1 | ||
59 | |||
60 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
1 | 2 | ||
3 | Commit d9df28e7b07 ("iotests: check whitelisted formats") added the | ||
4 | modern @iotests.skip_if_unsupported() to the functions in this test, | ||
5 | so we don't need the old explicit test here anymore. | ||
6 | |||
7 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
8 | Message-Id: <20200129141751.32652-1-thuth@redhat.com> | ||
9 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
10 | Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com> | ||
11 | Tested-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com> | ||
12 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
13 | --- | ||
14 | tests/qemu-iotests/139 | 3 --- | ||
15 | 1 file changed, 3 deletions(-) | ||
16 | |||
17 | diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139 | ||
18 | index XXXXXXX..XXXXXXX 100755 | ||
19 | --- a/tests/qemu-iotests/139 | ||
20 | +++ b/tests/qemu-iotests/139 | ||
21 | @@ -XXX,XX +XXX,XX @@ class TestBlockdevDel(iotests.QMPTestCase): | ||
22 | |||
23 | @iotests.skip_if_unsupported(['quorum']) | ||
24 | def testQuorum(self): | ||
25 | - if not iotests.supports_quorum(): | ||
26 | - return | ||
27 | - | ||
28 | self.addQuorum('quorum0', 'node0', 'node1') | ||
29 | # We cannot remove the children of a Quorum device | ||
30 | self.delBlockDriverState('node0', expect_error = True) | ||
31 | -- | ||
32 | 2.24.1 | ||
33 | |||
34 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | 8dff69b94 added an aio parameter to the drive parameter but forgot to |
---|---|---|---|
2 | add a comma before, thus breaking the test. Fix it again. | ||
2 | 3 | ||
3 | Passing a request size larger than BDRV_REQUEST_MAX_BYTES to any of the | 4 | Fixes: 8dff69b9415b4287e900358744b732195e1ab2e2 |
4 | I/O commands results in an error. While 'read' and 'write' handle the | 5 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
5 | error correctly, 'aio_read' and 'aio_write' hit an assertion: | 6 | Message-Id: <20200206130812.612960-1-mreitz@redhat.com> |
6 | 7 | Reviewed-by: Eric Blake <eblake@redhat.com> | |
7 | blk_aio_read_entry: Assertion `rwco->qiov->size == acb->bytes' failed. | 8 | Tested-by: Eric Blake <eblake@redhat.com> |
8 | |||
9 | The reason is that the QEMU I/O code cannot handle request sizes | ||
10 | larger than BDRV_REQUEST_MAX_BYTES, so this patch makes qemu-io check | ||
11 | that all values are within range. | ||
12 | |||
13 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
14 | Message-id: 79f66648c685929a144396bda24d13a207131dcf.1485878688.git.berto@igalia.com | ||
15 | [mreitz: Use BDRV_REQUEST_MAX_BYTES instead of INT_MAX] | ||
16 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 9 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
17 | --- | 10 | --- |
18 | qemu-io-cmds.c | 20 +++++++++++++------- | 11 | tests/qemu-iotests/147 | 2 +- |
19 | 1 file changed, 13 insertions(+), 7 deletions(-) | 12 | 1 file changed, 1 insertion(+), 1 deletion(-) |
20 | 13 | ||
21 | diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c | 14 | diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147 |
22 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100755 |
23 | --- a/qemu-io-cmds.c | 16 | --- a/tests/qemu-iotests/147 |
24 | +++ b/qemu-io-cmds.c | 17 | +++ b/tests/qemu-iotests/147 |
25 | @@ -XXX,XX +XXX,XX @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov, | 18 | @@ -XXX,XX +XXX,XX @@ class BuiltinNBD(NBDBlockdevAddBase): |
26 | goto fail; | 19 | self.server.add_drive_raw('if=none,id=nbd-export,' + |
27 | } | 20 | 'file=%s,' % test_img + |
28 | 21 | 'format=%s,' % imgfmt + | |
29 | - if (len > SIZE_MAX) { | 22 | - 'cache=%s' % cachemode + |
30 | - printf("Argument '%s' exceeds maximum size %llu\n", arg, | 23 | + 'cache=%s,' % cachemode + |
31 | - (unsigned long long)SIZE_MAX); | 24 | 'aio=%s' % aiomode) |
32 | + if (len > BDRV_REQUEST_MAX_BYTES) { | 25 | self.server.launch() |
33 | + printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg, | ||
34 | + (uint64_t)BDRV_REQUEST_MAX_BYTES); | ||
35 | + goto fail; | ||
36 | + } | ||
37 | + | ||
38 | + if (count > BDRV_REQUEST_MAX_BYTES - len) { | ||
39 | + printf("The total number of bytes exceed the maximum size %" PRIu64 | ||
40 | + "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES); | ||
41 | goto fail; | ||
42 | } | ||
43 | |||
44 | @@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv) | ||
45 | if (count < 0) { | ||
46 | print_cvtnum_err(count, argv[optind]); | ||
47 | return 0; | ||
48 | - } else if (count > SIZE_MAX) { | ||
49 | + } else if (count > BDRV_REQUEST_MAX_BYTES) { | ||
50 | printf("length cannot exceed %" PRIu64 ", given %s\n", | ||
51 | - (uint64_t) SIZE_MAX, argv[optind]); | ||
52 | + (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | @@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv) | ||
57 | if (count < 0) { | ||
58 | print_cvtnum_err(count, argv[optind]); | ||
59 | return 0; | ||
60 | - } else if (count > SIZE_MAX) { | ||
61 | + } else if (count > BDRV_REQUEST_MAX_BYTES) { | ||
62 | printf("length cannot exceed %" PRIu64 ", given %s\n", | ||
63 | - (uint64_t) SIZE_MAX, argv[optind]); | ||
64 | + (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]); | ||
65 | return 0; | ||
66 | } | ||
67 | 26 | ||
68 | -- | 27 | -- |
69 | 2.11.0 | 28 | 2.24.1 |
70 | 29 | ||
71 | 30 | diff view generated by jsdifflib |
1 | From: Dou Liyang <douly.fnst@cn.fujitsu.com> | 1 | From: Peter Krempa <pkrempa@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | In order to reduce the execution time, this patch optimize | 3 | When a management application manages node names there's no reason to |
4 | the qmp_query_blockstats(): | 4 | recurse into backing images in the output of query-named-block-nodes. |
5 | Remove the next_query_bds function. | ||
6 | Remove the bdrv_query_stats function. | ||
7 | Remove some judgement sentence. | ||
8 | 5 | ||
9 | The original qmp_query_blockstats calls next_query_bds to get | 6 | Add a parameter to the command which will return just the top level |
10 | the next objects in each loops. In the next_query_bds, it checks | 7 | structs. |
11 | the query_nodes and blk. It also call bdrv_query_stats to get | ||
12 | the stats, In the bdrv_query_stats, it checks blk and bs each | ||
13 | times. This waste more times, which may stall the main loop a | ||
14 | bit. And if the disk is too many and donot use the dataplane | ||
15 | feature, this may affect the performance in main loop thread. | ||
16 | 8 | ||
17 | This patch removes that two functions, and makes the structure | 9 | Signed-off-by: Peter Krempa <pkrempa@redhat.com> |
18 | clearly. | 10 | Message-Id: <4470f8c779abc404dcf65e375db195cd91a80651.1579509782.git.pkrempa@redhat.com> |
19 | 11 | Reviewed-by: Eric Blake <eblake@redhat.com> | |
20 | Signed-off-by: Dou Liyang <douly.fnst@cn.fujitsu.com> | 12 | [mreitz: Fixed coding style] |
21 | Message-id: 1484467275-27919-3-git-send-email-douly.fnst@cn.fujitsu.com | ||
22 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
23 | [mreitz: Removed duplicate info->value assignment] | ||
24 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 13 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
25 | --- | 14 | --- |
26 | block/qapi.c | 73 ++++++++++++++++++++++++------------------------------------ | 15 | block.c | 5 +++-- |
27 | 1 file changed, 29 insertions(+), 44 deletions(-) | 16 | block/qapi.c | 11 +++++++++-- |
17 | blockdev.c | 8 ++++++-- | ||
18 | include/block/block.h | 2 +- | ||
19 | include/block/qapi.h | 4 +++- | ||
20 | monitor/hmp-cmds.c | 2 +- | ||
21 | qapi/block-core.json | 7 ++++++- | ||
22 | 7 files changed, 29 insertions(+), 10 deletions(-) | ||
28 | 23 | ||
24 | diff --git a/block.c b/block.c | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/block.c | ||
27 | +++ b/block.c | ||
28 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_node(const char *node_name) | ||
29 | } | ||
30 | |||
31 | /* Put this QMP function here so it can access the static graph_bdrv_states. */ | ||
32 | -BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp) | ||
33 | +BlockDeviceInfoList *bdrv_named_nodes_list(bool flat, | ||
34 | + Error **errp) | ||
35 | { | ||
36 | BlockDeviceInfoList *list, *entry; | ||
37 | BlockDriverState *bs; | ||
38 | |||
39 | list = NULL; | ||
40 | QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) { | ||
41 | - BlockDeviceInfo *info = bdrv_block_device_info(NULL, bs, errp); | ||
42 | + BlockDeviceInfo *info = bdrv_block_device_info(NULL, bs, flat, errp); | ||
43 | if (!info) { | ||
44 | qapi_free_BlockDeviceInfoList(list); | ||
45 | return NULL; | ||
29 | diff --git a/block/qapi.c b/block/qapi.c | 46 | diff --git a/block/qapi.c b/block/qapi.c |
30 | index XXXXXXX..XXXXXXX 100644 | 47 | index XXXXXXX..XXXXXXX 100644 |
31 | --- a/block/qapi.c | 48 | --- a/block/qapi.c |
32 | +++ b/block/qapi.c | 49 | +++ b/block/qapi.c |
33 | @@ -XXX,XX +XXX,XX @@ static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs, | 50 | @@ -XXX,XX +XXX,XX @@ |
34 | return s; | 51 | #include "qemu/cutils.h" |
52 | |||
53 | BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, | ||
54 | - BlockDriverState *bs, Error **errp) | ||
55 | + BlockDriverState *bs, | ||
56 | + bool flat, | ||
57 | + Error **errp) | ||
58 | { | ||
59 | ImageInfo **p_image_info; | ||
60 | BlockDriverState *bs0; | ||
61 | @@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, | ||
62 | return NULL; | ||
63 | } | ||
64 | |||
65 | + /* stop gathering data for flat output */ | ||
66 | + if (flat) { | ||
67 | + break; | ||
68 | + } | ||
69 | + | ||
70 | if (bs0->drv && bs0->backing) { | ||
71 | info->backing_file_depth++; | ||
72 | bs0 = bs0->backing->bs; | ||
73 | @@ -XXX,XX +XXX,XX @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, | ||
74 | |||
75 | if (bs && bs->drv) { | ||
76 | info->has_inserted = true; | ||
77 | - info->inserted = bdrv_block_device_info(blk, bs, errp); | ||
78 | + info->inserted = bdrv_block_device_info(blk, bs, false, errp); | ||
79 | if (info->inserted == NULL) { | ||
80 | goto err; | ||
81 | } | ||
82 | diff --git a/blockdev.c b/blockdev.c | ||
83 | index XXXXXXX..XXXXXXX 100644 | ||
84 | --- a/blockdev.c | ||
85 | +++ b/blockdev.c | ||
86 | @@ -XXX,XX +XXX,XX @@ void qmp_drive_backup(DriveBackup *backup, Error **errp) | ||
87 | blockdev_do_action(&action, errp); | ||
35 | } | 88 | } |
36 | 89 | ||
37 | -static BlockStats *bdrv_query_stats(BlockBackend *blk, | 90 | -BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp) |
38 | - const BlockDriverState *bs, | 91 | +BlockDeviceInfoList *qmp_query_named_block_nodes(bool has_flat, |
39 | - bool query_backing) | 92 | + bool flat, |
40 | -{ | 93 | + Error **errp) |
41 | - BlockStats *s; | ||
42 | - | ||
43 | - s = bdrv_query_bds_stats(bs, query_backing); | ||
44 | - | ||
45 | - if (blk) { | ||
46 | - s->has_device = true; | ||
47 | - s->device = g_strdup(blk_name(blk)); | ||
48 | - bdrv_query_blk_stats(s->stats, blk); | ||
49 | - } | ||
50 | - | ||
51 | - return s; | ||
52 | -} | ||
53 | - | ||
54 | BlockInfoList *qmp_query_block(Error **errp) | ||
55 | { | 94 | { |
56 | BlockInfoList *head = NULL, **p_next = &head; | 95 | - return bdrv_named_nodes_list(errp); |
57 | @@ -XXX,XX +XXX,XX @@ BlockInfoList *qmp_query_block(Error **errp) | 96 | + bool return_flat = has_flat && flat; |
58 | return head; | 97 | + |
98 | + return bdrv_named_nodes_list(return_flat, errp); | ||
59 | } | 99 | } |
60 | 100 | ||
61 | -static bool next_query_bds(BlockBackend **blk, BlockDriverState **bs, | 101 | XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp) |
62 | - bool query_nodes) | 102 | diff --git a/include/block/block.h b/include/block/block.h |
63 | -{ | 103 | index XXXXXXX..XXXXXXX 100644 |
64 | - if (query_nodes) { | 104 | --- a/include/block/block.h |
65 | - *bs = bdrv_next_node(*bs); | 105 | +++ b/include/block/block.h |
66 | - return !!*bs; | 106 | @@ -XXX,XX +XXX,XX @@ void bdrv_lock_medium(BlockDriverState *bs, bool locked); |
67 | - } | 107 | void bdrv_eject(BlockDriverState *bs, bool eject_flag); |
68 | - | 108 | const char *bdrv_get_format_name(BlockDriverState *bs); |
69 | - *blk = blk_next(*blk); | 109 | BlockDriverState *bdrv_find_node(const char *node_name); |
70 | - *bs = *blk ? blk_bs(*blk) : NULL; | 110 | -BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp); |
71 | - | 111 | +BlockDeviceInfoList *bdrv_named_nodes_list(bool flat, Error **errp); |
72 | - return !!*blk; | 112 | XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp); |
73 | -} | 113 | BlockDriverState *bdrv_lookup_bs(const char *device, |
74 | - | 114 | const char *node_name, |
75 | BlockStatsList *qmp_query_blockstats(bool has_query_nodes, | 115 | diff --git a/include/block/qapi.h b/include/block/qapi.h |
76 | bool query_nodes, | 116 | index XXXXXXX..XXXXXXX 100644 |
77 | Error **errp) | 117 | --- a/include/block/qapi.h |
78 | { | 118 | +++ b/include/block/qapi.h |
79 | BlockStatsList *head = NULL, **p_next = &head; | 119 | @@ -XXX,XX +XXX,XX @@ |
80 | - BlockBackend *blk = NULL; | 120 | #include "block/snapshot.h" |
81 | - BlockDriverState *bs = NULL; | 121 | |
82 | + BlockBackend *blk; | 122 | BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, |
83 | + BlockDriverState *bs; | 123 | - BlockDriverState *bs, Error **errp); |
84 | 124 | + BlockDriverState *bs, | |
85 | /* Just to be safe if query_nodes is not always initialized */ | 125 | + bool flat, |
86 | - query_nodes = has_query_nodes && query_nodes; | 126 | + Error **errp); |
87 | - | 127 | int bdrv_query_snapshot_info_list(BlockDriverState *bs, |
88 | - while (next_query_bds(&blk, &bs, query_nodes)) { | 128 | SnapshotInfoList **p_list, |
89 | - BlockStatsList *info = g_malloc0(sizeof(*info)); | 129 | Error **errp); |
90 | - AioContext *ctx = blk ? blk_get_aio_context(blk) | 130 | diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c |
91 | - : bdrv_get_aio_context(bs); | 131 | index XXXXXXX..XXXXXXX 100644 |
92 | + if (has_query_nodes && query_nodes) { | 132 | --- a/monitor/hmp-cmds.c |
93 | + for (bs = bdrv_next_node(NULL); bs; bs = bdrv_next_node(bs)) { | 133 | +++ b/monitor/hmp-cmds.c |
94 | + BlockStatsList *info = g_malloc0(sizeof(*info)); | 134 | @@ -XXX,XX +XXX,XX @@ void hmp_info_block(Monitor *mon, const QDict *qdict) |
95 | + AioContext *ctx = bdrv_get_aio_context(bs); | ||
96 | |||
97 | - aio_context_acquire(ctx); | ||
98 | - info->value = bdrv_query_stats(blk, bs, !query_nodes); | ||
99 | - aio_context_release(ctx); | ||
100 | + aio_context_acquire(ctx); | ||
101 | + info->value = bdrv_query_bds_stats(bs, false); | ||
102 | + aio_context_release(ctx); | ||
103 | |||
104 | - *p_next = info; | ||
105 | - p_next = &info->next; | ||
106 | + *p_next = info; | ||
107 | + p_next = &info->next; | ||
108 | + } | ||
109 | + } else { | ||
110 | + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { | ||
111 | + BlockStatsList *info = g_malloc0(sizeof(*info)); | ||
112 | + AioContext *ctx = blk_get_aio_context(blk); | ||
113 | + BlockStats *s; | ||
114 | + | ||
115 | + aio_context_acquire(ctx); | ||
116 | + s = bdrv_query_bds_stats(blk_bs(blk), true); | ||
117 | + s->has_device = true; | ||
118 | + s->device = g_strdup(blk_name(blk)); | ||
119 | + bdrv_query_blk_stats(s->stats, blk); | ||
120 | + aio_context_release(ctx); | ||
121 | + | ||
122 | + info->value = s; | ||
123 | + *p_next = info; | ||
124 | + p_next = &info->next; | ||
125 | + } | ||
126 | } | 135 | } |
127 | 136 | ||
128 | return head; | 137 | /* Print node information */ |
138 | - blockdev_list = qmp_query_named_block_nodes(NULL); | ||
139 | + blockdev_list = qmp_query_named_block_nodes(false, false, NULL); | ||
140 | for (blockdev = blockdev_list; blockdev; blockdev = blockdev->next) { | ||
141 | assert(blockdev->value->has_node_name); | ||
142 | if (device && strcmp(device, blockdev->value->node_name)) { | ||
143 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
144 | index XXXXXXX..XXXXXXX 100644 | ||
145 | --- a/qapi/block-core.json | ||
146 | +++ b/qapi/block-core.json | ||
147 | @@ -XXX,XX +XXX,XX @@ | ||
148 | # | ||
149 | # Get the named block driver list | ||
150 | # | ||
151 | +# @flat: Omit the nested data about backing image ("backing-image" key) if true. | ||
152 | +# Default is false (Since 5.0) | ||
153 | +# | ||
154 | # Returns: the list of BlockDeviceInfo | ||
155 | # | ||
156 | # Since: 2.0 | ||
157 | @@ -XXX,XX +XXX,XX @@ | ||
158 | # } } ] } | ||
159 | # | ||
160 | ## | ||
161 | -{ 'command': 'query-named-block-nodes', 'returns': [ 'BlockDeviceInfo' ] } | ||
162 | +{ 'command': 'query-named-block-nodes', | ||
163 | + 'returns': [ 'BlockDeviceInfo' ], | ||
164 | + 'data': { '*flat': 'bool' } } | ||
165 | |||
166 | ## | ||
167 | # @XDbgBlockGraphNodeType: | ||
129 | -- | 168 | -- |
130 | 2.11.0 | 169 | 2.24.1 |
131 | 170 | ||
132 | 171 | diff view generated by jsdifflib |
1 | When trying to invoke qemu-img commit with a base image file name that | 1 | From: David Edmondson <david.edmondson@oracle.com> |
---|---|---|---|
2 | is not part of the top image's backing chain, the user receives a rather | ||
3 | plain "Base not found" error message. This is not really helpful because | ||
4 | it does not explain what "not found" means, potentially leaving the user | ||
5 | wondering why qemu cannot find a file despite it clearly existing in the | ||
6 | file system. | ||
7 | 2 | ||
8 | Improve the error message by clarifying that "not found" means "not | 3 | In many cases the target of a convert operation is a newly provisioned |
9 | found in the top image's backing chain". | 4 | target that the user knows is blank (reads as zero). In this situation |
5 | there is no requirement for qemu-img to wastefully zero out the entire | ||
6 | device. | ||
10 | 7 | ||
11 | Reported-by: Ala Hino <ahino@redhat.com> | 8 | Add a new option, --target-is-zero, allowing the user to indicate that |
12 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 9 | an existing target device will return zeros for all reads. |
13 | Message-id: 20161201020508.24417-1-mreitz@redhat.com | 10 | |
11 | Signed-off-by: David Edmondson <david.edmondson@oracle.com> | ||
12 | Message-Id: <20200205110248.2009589-2-david.edmondson@oracle.com> | ||
13 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
14 | Reviewed-by: Eric Blake <eblake@redhat.com> | 14 | Reviewed-by: Eric Blake <eblake@redhat.com> |
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 15 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
16 | --- | 16 | --- |
17 | qemu-img.c | 4 +++- | 17 | docs/interop/qemu-img.rst | 9 ++++++++- |
18 | 1 file changed, 3 insertions(+), 1 deletion(-) | 18 | qemu-img-cmds.hx | 4 ++-- |
19 | qemu-img.c | 26 +++++++++++++++++++++++--- | ||
20 | 3 files changed, 33 insertions(+), 6 deletions(-) | ||
19 | 21 | ||
22 | diff --git a/docs/interop/qemu-img.rst b/docs/interop/qemu-img.rst | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/docs/interop/qemu-img.rst | ||
25 | +++ b/docs/interop/qemu-img.rst | ||
26 | @@ -XXX,XX +XXX,XX @@ Parameters to convert subcommand: | ||
27 | will still be printed. Areas that cannot be read from the source will be | ||
28 | treated as containing only zeroes. | ||
29 | |||
30 | +.. option:: --target-is-zero | ||
31 | + | ||
32 | + Assume that reading the destination image will always return | ||
33 | + zeros. This parameter is mutually exclusive with a destination image | ||
34 | + that has a backing file. It is required to also use the ``-n`` | ||
35 | + parameter to skip image creation. | ||
36 | + | ||
37 | Parameters to dd subcommand: | ||
38 | |||
39 | .. program:: qemu-img-dd | ||
40 | @@ -XXX,XX +XXX,XX @@ Command description: | ||
41 | 4 | ||
42 | Error on reading data | ||
43 | |||
44 | -.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME | ||
45 | +.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME | ||
46 | |||
47 | Convert the disk image *FILENAME* or a snapshot *SNAPSHOT_PARAM* | ||
48 | to disk image *OUTPUT_FILENAME* using format *OUTPUT_FMT*. It can | ||
49 | diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx | ||
50 | index XXXXXXX..XXXXXXX 100644 | ||
51 | --- a/qemu-img-cmds.hx | ||
52 | +++ b/qemu-img-cmds.hx | ||
53 | @@ -XXX,XX +XXX,XX @@ SRST | ||
54 | ERST | ||
55 | |||
56 | DEF("convert", img_convert, | ||
57 | - "convert [--object objectdef] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename") | ||
58 | + "convert [--object objectdef] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename") | ||
59 | SRST | ||
60 | -.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME | ||
61 | +.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME | ||
62 | ERST | ||
63 | |||
64 | DEF("create", img_create, | ||
20 | diff --git a/qemu-img.c b/qemu-img.c | 65 | diff --git a/qemu-img.c b/qemu-img.c |
21 | index XXXXXXX..XXXXXXX 100644 | 66 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/qemu-img.c | 67 | --- a/qemu-img.c |
23 | +++ b/qemu-img.c | 68 | +++ b/qemu-img.c |
24 | @@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv) | 69 | @@ -XXX,XX +XXX,XX @@ enum { |
25 | if (base) { | 70 | OPTION_PREALLOCATION = 265, |
26 | base_bs = bdrv_find_backing_image(bs, base); | 71 | OPTION_SHRINK = 266, |
27 | if (!base_bs) { | 72 | OPTION_SALVAGE = 267, |
28 | - error_setg(&local_err, QERR_BASE_NOT_FOUND, base); | 73 | + OPTION_TARGET_IS_ZERO = 268, |
29 | + error_setg(&local_err, | 74 | }; |
30 | + "Did not find '%s' in the backing chain of '%s'", | 75 | |
31 | + base, filename); | 76 | typedef enum OutputFormat { |
32 | goto done; | 77 | @@ -XXX,XX +XXX,XX @@ static int convert_do_copy(ImgConvertState *s) |
78 | int64_t sector_num = 0; | ||
79 | |||
80 | /* Check whether we have zero initialisation or can get it efficiently */ | ||
81 | - if (s->target_is_new && s->min_sparse && !s->target_has_backing) { | ||
82 | + if (!s->has_zero_init && s->target_is_new && s->min_sparse && | ||
83 | + !s->target_has_backing) { | ||
84 | s->has_zero_init = bdrv_has_zero_init(blk_bs(s->target)); | ||
85 | - } else { | ||
86 | - s->has_zero_init = false; | ||
87 | } | ||
88 | |||
89 | if (!s->has_zero_init && !s->target_has_backing && | ||
90 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | ||
91 | {"force-share", no_argument, 0, 'U'}, | ||
92 | {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS}, | ||
93 | {"salvage", no_argument, 0, OPTION_SALVAGE}, | ||
94 | + {"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO}, | ||
95 | {0, 0, 0, 0} | ||
96 | }; | ||
97 | c = getopt_long(argc, argv, ":hf:O:B:Cco:l:S:pt:T:qnm:WU", | ||
98 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | ||
99 | case OPTION_TARGET_IMAGE_OPTS: | ||
100 | tgt_image_opts = true; | ||
101 | break; | ||
102 | + case OPTION_TARGET_IS_ZERO: | ||
103 | + /* | ||
104 | + * The user asserting that the target is blank has the | ||
105 | + * same effect as the target driver supporting zero | ||
106 | + * initialisation. | ||
107 | + */ | ||
108 | + s.has_zero_init = true; | ||
109 | + break; | ||
33 | } | 110 | } |
34 | } else { | 111 | } |
112 | |||
113 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | ||
114 | warn_report("This will become an error in future QEMU versions."); | ||
115 | } | ||
116 | |||
117 | + if (s.has_zero_init && !skip_create) { | ||
118 | + error_report("--target-is-zero requires use of -n flag"); | ||
119 | + goto fail_getopt; | ||
120 | + } | ||
121 | + | ||
122 | s.src_num = argc - optind - 1; | ||
123 | out_filename = s.src_num >= 1 ? argv[argc - 1] : NULL; | ||
124 | |||
125 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | ||
126 | } | ||
127 | s.target_has_backing = (bool) out_baseimg; | ||
128 | |||
129 | + if (s.has_zero_init && s.target_has_backing) { | ||
130 | + error_report("Cannot use --target-is-zero when the destination " | ||
131 | + "image has a backing file"); | ||
132 | + goto out; | ||
133 | + } | ||
134 | + | ||
135 | if (s.src_num > 1 && out_baseimg) { | ||
136 | error_report("Having a backing file for the target makes no sense when " | ||
137 | "concatenating multiple input images"); | ||
35 | -- | 138 | -- |
36 | 2.11.0 | 139 | 2.24.1 |
37 | 140 | ||
38 | 141 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | From: Daniel P. Berrangé <berrange@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | The metadata overlap checks introduced in a40f1c2add help detect | 3 | When initializing the LUKS header the size with default encryption |
4 | corruption in the qcow2 image by verifying that data writes don't | 4 | parameters will currently be 2068480 bytes. This is rounded up to |
5 | overlap with existing metadata sections. | 5 | a multiple of the cluster size, 2081792, with 64k sectors. If the |
6 | 6 | end of the header is not the same as the end of the cluster we fill | |
7 | The 'refcount-block' check in particular iterates over the refcount | 7 | the extra space with zeros. This was forgetting that not even the |
8 | table in order to get the addresses of all refcount blocks and check | 8 | space allocated for the header will be fully initialized, as we |
9 | that none of them overlap with the region where we want to write. | 9 | only write key material for the first key slot. The space left |
10 | 10 | for the other 7 slots is never written to. | |
11 | The problem with the refcount table is that since it always occupies | 11 | |
12 | complete clusters its size is usually very big. With the default | 12 | An optimization to the ref count checking code: |
13 | values of cluster_size=64KB and refcount_bits=16 this table holds 8192 | 13 | |
14 | entries, each one of them enough to map 2GB worth of host clusters. | 14 | commit a5fff8d4b4d928311a5005efa12d0991fe3b66f9 (refs/bisect/bad) |
15 | 15 | Author: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | |
16 | So unless we're using images with several TB of allocated data this | 16 | Date: Wed Feb 27 16:14:30 2019 +0300 |
17 | table is going to be mostly empty, and iterating over it is a waste of | 17 | |
18 | CPU. If the storage backend is fast enough this can have an effect on | 18 | qcow2-refcount: avoid eating RAM |
19 | I/O performance. | 19 | |
20 | 20 | made the assumption that every cluster which was allocated would | |
21 | This patch keeps the index of the last used (i.e. non-zero) entry in | 21 | have at least some data written to it. This was violated by way |
22 | the refcount table and updates it every time the table changes. The | 22 | the LUKS header is only partially written, with much space simply |
23 | refcount-block overlap check then uses that index instead of reading | 23 | reserved for future use. |
24 | the whole table. | 24 | |
25 | 25 | Depending on the cluster size this problem was masked by the | |
26 | In my tests with a 4GB qcow2 file stored in RAM this doubles the | 26 | logic which wrote zeros between the end of the LUKS header and |
27 | amount of write IOPS. | 27 | the end of the cluster. |
28 | 28 | ||
29 | Signed-off-by: Alberto Garcia <berto@igalia.com> | 29 | $ qemu-img create --object secret,id=cluster_encrypt0,data=123456 \ |
30 | Message-id: 20170201123828.4815-1-berto@igalia.com | 30 | -f qcow2 -o cluster_size=2k,encrypt.iter-time=1,\ |
31 | Reviewed-by: Max Reitz <mreitz@redhat.com> | 31 | encrypt.format=luks,encrypt.key-secret=cluster_encrypt0 \ |
32 | cluster_size_check.qcow2 100M | ||
33 | Formatting 'cluster_size_check.qcow2', fmt=qcow2 size=104857600 | ||
34 | encrypt.format=luks encrypt.key-secret=cluster_encrypt0 | ||
35 | encrypt.iter-time=1 cluster_size=2048 lazy_refcounts=off refcount_bits=16 | ||
36 | |||
37 | $ qemu-img check --object secret,id=cluster_encrypt0,data=redhat \ | ||
38 | 'json:{"driver": "qcow2", "encrypt.format": "luks", \ | ||
39 | "encrypt.key-secret": "cluster_encrypt0", \ | ||
40 | "file.driver": "file", "file.filename": "cluster_size_check.qcow2"}' | ||
41 | ERROR: counting reference for region exceeding the end of the file by one cluster or more: offset 0x2000 size 0x1f9000 | ||
42 | Leaked cluster 4 refcount=1 reference=0 | ||
43 | ...snip... | ||
44 | Leaked cluster 130 refcount=1 reference=0 | ||
45 | |||
46 | 1 errors were found on the image. | ||
47 | Data may be corrupted, or further writes to the image may corrupt it. | ||
48 | |||
49 | 127 leaked clusters were found on the image. | ||
50 | This means waste of disk space, but no harm to data. | ||
51 | Image end offset: 268288 | ||
52 | |||
53 | The problem only exists when the disk image is entirely empty. Writing | ||
54 | data to the disk image payload will solve the problem by causing the | ||
55 | end of the file to be extended further. | ||
56 | |||
57 | The change fixes it by ensuring that the entire allocated LUKS header | ||
58 | region is fully initialized with zeros. The qemu-img check will still | ||
59 | fail for any pre-existing disk images created prior to this change, | ||
60 | unless at least 1 byte of the payload is written to. | ||
61 | |||
62 | Fully writing zeros to the entire LUKS header is a good idea regardless | ||
63 | as it ensures that space has been allocated on the host filesystem (or | ||
64 | whatever block storage backend is used). | ||
65 | |||
66 | Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> | ||
67 | Message-Id: <20200207135520.2669430-1-berrange@redhat.com> | ||
68 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
32 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 69 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
33 | --- | 70 | --- |
34 | block/qcow2.h | 1 + | 71 | block/qcow2.c | 11 +++-- |
35 | block/qcow2-refcount.c | 24 +++++++++++++++++++++++- | 72 | tests/qemu-iotests/284 | 97 ++++++++++++++++++++++++++++++++++++++ |
36 | block/qcow2.c | 1 + | 73 | tests/qemu-iotests/284.out | 62 ++++++++++++++++++++++++ |
37 | 3 files changed, 25 insertions(+), 1 deletion(-) | 74 | tests/qemu-iotests/group | 1 + |
38 | 75 | 4 files changed, 167 insertions(+), 4 deletions(-) | |
39 | diff --git a/block/qcow2.h b/block/qcow2.h | 76 | create mode 100755 tests/qemu-iotests/284 |
40 | index XXXXXXX..XXXXXXX 100644 | 77 | create mode 100644 tests/qemu-iotests/284.out |
41 | --- a/block/qcow2.h | 78 | |
42 | +++ b/block/qcow2.h | ||
43 | @@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State { | ||
44 | uint64_t *refcount_table; | ||
45 | uint64_t refcount_table_offset; | ||
46 | uint32_t refcount_table_size; | ||
47 | + uint32_t max_refcount_table_index; /* Last used entry in refcount_table */ | ||
48 | uint64_t free_cluster_index; | ||
49 | uint64_t free_byte_offset; | ||
50 | |||
51 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c | ||
52 | index XXXXXXX..XXXXXXX 100644 | ||
53 | --- a/block/qcow2-refcount.c | ||
54 | +++ b/block/qcow2-refcount.c | ||
55 | @@ -XXX,XX +XXX,XX @@ static Qcow2SetRefcountFunc *const set_refcount_funcs[] = { | ||
56 | /*********************************************************/ | ||
57 | /* refcount handling */ | ||
58 | |||
59 | +static void update_max_refcount_table_index(BDRVQcow2State *s) | ||
60 | +{ | ||
61 | + unsigned i = s->refcount_table_size - 1; | ||
62 | + while (i > 0 && (s->refcount_table[i] & REFT_OFFSET_MASK) == 0) { | ||
63 | + i--; | ||
64 | + } | ||
65 | + /* Set s->max_refcount_table_index to the index of the last used entry */ | ||
66 | + s->max_refcount_table_index = i; | ||
67 | +} | ||
68 | + | ||
69 | int qcow2_refcount_init(BlockDriverState *bs) | ||
70 | { | ||
71 | BDRVQcow2State *s = bs->opaque; | ||
72 | @@ -XXX,XX +XXX,XX @@ int qcow2_refcount_init(BlockDriverState *bs) | ||
73 | } | ||
74 | for(i = 0; i < s->refcount_table_size; i++) | ||
75 | be64_to_cpus(&s->refcount_table[i]); | ||
76 | + update_max_refcount_table_index(s); | ||
77 | } | ||
78 | return 0; | ||
79 | fail: | ||
80 | @@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs, | ||
81 | } | ||
82 | |||
83 | s->refcount_table[refcount_table_index] = new_block; | ||
84 | + /* If there's a hole in s->refcount_table then it can happen | ||
85 | + * that refcount_table_index < s->max_refcount_table_index */ | ||
86 | + s->max_refcount_table_index = | ||
87 | + MAX(s->max_refcount_table_index, refcount_table_index); | ||
88 | |||
89 | /* The new refcount block may be where the caller intended to put its | ||
90 | * data, so let it restart the search. */ | ||
91 | @@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs, | ||
92 | s->refcount_table = new_table; | ||
93 | s->refcount_table_size = table_size; | ||
94 | s->refcount_table_offset = table_offset; | ||
95 | + update_max_refcount_table_index(s); | ||
96 | |||
97 | /* Free old table. */ | ||
98 | qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t), | ||
99 | @@ -XXX,XX +XXX,XX @@ write_refblocks: | ||
100 | s->refcount_table = on_disk_reftable; | ||
101 | s->refcount_table_offset = reftable_offset; | ||
102 | s->refcount_table_size = reftable_size; | ||
103 | + update_max_refcount_table_index(s); | ||
104 | |||
105 | return 0; | ||
106 | |||
107 | @@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, | ||
108 | } | ||
109 | |||
110 | if ((chk & QCOW2_OL_REFCOUNT_BLOCK) && s->refcount_table) { | ||
111 | - for (i = 0; i < s->refcount_table_size; i++) { | ||
112 | + unsigned last_entry = s->max_refcount_table_index; | ||
113 | + assert(last_entry < s->refcount_table_size); | ||
114 | + assert(last_entry + 1 == s->refcount_table_size || | ||
115 | + (s->refcount_table[last_entry + 1] & REFT_OFFSET_MASK) == 0); | ||
116 | + for (i = 0; i <= last_entry; i++) { | ||
117 | if ((s->refcount_table[i] & REFT_OFFSET_MASK) && | ||
118 | overlaps_with(s->refcount_table[i] & REFT_OFFSET_MASK, | ||
119 | s->cluster_size)) { | ||
120 | @@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, | ||
121 | /* Now update the rest of the in-memory information */ | ||
122 | old_reftable = s->refcount_table; | ||
123 | s->refcount_table = new_reftable; | ||
124 | + update_max_refcount_table_index(s); | ||
125 | |||
126 | s->refcount_bits = 1 << refcount_order; | ||
127 | s->refcount_max = UINT64_C(1) << (s->refcount_bits - 1); | ||
128 | diff --git a/block/qcow2.c b/block/qcow2.c | 79 | diff --git a/block/qcow2.c b/block/qcow2.c |
129 | index XXXXXXX..XXXXXXX 100644 | 80 | index XXXXXXX..XXXXXXX 100644 |
130 | --- a/block/qcow2.c | 81 | --- a/block/qcow2.c |
131 | +++ b/block/qcow2.c | 82 | +++ b/block/qcow2.c |
132 | @@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs) | 83 | @@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen, |
133 | 84 | s->crypto_header.length = headerlen; | |
134 | s->refcount_table_offset = s->cluster_size; | 85 | s->crypto_header.offset = ret; |
135 | s->refcount_table_size = s->cluster_size / sizeof(uint64_t); | 86 | |
136 | + s->max_refcount_table_index = 0; | 87 | - /* Zero fill remaining space in cluster so it has predictable |
137 | 88 | - * content in case of future spec changes */ | |
138 | g_free(s->refcount_table); | 89 | + /* |
139 | s->refcount_table = new_reftable; | 90 | + * Zero fill all space in cluster so it has predictable |
91 | + * content, as we may not initialize some regions of the | ||
92 | + * header (eg only 1 out of 8 key slots will be initialized) | ||
93 | + */ | ||
94 | clusterlen = size_to_clusters(s, headerlen) * s->cluster_size; | ||
95 | assert(qcow2_pre_write_overlap_check(bs, 0, ret, clusterlen, false) == 0); | ||
96 | ret = bdrv_pwrite_zeroes(bs->file, | ||
97 | - ret + headerlen, | ||
98 | - clusterlen - headerlen, 0); | ||
99 | + ret, | ||
100 | + clusterlen, 0); | ||
101 | if (ret < 0) { | ||
102 | error_setg_errno(errp, -ret, "Could not zero fill encryption header"); | ||
103 | return -1; | ||
104 | diff --git a/tests/qemu-iotests/284 b/tests/qemu-iotests/284 | ||
105 | new file mode 100755 | ||
106 | index XXXXXXX..XXXXXXX | ||
107 | --- /dev/null | ||
108 | +++ b/tests/qemu-iotests/284 | ||
109 | @@ -XXX,XX +XXX,XX @@ | ||
110 | +#!/usr/bin/env bash | ||
111 | +# | ||
112 | +# Test ref count checks on encrypted images | ||
113 | +# | ||
114 | +# Copyright (C) 2019 Red Hat, Inc. | ||
115 | +# | ||
116 | +# This program is free software; you can redistribute it and/or modify | ||
117 | +# it under the terms of the GNU General Public License as published by | ||
118 | +# the Free Software Foundation; either version 2 of the License, or | ||
119 | +# (at your option) any later version. | ||
120 | +# | ||
121 | +# This program is distributed in the hope that it will be useful, | ||
122 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
123 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
124 | +# GNU General Public License for more details. | ||
125 | +# | ||
126 | +# You should have received a copy of the GNU General Public License | ||
127 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
128 | +# | ||
129 | + | ||
130 | +# creator | ||
131 | +owner=berrange@redhat.com | ||
132 | + | ||
133 | +seq=`basename $0` | ||
134 | +echo "QA output created by $seq" | ||
135 | + | ||
136 | +status=1 # failure is the default! | ||
137 | + | ||
138 | +_cleanup() | ||
139 | +{ | ||
140 | + _cleanup_test_img | ||
141 | +} | ||
142 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
143 | + | ||
144 | +# get standard environment, filters and checks | ||
145 | +. ./common.rc | ||
146 | +. ./common.filter | ||
147 | + | ||
148 | +_supported_fmt qcow2 | ||
149 | +_supported_proto generic | ||
150 | +_supported_os Linux | ||
151 | + | ||
152 | + | ||
153 | +size=1M | ||
154 | + | ||
155 | +SECRET="secret,id=sec0,data=astrochicken" | ||
156 | + | ||
157 | +IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0" | ||
158 | +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT | ||
159 | + | ||
160 | +_run_test() | ||
161 | +{ | ||
162 | + IMGOPTSSYNTAX=true | ||
163 | + OLD_TEST_IMG="$TEST_IMG" | ||
164 | + TEST_IMG="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0" | ||
165 | + QEMU_IMG_EXTRA_ARGS="--image-opts --object $SECRET" | ||
166 | + | ||
167 | + echo | ||
168 | + echo "== cluster size $csize" | ||
169 | + echo "== checking image refcounts ==" | ||
170 | + _check_test_img | ||
171 | + | ||
172 | + echo | ||
173 | + echo "== writing some data ==" | ||
174 | + $QEMU_IO -c "write -P 0x9 0 1" $QEMU_IMG_EXTRA_ARGS $TEST_IMG | _filter_qemu_io | _filter_testdir | ||
175 | + echo | ||
176 | + echo "== rechecking image refcounts ==" | ||
177 | + _check_test_img | ||
178 | + | ||
179 | + echo | ||
180 | + echo "== writing some more data ==" | ||
181 | + $QEMU_IO -c "write -P 0x9 $csize 1" $QEMU_IMG_EXTRA_ARGS $TEST_IMG | _filter_qemu_io | _filter_testdir | ||
182 | + echo | ||
183 | + echo "== rechecking image refcounts ==" | ||
184 | + _check_test_img | ||
185 | + | ||
186 | + TEST_IMG="$OLD_TEST_IMG" | ||
187 | + QEMU_IMG_EXTRA_ARGS= | ||
188 | + IMGOPTSSYNTAX= | ||
189 | +} | ||
190 | + | ||
191 | + | ||
192 | +echo | ||
193 | +echo "testing LUKS qcow2 encryption" | ||
194 | +echo | ||
195 | + | ||
196 | +for csize in 512 2048 32768 | ||
197 | +do | ||
198 | + _make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,cluster_size=$csize" $size | ||
199 | + _run_test | ||
200 | + _cleanup_test_img | ||
201 | +done | ||
202 | + | ||
203 | +# success, all done | ||
204 | +echo "*** done" | ||
205 | +rm -f $seq.full | ||
206 | +status=0 | ||
207 | diff --git a/tests/qemu-iotests/284.out b/tests/qemu-iotests/284.out | ||
208 | new file mode 100644 | ||
209 | index XXXXXXX..XXXXXXX | ||
210 | --- /dev/null | ||
211 | +++ b/tests/qemu-iotests/284.out | ||
212 | @@ -XXX,XX +XXX,XX @@ | ||
213 | +QA output created by 284 | ||
214 | + | ||
215 | +testing LUKS qcow2 encryption | ||
216 | + | ||
217 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 | ||
218 | + | ||
219 | +== cluster size 512 | ||
220 | +== checking image refcounts == | ||
221 | +No errors were found on the image. | ||
222 | + | ||
223 | +== writing some data == | ||
224 | +wrote 1/1 bytes at offset 0 | ||
225 | +1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
226 | + | ||
227 | +== rechecking image refcounts == | ||
228 | +No errors were found on the image. | ||
229 | + | ||
230 | +== writing some more data == | ||
231 | +wrote 1/1 bytes at offset 512 | ||
232 | +1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
233 | + | ||
234 | +== rechecking image refcounts == | ||
235 | +No errors were found on the image. | ||
236 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 | ||
237 | + | ||
238 | +== cluster size 2048 | ||
239 | +== checking image refcounts == | ||
240 | +No errors were found on the image. | ||
241 | + | ||
242 | +== writing some data == | ||
243 | +wrote 1/1 bytes at offset 0 | ||
244 | +1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
245 | + | ||
246 | +== rechecking image refcounts == | ||
247 | +No errors were found on the image. | ||
248 | + | ||
249 | +== writing some more data == | ||
250 | +wrote 1/1 bytes at offset 2048 | ||
251 | +1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
252 | + | ||
253 | +== rechecking image refcounts == | ||
254 | +No errors were found on the image. | ||
255 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 | ||
256 | + | ||
257 | +== cluster size 32768 | ||
258 | +== checking image refcounts == | ||
259 | +No errors were found on the image. | ||
260 | + | ||
261 | +== writing some data == | ||
262 | +wrote 1/1 bytes at offset 0 | ||
263 | +1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
264 | + | ||
265 | +== rechecking image refcounts == | ||
266 | +No errors were found on the image. | ||
267 | + | ||
268 | +== writing some more data == | ||
269 | +wrote 1/1 bytes at offset 32768 | ||
270 | +1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
271 | + | ||
272 | +== rechecking image refcounts == | ||
273 | +No errors were found on the image. | ||
274 | +*** done | ||
275 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
276 | index XXXXXXX..XXXXXXX 100644 | ||
277 | --- a/tests/qemu-iotests/group | ||
278 | +++ b/tests/qemu-iotests/group | ||
279 | @@ -XXX,XX +XXX,XX @@ | ||
280 | 280 rw migration quick | ||
281 | 281 rw quick | ||
282 | 283 auto quick | ||
283 | +284 rw | ||
140 | -- | 284 | -- |
141 | 2.11.0 | 285 | 2.24.1 |
142 | 286 | ||
143 | 287 | diff view generated by jsdifflib |
1 | From: Peter Lieven <pl@kamp.de> | 1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
---|---|---|---|
2 | 2 | ||
3 | commit 94d6a7a accidentally left the naming of runtime opts and QAPI | 3 | backup-top "supports" write-unchanged, by skipping CBW operation in |
4 | scheme inconsistent. As one consequence passing of parameters in the | 4 | backup_top_co_pwritev. But it forgets to do the same in |
5 | URI is broken. Sync the naming of the runtime opts to the QAPI | 5 | backup_top_co_pwrite_zeroes, as well as declare support for |
6 | scheme. | 6 | BDRV_REQ_WRITE_UNCHANGED. |
7 | 7 | ||
8 | Please note that this is technically backwards incompatible with the 2.8 | 8 | Fix this, and, while being here, declare also support for flags |
9 | release, but the 2.8 release is the only version that had the wrong naming. | 9 | supported by source child. |
10 | Furthermore release 2.8 suffered from a NULL pointer dereference during | ||
11 | URI parsing. | ||
12 | 10 | ||
13 | Fixes: 94d6a7a76e9df9919629428f6c598e2b97d9426c | 11 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
14 | Cc: qemu-stable@nongnu.org | 12 | Message-Id: <20200207161231.32707-1-vsementsov@virtuozzo.com> |
15 | Signed-off-by: Peter Lieven <pl@kamp.de> | ||
16 | Message-id: 1485942829-10756-3-git-send-email-pl@kamp.de | ||
17 | [mreitz: Fixed commit message] | ||
18 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
19 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 13 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
20 | --- | 14 | --- |
21 | block/nfs.c | 46 +++++++++++++++++++++++----------------------- | 15 | block/backup-top.c | 31 ++++++++++++++++++++----------- |
22 | 1 file changed, 23 insertions(+), 23 deletions(-) | 16 | 1 file changed, 20 insertions(+), 11 deletions(-) |
23 | 17 | ||
24 | diff --git a/block/nfs.c b/block/nfs.c | 18 | diff --git a/block/backup-top.c b/block/backup-top.c |
25 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
26 | --- a/block/nfs.c | 20 | --- a/block/backup-top.c |
27 | +++ b/block/nfs.c | 21 | +++ b/block/backup-top.c |
28 | @@ -XXX,XX +XXX,XX @@ static QemuOptsList runtime_opts = { | 22 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_co_preadv( |
29 | .help = "Path of the image on the host", | 23 | } |
30 | }, | 24 | |
31 | { | 25 | static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset, |
32 | - .name = "uid", | 26 | - uint64_t bytes) |
33 | + .name = "user", | 27 | + uint64_t bytes, BdrvRequestFlags flags) |
34 | .type = QEMU_OPT_NUMBER, | 28 | { |
35 | .help = "UID value to use when talking to the server", | 29 | BDRVBackupTopState *s = bs->opaque; |
36 | }, | 30 | - uint64_t end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size); |
37 | { | 31 | - uint64_t off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size); |
38 | - .name = "gid", | 32 | + uint64_t off, end; |
39 | + .name = "group", | 33 | + |
40 | .type = QEMU_OPT_NUMBER, | 34 | + if (flags & BDRV_REQ_WRITE_UNCHANGED) { |
41 | .help = "GID value to use when talking to the server", | 35 | + return 0; |
42 | }, | 36 | + } |
43 | { | 37 | + |
44 | - .name = "tcp-syncnt", | 38 | + off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size); |
45 | + .name = "tcp-syn-count", | 39 | + end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size); |
46 | .type = QEMU_OPT_NUMBER, | 40 | |
47 | .help = "Number of SYNs to send during the session establish", | 41 | return block_copy(s->bcs, off, end - off, NULL); |
48 | }, | 42 | } |
49 | { | 43 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset, |
50 | - .name = "readahead", | 44 | static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs, |
51 | + .name = "readahead-size", | 45 | int64_t offset, int bytes) |
52 | .type = QEMU_OPT_NUMBER, | 46 | { |
53 | .help = "Set the readahead size in bytes", | 47 | - int ret = backup_top_cbw(bs, offset, bytes); |
54 | }, | 48 | + int ret = backup_top_cbw(bs, offset, bytes, 0); |
55 | { | 49 | if (ret < 0) { |
56 | - .name = "pagecache", | 50 | return ret; |
57 | + .name = "page-cache-size", | ||
58 | .type = QEMU_OPT_NUMBER, | ||
59 | .help = "Set the pagecache size in bytes", | ||
60 | }, | ||
61 | @@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options, | ||
62 | goto fail; | ||
63 | } | 51 | } |
64 | 52 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs, | |
65 | - if (qemu_opt_get(opts, "uid")) { | 53 | static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs, |
66 | - client->uid = qemu_opt_get_number(opts, "uid", 0); | 54 | int64_t offset, int bytes, BdrvRequestFlags flags) |
67 | + if (qemu_opt_get(opts, "user")) { | 55 | { |
68 | + client->uid = qemu_opt_get_number(opts, "user", 0); | 56 | - int ret = backup_top_cbw(bs, offset, bytes); |
69 | nfs_set_uid(client->context, client->uid); | 57 | + int ret = backup_top_cbw(bs, offset, bytes, flags); |
58 | if (ret < 0) { | ||
59 | return ret; | ||
70 | } | 60 | } |
71 | 61 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs, | |
72 | - if (qemu_opt_get(opts, "gid")) { | 62 | uint64_t bytes, |
73 | - client->gid = qemu_opt_get_number(opts, "gid", 0); | 63 | QEMUIOVector *qiov, int flags) |
74 | + if (qemu_opt_get(opts, "group")) { | 64 | { |
75 | + client->gid = qemu_opt_get_number(opts, "group", 0); | 65 | - if (!(flags & BDRV_REQ_WRITE_UNCHANGED)) { |
76 | nfs_set_gid(client->context, client->gid); | 66 | - int ret = backup_top_cbw(bs, offset, bytes); |
67 | - if (ret < 0) { | ||
68 | - return ret; | ||
69 | - } | ||
70 | + int ret = backup_top_cbw(bs, offset, bytes, flags); | ||
71 | + if (ret < 0) { | ||
72 | + return ret; | ||
77 | } | 73 | } |
78 | 74 | ||
79 | - if (qemu_opt_get(opts, "tcp-syncnt")) { | 75 | return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags); |
80 | - client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syncnt", 0); | 76 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, |
81 | + if (qemu_opt_get(opts, "tcp-syn-count")) { | 77 | return NULL; |
82 | + client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syn-count", 0); | ||
83 | nfs_set_tcp_syncnt(client->context, client->tcp_syncnt); | ||
84 | } | 78 | } |
85 | 79 | ||
86 | #ifdef LIBNFS_FEATURE_READAHEAD | 80 | - top->total_sectors = source->total_sectors; |
87 | - if (qemu_opt_get(opts, "readahead")) { | 81 | state = top->opaque; |
88 | + if (qemu_opt_get(opts, "readahead-size")) { | 82 | + top->total_sectors = source->total_sectors; |
89 | if (open_flags & BDRV_O_NOCACHE) { | 83 | + top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | |
90 | error_setg(errp, "Cannot enable NFS readahead " | 84 | + (BDRV_REQ_FUA & source->supported_write_flags); |
91 | "if cache.direct = on"); | 85 | + top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | |
92 | goto fail; | 86 | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & |
93 | } | 87 | + source->supported_zero_flags); |
94 | - client->readahead = qemu_opt_get_number(opts, "readahead", 0); | 88 | |
95 | + client->readahead = qemu_opt_get_number(opts, "readahead-size", 0); | 89 | bdrv_ref(target); |
96 | if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) { | 90 | state->target = bdrv_attach_child(top, target, "target", &child_file, errp); |
97 | error_report("NFS Warning: Truncating NFS readahead " | ||
98 | "size to %d", QEMU_NFS_MAX_READAHEAD_SIZE); | ||
99 | @@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options, | ||
100 | #endif | ||
101 | |||
102 | #ifdef LIBNFS_FEATURE_PAGECACHE | ||
103 | - if (qemu_opt_get(opts, "pagecache")) { | ||
104 | + if (qemu_opt_get(opts, "page-cache-size")) { | ||
105 | if (open_flags & BDRV_O_NOCACHE) { | ||
106 | error_setg(errp, "Cannot enable NFS pagecache " | ||
107 | "if cache.direct = on"); | ||
108 | goto fail; | ||
109 | } | ||
110 | - client->pagecache = qemu_opt_get_number(opts, "pagecache", 0); | ||
111 | + client->pagecache = qemu_opt_get_number(opts, "page-cache-size", 0); | ||
112 | if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) { | ||
113 | error_report("NFS Warning: Truncating NFS pagecache " | ||
114 | "size to %d pages", QEMU_NFS_MAX_PAGECACHE_SIZE); | ||
115 | @@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options) | ||
116 | qdict_put(opts, "path", qstring_from_str(client->path)); | ||
117 | |||
118 | if (client->uid) { | ||
119 | - qdict_put(opts, "uid", qint_from_int(client->uid)); | ||
120 | + qdict_put(opts, "user", qint_from_int(client->uid)); | ||
121 | } | ||
122 | if (client->gid) { | ||
123 | - qdict_put(opts, "gid", qint_from_int(client->gid)); | ||
124 | + qdict_put(opts, "group", qint_from_int(client->gid)); | ||
125 | } | ||
126 | if (client->tcp_syncnt) { | ||
127 | - qdict_put(opts, "tcp-syncnt", | ||
128 | - qint_from_int(client->tcp_syncnt)); | ||
129 | + qdict_put(opts, "tcp-syn-cnt", | ||
130 | + qint_from_int(client->tcp_syncnt)); | ||
131 | } | ||
132 | if (client->readahead) { | ||
133 | - qdict_put(opts, "readahead", | ||
134 | - qint_from_int(client->readahead)); | ||
135 | + qdict_put(opts, "readahead-size", | ||
136 | + qint_from_int(client->readahead)); | ||
137 | } | ||
138 | if (client->pagecache) { | ||
139 | - qdict_put(opts, "pagecache", | ||
140 | - qint_from_int(client->pagecache)); | ||
141 | + qdict_put(opts, "page-cache-size", | ||
142 | + qint_from_int(client->pagecache)); | ||
143 | } | ||
144 | if (client->debug) { | ||
145 | qdict_put(opts, "debug", qint_from_int(client->debug)); | ||
146 | -- | 91 | -- |
147 | 2.11.0 | 92 | 2.24.1 |
148 | 93 | ||
149 | 94 | diff view generated by jsdifflib |
1 | From: Peter Maydell <peter.maydell@linaro.org> | 1 | First, driver=qcow2 will not work so well with non-qcow2 formats (and |
---|---|---|---|
2 | this test claims to support qcow, qed, and vmdk). | ||
2 | 3 | ||
3 | Some of the argument parsing in qemu-img uses strtoul() to parse | 4 | Second, vmdk will always report the backing file format to be vmdk. |
4 | integer arguments. This is tricky to get correct and in fact the | 5 | Filter that out so the output looks like for all other formats. |
5 | code does not get it right, because it assigns the result of | ||
6 | strtoul() to an 'int' variable and then tries to check for > INT_MAX. | ||
7 | Coverity correctly complains that the comparison is always false. | ||
8 | 6 | ||
9 | Rewrite to use qemu_strtoul(), which has a saner convention for | 7 | Third, the flat vmdk subformats do not support backing files, so they |
10 | reporting conversion failures. | 8 | will not work with this test. |
11 | 9 | ||
12 | (Fixes CID 1356421, CID 1356422, CID 1356423.) | 10 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
13 | 11 | Message-Id: <20191219144243.1763246-1-mreitz@redhat.com> | |
14 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Tested-by: Thomas Huth <thuth@redhat.com> |
15 | Message-id: 1486744104-15590-2-git-send-email-peter.maydell@linaro.org | ||
16 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
17 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 13 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
18 | --- | 14 | --- |
19 | qemu-img.c | 32 ++++++++++++++++---------------- | 15 | tests/qemu-iotests/279 | 7 +++++-- |
20 | 1 file changed, 16 insertions(+), 16 deletions(-) | 16 | 1 file changed, 5 insertions(+), 2 deletions(-) |
21 | 17 | ||
22 | diff --git a/qemu-img.c b/qemu-img.c | 18 | diff --git a/tests/qemu-iotests/279 b/tests/qemu-iotests/279 |
23 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100755 |
24 | --- a/qemu-img.c | 20 | --- a/tests/qemu-iotests/279 |
25 | +++ b/qemu-img.c | 21 | +++ b/tests/qemu-iotests/279 |
26 | @@ -XXX,XX +XXX,XX @@ static int img_bench(int argc, char **argv) | 22 | @@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15 |
27 | break; | 23 | _supported_fmt qcow qcow2 vmdk qed |
28 | case 'c': | 24 | _supported_proto file |
29 | { | 25 | _supported_os Linux |
30 | - char *end; | 26 | +_unsupported_imgopts "subformat=monolithicFlat" \ |
31 | - errno = 0; | 27 | + "subformat=twoGbMaxExtentFlat" \ |
32 | - count = strtoul(optarg, &end, 0); | 28 | |
33 | - if (errno || *end || count > INT_MAX) { | 29 | TEST_IMG="$TEST_IMG.base" _make_test_img 64M |
34 | + unsigned long res; | 30 | TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" |
35 | + | 31 | @@ -XXX,XX +XXX,XX @@ _make_test_img -b "$TEST_IMG.mid" |
36 | + if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) { | 32 | |
37 | error_report("Invalid request count specified"); | 33 | echo |
38 | return 1; | 34 | echo '== qemu-img info --backing-chain ==' |
39 | } | 35 | -_img_info --backing-chain | _filter_img_info |
40 | + count = res; | 36 | +_img_info --backing-chain | _filter_img_info | grep -v 'backing file format' |
41 | break; | 37 | |
42 | } | 38 | echo |
43 | case 'd': | 39 | echo '== qemu-img info --backing-chain --image-opts ==' |
44 | { | 40 | -TEST_IMG="driver=qcow2,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts | _filter_img_info |
45 | - char *end; | 41 | +TEST_IMG="driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts \ |
46 | - errno = 0; | 42 | + | _filter_img_info | grep -v 'backing file format' |
47 | - depth = strtoul(optarg, &end, 0); | 43 | |
48 | - if (errno || *end || depth > INT_MAX) { | 44 | # success, all done |
49 | + unsigned long res; | 45 | echo "*** done" |
50 | + | ||
51 | + if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) { | ||
52 | error_report("Invalid queue depth specified"); | ||
53 | return 1; | ||
54 | } | ||
55 | + depth = res; | ||
56 | break; | ||
57 | } | ||
58 | case 'f': | ||
59 | @@ -XXX,XX +XXX,XX @@ static int img_bench(int argc, char **argv) | ||
60 | break; | ||
61 | case OPTION_PATTERN: | ||
62 | { | ||
63 | - char *end; | ||
64 | - errno = 0; | ||
65 | - pattern = strtoul(optarg, &end, 0); | ||
66 | - if (errno || *end || pattern > 0xff) { | ||
67 | + unsigned long res; | ||
68 | + | ||
69 | + if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > 0xff) { | ||
70 | error_report("Invalid pattern byte specified"); | ||
71 | return 1; | ||
72 | } | ||
73 | + pattern = res; | ||
74 | break; | ||
75 | } | ||
76 | case OPTION_FLUSH_INTERVAL: | ||
77 | { | ||
78 | - char *end; | ||
79 | - errno = 0; | ||
80 | - flush_interval = strtoul(optarg, &end, 0); | ||
81 | - if (errno || *end || flush_interval > INT_MAX) { | ||
82 | + unsigned long res; | ||
83 | + | ||
84 | + if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) { | ||
85 | error_report("Invalid flush interval specified"); | ||
86 | return 1; | ||
87 | } | ||
88 | + flush_interval = res; | ||
89 | break; | ||
90 | } | ||
91 | case OPTION_NO_DRAIN: | ||
92 | -- | 46 | -- |
93 | 2.11.0 | 47 | 2.24.1 |
94 | 48 | ||
95 | 49 | diff view generated by jsdifflib |
1 | From: Dou Liyang <douly.fnst@cn.fujitsu.com> | 1 | When nbd_close() is called from a coroutine, the connection_co never |
---|---|---|---|
2 | gets to run, and thus nbd_teardown_connection() hangs. | ||
2 | 3 | ||
3 | The bdrv_query_stats and bdrv_query_bds_stats functions need to call | 4 | This is because aio_co_enter() only puts the connection_co into the main |
4 | each other, that increases the coupling. it also makes the program | 5 | coroutine's wake-up queue, so this main coroutine needs to yield and |
5 | complicated and makes some unnecessary tests. | 6 | wait for connection_co to terminate. |
6 | 7 | ||
7 | Remove the call from bdrv_query_bds_stats to bdrv_query_stats, just | 8 | Suggested-by: Kevin Wolf <kwolf@redhat.com> |
8 | take some recursion to make it clearly. | 9 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
9 | 10 | Message-Id: <20200122164532.178040-2-mreitz@redhat.com> | |
10 | Avoid testing whether the blk is NULL during querying the bds stats. | 11 | Reviewed-by: Eric Blake <eblake@redhat.com> |
11 | It is unnecessary. | 12 | Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> |
12 | |||
13 | Signed-off-by: Dou Liyang <douly.fnst@cn.fujitsu.com> | ||
14 | Message-id: 1484467275-27919-2-git-send-email-douly.fnst@cn.fujitsu.com | ||
15 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
16 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 13 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
17 | --- | 14 | --- |
18 | block/qapi.c | 26 ++++++++++++++------------ | 15 | block/nbd.c | 14 +++++++++++++- |
19 | 1 file changed, 14 insertions(+), 12 deletions(-) | 16 | 1 file changed, 13 insertions(+), 1 deletion(-) |
20 | 17 | ||
21 | diff --git a/block/qapi.c b/block/qapi.c | 18 | diff --git a/block/nbd.c b/block/nbd.c |
22 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/block/qapi.c | 20 | --- a/block/nbd.c |
24 | +++ b/block/qapi.c | 21 | +++ b/block/nbd.c |
25 | @@ -XXX,XX +XXX,XX @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info, | 22 | @@ -XXX,XX +XXX,XX @@ typedef struct BDRVNBDState { |
26 | qapi_free_BlockInfo(info); | 23 | CoMutex send_mutex; |
24 | CoQueue free_sema; | ||
25 | Coroutine *connection_co; | ||
26 | + Coroutine *teardown_co; | ||
27 | QemuCoSleepState *connection_co_sleep_ns_state; | ||
28 | bool drained; | ||
29 | bool wait_drained_end; | ||
30 | @@ -XXX,XX +XXX,XX @@ static void nbd_teardown_connection(BlockDriverState *bs) | ||
31 | qemu_co_sleep_wake(s->connection_co_sleep_ns_state); | ||
32 | } | ||
33 | } | ||
34 | - BDRV_POLL_WHILE(bs, s->connection_co); | ||
35 | + if (qemu_in_coroutine()) { | ||
36 | + s->teardown_co = qemu_coroutine_self(); | ||
37 | + /* connection_co resumes us when it terminates */ | ||
38 | + qemu_coroutine_yield(); | ||
39 | + s->teardown_co = NULL; | ||
40 | + } else { | ||
41 | + BDRV_POLL_WHILE(bs, s->connection_co); | ||
42 | + } | ||
43 | + assert(!s->connection_co); | ||
27 | } | 44 | } |
28 | 45 | ||
29 | -static BlockStats *bdrv_query_stats(BlockBackend *blk, | 46 | static bool nbd_client_connecting(BDRVNBDState *s) |
30 | - const BlockDriverState *bs, | 47 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque) |
31 | - bool query_backing); | 48 | s->ioc = NULL; |
32 | - | ||
33 | static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk) | ||
34 | { | ||
35 | BlockAcctStats *stats = blk_get_stats(blk); | ||
36 | @@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk) | ||
37 | } | 49 | } |
50 | |||
51 | + if (s->teardown_co) { | ||
52 | + aio_co_wake(s->teardown_co); | ||
53 | + } | ||
54 | aio_wait_kick(); | ||
38 | } | 55 | } |
39 | 56 | ||
40 | -static void bdrv_query_bds_stats(BlockStats *s, const BlockDriverState *bs, | ||
41 | +static BlockStats *bdrv_query_bds_stats(const BlockDriverState *bs, | ||
42 | bool query_backing) | ||
43 | { | ||
44 | + BlockStats *s = NULL; | ||
45 | + | ||
46 | + s = g_malloc0(sizeof(*s)); | ||
47 | + s->stats = g_malloc0(sizeof(*s->stats)); | ||
48 | + | ||
49 | + if (!bs) { | ||
50 | + return s; | ||
51 | + } | ||
52 | + | ||
53 | if (bdrv_get_node_name(bs)[0]) { | ||
54 | s->has_node_name = true; | ||
55 | s->node_name = g_strdup(bdrv_get_node_name(bs)); | ||
56 | @@ -XXX,XX +XXX,XX @@ static void bdrv_query_bds_stats(BlockStats *s, const BlockDriverState *bs, | ||
57 | |||
58 | if (bs->file) { | ||
59 | s->has_parent = true; | ||
60 | - s->parent = bdrv_query_stats(NULL, bs->file->bs, query_backing); | ||
61 | + s->parent = bdrv_query_bds_stats(bs->file->bs, query_backing); | ||
62 | } | ||
63 | |||
64 | if (query_backing && bs->backing) { | ||
65 | s->has_backing = true; | ||
66 | - s->backing = bdrv_query_stats(NULL, bs->backing->bs, query_backing); | ||
67 | + s->backing = bdrv_query_bds_stats(bs->backing->bs, query_backing); | ||
68 | } | ||
69 | |||
70 | + return s; | ||
71 | } | ||
72 | |||
73 | static BlockStats *bdrv_query_stats(BlockBackend *blk, | ||
74 | @@ -XXX,XX +XXX,XX @@ static BlockStats *bdrv_query_stats(BlockBackend *blk, | ||
75 | { | ||
76 | BlockStats *s; | ||
77 | |||
78 | - s = g_malloc0(sizeof(*s)); | ||
79 | - s->stats = g_malloc0(sizeof(*s->stats)); | ||
80 | + s = bdrv_query_bds_stats(bs, query_backing); | ||
81 | |||
82 | if (blk) { | ||
83 | s->has_device = true; | ||
84 | s->device = g_strdup(blk_name(blk)); | ||
85 | bdrv_query_blk_stats(s->stats, blk); | ||
86 | } | ||
87 | - if (bs) { | ||
88 | - bdrv_query_bds_stats(s, bs, query_backing); | ||
89 | - } | ||
90 | |||
91 | return s; | ||
92 | } | ||
93 | -- | 57 | -- |
94 | 2.11.0 | 58 | 2.24.1 |
95 | 59 | ||
96 | 60 | diff view generated by jsdifflib |
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 1 | If a protocol driver does not support image creation, we can see whether |
---|---|---|---|
2 | 2 | maybe the file exists already. If so, just truncating it will be | |
3 | Current implementation invalidates firstly parent bds and then its | 3 | sufficient. |
4 | children. This leads to the following bug: | 4 | |
5 | 5 | Signed-off-by: Max Reitz <mreitz@redhat.com> | |
6 | after incoming migration, in bdrv_invalidate_cache_all: | 6 | Message-Id: <20200122164532.178040-3-mreitz@redhat.com> |
7 | 1. invalidate parent bds - reopen it with BDRV_O_INACTIVE cleared | ||
8 | 2. child is not yet invalidated | ||
9 | 3. parent check that its BDRV_O_INACTIVE is cleared | ||
10 | 4. parent writes to child | ||
11 | 5. assert in bdrv_co_pwritev, as BDRV_O_INACTIVE is set for child | ||
12 | |||
13 | This patch fixes it by just changing invalidate sequence: invalidate | ||
14 | children first. | ||
15 | |||
16 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
17 | Message-id: 20170131112308.54189-1-vsementsov@virtuozzo.com | ||
18 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
19 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
20 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 7 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
21 | --- | 8 | --- |
22 | block.c | 11 +++++------ | 9 | block.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++----- |
23 | 1 file changed, 5 insertions(+), 6 deletions(-) | 10 | 1 file changed, 147 insertions(+), 12 deletions(-) |
24 | 11 | ||
25 | diff --git a/block.c b/block.c | 12 | diff --git a/block.c b/block.c |
26 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
27 | --- a/block.c | 14 | --- a/block.c |
28 | +++ b/block.c | 15 | +++ b/block.c |
29 | @@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp) | 16 | @@ -XXX,XX +XXX,XX @@ out: |
30 | if (!(bs->open_flags & BDRV_O_INACTIVE)) { | 17 | return ret; |
18 | } | ||
19 | |||
20 | -int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp) | ||
21 | +/** | ||
22 | + * Helper function for bdrv_create_file_fallback(): Resize @blk to at | ||
23 | + * least the given @minimum_size. | ||
24 | + * | ||
25 | + * On success, return @blk's actual length. | ||
26 | + * Otherwise, return -errno. | ||
27 | + */ | ||
28 | +static int64_t create_file_fallback_truncate(BlockBackend *blk, | ||
29 | + int64_t minimum_size, Error **errp) | ||
30 | { | ||
31 | - BlockDriver *drv; | ||
32 | + Error *local_err = NULL; | ||
33 | + int64_t size; | ||
34 | + int ret; | ||
35 | + | ||
36 | + ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err); | ||
37 | + if (ret < 0 && ret != -ENOTSUP) { | ||
38 | + error_propagate(errp, local_err); | ||
39 | + return ret; | ||
40 | + } | ||
41 | + | ||
42 | + size = blk_getlength(blk); | ||
43 | + if (size < 0) { | ||
44 | + error_free(local_err); | ||
45 | + error_setg_errno(errp, -size, | ||
46 | + "Failed to inquire the new image file's length"); | ||
47 | + return size; | ||
48 | + } | ||
49 | + | ||
50 | + if (size < minimum_size) { | ||
51 | + /* Need to grow the image, but we failed to do that */ | ||
52 | + error_propagate(errp, local_err); | ||
53 | + return -ENOTSUP; | ||
54 | + } | ||
55 | + | ||
56 | + error_free(local_err); | ||
57 | + local_err = NULL; | ||
58 | + | ||
59 | + return size; | ||
60 | +} | ||
61 | + | ||
62 | +/** | ||
63 | + * Helper function for bdrv_create_file_fallback(): Zero the first | ||
64 | + * sector to remove any potentially pre-existing image header. | ||
65 | + */ | ||
66 | +static int create_file_fallback_zero_first_sector(BlockBackend *blk, | ||
67 | + int64_t current_size, | ||
68 | + Error **errp) | ||
69 | +{ | ||
70 | + int64_t bytes_to_clear; | ||
71 | + int ret; | ||
72 | + | ||
73 | + bytes_to_clear = MIN(current_size, BDRV_SECTOR_SIZE); | ||
74 | + if (bytes_to_clear) { | ||
75 | + ret = blk_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP); | ||
76 | + if (ret < 0) { | ||
77 | + error_setg_errno(errp, -ret, | ||
78 | + "Failed to clear the new image's first sector"); | ||
79 | + return ret; | ||
80 | + } | ||
81 | + } | ||
82 | + | ||
83 | + return 0; | ||
84 | +} | ||
85 | + | ||
86 | +static int bdrv_create_file_fallback(const char *filename, BlockDriver *drv, | ||
87 | + QemuOpts *opts, Error **errp) | ||
88 | +{ | ||
89 | + BlockBackend *blk; | ||
90 | + QDict *options = qdict_new(); | ||
91 | + int64_t size = 0; | ||
92 | + char *buf = NULL; | ||
93 | + PreallocMode prealloc; | ||
94 | Error *local_err = NULL; | ||
95 | int ret; | ||
96 | |||
97 | + size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0); | ||
98 | + buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); | ||
99 | + prealloc = qapi_enum_parse(&PreallocMode_lookup, buf, | ||
100 | + PREALLOC_MODE_OFF, &local_err); | ||
101 | + g_free(buf); | ||
102 | + if (local_err) { | ||
103 | + error_propagate(errp, local_err); | ||
104 | + return -EINVAL; | ||
105 | + } | ||
106 | + | ||
107 | + if (prealloc != PREALLOC_MODE_OFF) { | ||
108 | + error_setg(errp, "Unsupported preallocation mode '%s'", | ||
109 | + PreallocMode_str(prealloc)); | ||
110 | + return -ENOTSUP; | ||
111 | + } | ||
112 | + | ||
113 | + qdict_put_str(options, "driver", drv->format_name); | ||
114 | + | ||
115 | + blk = blk_new_open(filename, NULL, options, | ||
116 | + BDRV_O_RDWR | BDRV_O_RESIZE, errp); | ||
117 | + if (!blk) { | ||
118 | + error_prepend(errp, "Protocol driver '%s' does not support image " | ||
119 | + "creation, and opening the image failed: ", | ||
120 | + drv->format_name); | ||
121 | + return -EINVAL; | ||
122 | + } | ||
123 | + | ||
124 | + size = create_file_fallback_truncate(blk, size, errp); | ||
125 | + if (size < 0) { | ||
126 | + ret = size; | ||
127 | + goto out; | ||
128 | + } | ||
129 | + | ||
130 | + ret = create_file_fallback_zero_first_sector(blk, size, errp); | ||
131 | + if (ret < 0) { | ||
132 | + goto out; | ||
133 | + } | ||
134 | + | ||
135 | + ret = 0; | ||
136 | +out: | ||
137 | + blk_unref(blk); | ||
138 | + return ret; | ||
139 | +} | ||
140 | + | ||
141 | +int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp) | ||
142 | +{ | ||
143 | + BlockDriver *drv; | ||
144 | + | ||
145 | drv = bdrv_find_protocol(filename, true, errp); | ||
146 | if (drv == NULL) { | ||
147 | return -ENOENT; | ||
148 | } | ||
149 | |||
150 | - ret = bdrv_create(drv, filename, opts, &local_err); | ||
151 | - error_propagate(errp, local_err); | ||
152 | - return ret; | ||
153 | + if (drv->bdrv_co_create_opts) { | ||
154 | + return bdrv_create(drv, filename, opts, errp); | ||
155 | + } else { | ||
156 | + return bdrv_create_file_fallback(filename, drv, opts, errp); | ||
157 | + } | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | @@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = { | ||
162 | }, | ||
163 | }; | ||
164 | |||
165 | +static QemuOptsList fallback_create_opts = { | ||
166 | + .name = "fallback-create-opts", | ||
167 | + .head = QTAILQ_HEAD_INITIALIZER(fallback_create_opts.head), | ||
168 | + .desc = { | ||
169 | + { | ||
170 | + .name = BLOCK_OPT_SIZE, | ||
171 | + .type = QEMU_OPT_SIZE, | ||
172 | + .help = "Virtual disk size" | ||
173 | + }, | ||
174 | + { | ||
175 | + .name = BLOCK_OPT_PREALLOC, | ||
176 | + .type = QEMU_OPT_STRING, | ||
177 | + .help = "Preallocation mode (allowed values: off)" | ||
178 | + }, | ||
179 | + { /* end of list */ } | ||
180 | + } | ||
181 | +}; | ||
182 | + | ||
183 | /* | ||
184 | * Common part for opening disk images and files | ||
185 | * | ||
186 | @@ -XXX,XX +XXX,XX @@ void bdrv_img_create(const char *filename, const char *fmt, | ||
31 | return; | 187 | return; |
32 | } | 188 | } |
33 | - bs->open_flags &= ~BDRV_O_INACTIVE; | 189 | |
34 | 190 | - if (!proto_drv->create_opts) { | |
35 | - if (bs->drv->bdrv_invalidate_cache) { | 191 | - error_setg(errp, "Protocol driver '%s' does not support image creation", |
36 | - bs->drv->bdrv_invalidate_cache(bs, &local_err); | 192 | - proto_drv->format_name); |
37 | + QLIST_FOREACH(child, &bs->children, next) { | 193 | - return; |
38 | + bdrv_invalidate_cache(child->bs, &local_err); | 194 | - } |
39 | if (local_err) { | 195 | - |
40 | - bs->open_flags |= BDRV_O_INACTIVE; | 196 | /* Create parameter list */ |
41 | error_propagate(errp, local_err); | 197 | create_opts = qemu_opts_append(create_opts, drv->create_opts); |
42 | return; | 198 | - create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); |
43 | } | 199 | + if (proto_drv->create_opts) { |
44 | } | 200 | + create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); |
45 | 201 | + } else { | |
46 | - QLIST_FOREACH(child, &bs->children, next) { | 202 | + create_opts = qemu_opts_append(create_opts, &fallback_create_opts); |
47 | - bdrv_invalidate_cache(child->bs, &local_err); | 203 | + } |
48 | + bs->open_flags &= ~BDRV_O_INACTIVE; | 204 | |
49 | + if (bs->drv->bdrv_invalidate_cache) { | 205 | opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); |
50 | + bs->drv->bdrv_invalidate_cache(bs, &local_err); | 206 | |
51 | if (local_err) { | ||
52 | bs->open_flags |= BDRV_O_INACTIVE; | ||
53 | error_propagate(errp, local_err); | ||
54 | -- | 207 | -- |
55 | 2.11.0 | 208 | 2.24.1 |
56 | 209 | ||
57 | 210 | diff view generated by jsdifflib |
1 | From: QingFeng Hao <haoqf@linux.vnet.ibm.com> | 1 | The generic fallback implementation effectively does the same. |
---|---|---|---|
2 | 2 | ||
3 | If TEST_DIR is set to /tmp, test case 144 will fail. The reason is that | 3 | Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> |
4 | TEST_DIR resembles 144's test image name tmp.qcow2. | 4 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
5 | When 144 is testing $TEST_DIR/tmp.qcow2, it wants to replace | 5 | Message-Id: <20200122164532.178040-4-mreitz@redhat.com> |
6 | $TEST_DIR/tmp.qcow2 to TEST_DIR/tmp.qcow2, but actually it will fail | ||
7 | and get TEST_DIRTEST_DIR.qcow2 in this case. | ||
8 | The fix is just to modify the code to replace $TEST_DIR/ with TEST_DIR/. | ||
9 | |||
10 | Signed-off-by: QingFeng Hao <haoqf@linux.vnet.ibm.com> | ||
11 | Message-id: 20161216054723.96055-2-haoqf@linux.vnet.ibm.com | ||
12 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
13 | [mreitz: Fixed commit message and dropped superfluous escaping] | ||
14 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 6 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
15 | --- | 7 | --- |
16 | tests/qemu-iotests/common.filter | 2 +- | 8 | block/file-posix.c | 67 ---------------------------------------------- |
17 | 1 file changed, 1 insertion(+), 1 deletion(-) | 9 | 1 file changed, 67 deletions(-) |
18 | 10 | ||
19 | diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter | 11 | diff --git a/block/file-posix.c b/block/file-posix.c |
20 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/tests/qemu-iotests/common.filter | 13 | --- a/block/file-posix.c |
22 | +++ b/tests/qemu-iotests/common.filter | 14 | +++ b/block/file-posix.c |
23 | @@ -XXX,XX +XXX,XX @@ _filter_generated_node_ids() | 15 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs, |
24 | # replace occurrences of the actual TEST_DIR value with TEST_DIR | 16 | return raw_do_pwrite_zeroes(bs, offset, bytes, flags, true); |
25 | _filter_testdir() | ||
26 | { | ||
27 | - sed -e "s#$TEST_DIR#TEST_DIR#g" | ||
28 | + sed -e "s#$TEST_DIR/#TEST_DIR/#g" | ||
29 | } | 17 | } |
30 | 18 | ||
31 | # replace occurrences of the actual IMGFMT value with IMGFMT | 19 | -static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts, |
20 | - Error **errp) | ||
21 | -{ | ||
22 | - int fd; | ||
23 | - int ret = 0; | ||
24 | - struct stat stat_buf; | ||
25 | - int64_t total_size = 0; | ||
26 | - bool has_prefix; | ||
27 | - | ||
28 | - /* This function is used by both protocol block drivers and therefore either | ||
29 | - * of these prefixes may be given. | ||
30 | - * The return value has to be stored somewhere, otherwise this is an error | ||
31 | - * due to -Werror=unused-value. */ | ||
32 | - has_prefix = | ||
33 | - strstart(filename, "host_device:", &filename) || | ||
34 | - strstart(filename, "host_cdrom:" , &filename); | ||
35 | - | ||
36 | - (void)has_prefix; | ||
37 | - | ||
38 | - ret = raw_normalize_devicepath(&filename, errp); | ||
39 | - if (ret < 0) { | ||
40 | - return ret; | ||
41 | - } | ||
42 | - | ||
43 | - /* Read out options */ | ||
44 | - total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), | ||
45 | - BDRV_SECTOR_SIZE); | ||
46 | - | ||
47 | - fd = qemu_open(filename, O_WRONLY | O_BINARY); | ||
48 | - if (fd < 0) { | ||
49 | - ret = -errno; | ||
50 | - error_setg_errno(errp, -ret, "Could not open device"); | ||
51 | - return ret; | ||
52 | - } | ||
53 | - | ||
54 | - if (fstat(fd, &stat_buf) < 0) { | ||
55 | - ret = -errno; | ||
56 | - error_setg_errno(errp, -ret, "Could not stat device"); | ||
57 | - } else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode)) { | ||
58 | - error_setg(errp, | ||
59 | - "The given file is neither a block nor a character device"); | ||
60 | - ret = -ENODEV; | ||
61 | - } else if (lseek(fd, 0, SEEK_END) < total_size) { | ||
62 | - error_setg(errp, "Device is too small"); | ||
63 | - ret = -ENOSPC; | ||
64 | - } | ||
65 | - | ||
66 | - if (!ret && total_size) { | ||
67 | - uint8_t buf[BDRV_SECTOR_SIZE] = { 0 }; | ||
68 | - int64_t zero_size = MIN(BDRV_SECTOR_SIZE, total_size); | ||
69 | - if (lseek(fd, 0, SEEK_SET) == -1) { | ||
70 | - ret = -errno; | ||
71 | - } else { | ||
72 | - ret = qemu_write_full(fd, buf, zero_size); | ||
73 | - ret = ret == zero_size ? 0 : -errno; | ||
74 | - } | ||
75 | - } | ||
76 | - qemu_close(fd); | ||
77 | - return ret; | ||
78 | -} | ||
79 | - | ||
80 | static BlockDriver bdrv_host_device = { | ||
81 | .format_name = "host_device", | ||
82 | .protocol_name = "host_device", | ||
83 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = { | ||
84 | .bdrv_reopen_prepare = raw_reopen_prepare, | ||
85 | .bdrv_reopen_commit = raw_reopen_commit, | ||
86 | .bdrv_reopen_abort = raw_reopen_abort, | ||
87 | - .bdrv_co_create_opts = hdev_co_create_opts, | ||
88 | - .create_opts = &raw_create_opts, | ||
89 | .mutable_opts = mutable_opts, | ||
90 | .bdrv_co_invalidate_cache = raw_co_invalidate_cache, | ||
91 | .bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes, | ||
92 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = { | ||
93 | .bdrv_reopen_prepare = raw_reopen_prepare, | ||
94 | .bdrv_reopen_commit = raw_reopen_commit, | ||
95 | .bdrv_reopen_abort = raw_reopen_abort, | ||
96 | - .bdrv_co_create_opts = hdev_co_create_opts, | ||
97 | - .create_opts = &raw_create_opts, | ||
98 | .mutable_opts = mutable_opts, | ||
99 | .bdrv_co_invalidate_cache = raw_co_invalidate_cache, | ||
100 | |||
101 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = { | ||
102 | .bdrv_reopen_prepare = raw_reopen_prepare, | ||
103 | .bdrv_reopen_commit = raw_reopen_commit, | ||
104 | .bdrv_reopen_abort = raw_reopen_abort, | ||
105 | - .bdrv_co_create_opts = hdev_co_create_opts, | ||
106 | - .create_opts = &raw_create_opts, | ||
107 | .mutable_opts = mutable_opts, | ||
108 | |||
109 | .bdrv_co_preadv = raw_co_preadv, | ||
32 | -- | 110 | -- |
33 | 2.11.0 | 111 | 2.24.1 |
34 | 112 | ||
35 | 113 | diff view generated by jsdifflib |
1 | From: Nir Soffer <nirsof@gmail.com> | 1 | The generic fallback implementation effectively does the same. |
---|---|---|---|
2 | 2 | ||
3 | This helper allows adding tests supporting any format expect the | 3 | Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> |
4 | specified formats. This may be useful to test that many formats behave | 4 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
5 | in a common way. | 5 | Message-Id: <20200122164532.178040-5-mreitz@redhat.com> |
6 | |||
7 | Signed-off-by: Nir Soffer <nirsof@gmail.com> | ||
8 | Message-id: 20170201003120.23378-3-nirsof@gmail.com | ||
9 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
10 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 6 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
11 | --- | 7 | --- |
12 | tests/qemu-iotests/common.rc | 11 +++++++++++ | 8 | block/iscsi.c | 56 --------------------------------------------------- |
13 | 1 file changed, 11 insertions(+) | 9 | 1 file changed, 56 deletions(-) |
14 | 10 | ||
15 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc | 11 | diff --git a/block/iscsi.c b/block/iscsi.c |
16 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/tests/qemu-iotests/common.rc | 13 | --- a/block/iscsi.c |
18 | +++ b/tests/qemu-iotests/common.rc | 14 | +++ b/block/iscsi.c |
19 | @@ -XXX,XX +XXX,XX @@ _supported_fmt() | 15 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset, |
20 | _notrun "not suitable for this image format: $IMGFMT" | 16 | return 0; |
21 | } | 17 | } |
22 | 18 | ||
23 | +# tests whether $IMGFMT is one of the unsupported image format for a test | 19 | -static int coroutine_fn iscsi_co_create_opts(const char *filename, QemuOpts *opts, |
24 | +# | 20 | - Error **errp) |
25 | +_unsupported_fmt() | 21 | -{ |
26 | +{ | 22 | - int ret = 0; |
27 | + for f; do | 23 | - int64_t total_size = 0; |
28 | + if [ "$f" = "$IMGFMT" ]; then | 24 | - BlockDriverState *bs; |
29 | + _notrun "not suitable for this image format: $IMGFMT" | 25 | - IscsiLun *iscsilun = NULL; |
30 | + fi | 26 | - QDict *bs_options; |
31 | + done | 27 | - Error *local_err = NULL; |
32 | +} | 28 | - |
33 | + | 29 | - bs = bdrv_new(); |
34 | # tests whether $IMGPROTO is one of the supported image protocols for a test | 30 | - |
35 | # | 31 | - /* Read out options */ |
36 | _supported_proto() | 32 | - total_size = DIV_ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), |
33 | - BDRV_SECTOR_SIZE); | ||
34 | - bs->opaque = g_new0(struct IscsiLun, 1); | ||
35 | - iscsilun = bs->opaque; | ||
36 | - | ||
37 | - bs_options = qdict_new(); | ||
38 | - iscsi_parse_filename(filename, bs_options, &local_err); | ||
39 | - if (local_err) { | ||
40 | - error_propagate(errp, local_err); | ||
41 | - ret = -EINVAL; | ||
42 | - } else { | ||
43 | - ret = iscsi_open(bs, bs_options, 0, NULL); | ||
44 | - } | ||
45 | - qobject_unref(bs_options); | ||
46 | - | ||
47 | - if (ret != 0) { | ||
48 | - goto out; | ||
49 | - } | ||
50 | - iscsi_detach_aio_context(bs); | ||
51 | - if (iscsilun->type != TYPE_DISK) { | ||
52 | - ret = -ENODEV; | ||
53 | - goto out; | ||
54 | - } | ||
55 | - if (bs->total_sectors < total_size) { | ||
56 | - ret = -ENOSPC; | ||
57 | - goto out; | ||
58 | - } | ||
59 | - | ||
60 | - ret = 0; | ||
61 | -out: | ||
62 | - if (iscsilun->iscsi != NULL) { | ||
63 | - iscsi_destroy_context(iscsilun->iscsi); | ||
64 | - } | ||
65 | - g_free(bs->opaque); | ||
66 | - bs->opaque = NULL; | ||
67 | - bdrv_unref(bs); | ||
68 | - return ret; | ||
69 | -} | ||
70 | - | ||
71 | static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) | ||
72 | { | ||
73 | IscsiLun *iscsilun = bs->opaque; | ||
74 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = { | ||
75 | .bdrv_parse_filename = iscsi_parse_filename, | ||
76 | .bdrv_file_open = iscsi_open, | ||
77 | .bdrv_close = iscsi_close, | ||
78 | - .bdrv_co_create_opts = iscsi_co_create_opts, | ||
79 | - .create_opts = &iscsi_create_opts, | ||
80 | .bdrv_reopen_prepare = iscsi_reopen_prepare, | ||
81 | .bdrv_reopen_commit = iscsi_reopen_commit, | ||
82 | .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, | ||
83 | @@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = { | ||
84 | .bdrv_parse_filename = iscsi_parse_filename, | ||
85 | .bdrv_file_open = iscsi_open, | ||
86 | .bdrv_close = iscsi_close, | ||
87 | - .bdrv_co_create_opts = iscsi_co_create_opts, | ||
88 | - .create_opts = &iscsi_create_opts, | ||
89 | .bdrv_reopen_prepare = iscsi_reopen_prepare, | ||
90 | .bdrv_reopen_commit = iscsi_reopen_commit, | ||
91 | .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, | ||
37 | -- | 92 | -- |
38 | 2.11.0 | 93 | 2.24.1 |
39 | 94 | ||
40 | 95 | diff view generated by jsdifflib |
1 | From: Nir Soffer <nirsof@gmail.com> | 1 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
---|---|---|---|
2 | 2 | Message-Id: <20200122164532.178040-6-mreitz@redhat.com> | |
3 | Add regression tests checking that qemu-io fails with non-zero exit code | 3 | Reviewed-by: Eric Blake <eblake@redhat.com> |
4 | when reading non-existing file or using the wrong image format. | 4 | Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> |
5 | 5 | [mreitz: Added a note that NBD does not support resizing, which is why | |
6 | Signed-off-by: Nir Soffer <nirsof@gmail.com> | 6 | the second case is expected to fail] |
7 | Message-id: 20170201003120.23378-4-nirsof@gmail.com | ||
8 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
9 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 7 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
10 | --- | 8 | --- |
11 | tests/qemu-iotests/174 | 59 ++++++++++++++++++++++++++++++++++++++++++++++ | 9 | tests/qemu-iotests/259 | 62 ++++++++++++++++++++++++++++++++++++++ |
12 | tests/qemu-iotests/174.out | 7 ++++++ | 10 | tests/qemu-iotests/259.out | 14 +++++++++ |
13 | tests/qemu-iotests/group | 1 + | 11 | tests/qemu-iotests/group | 1 + |
14 | 3 files changed, 67 insertions(+) | 12 | 3 files changed, 77 insertions(+) |
15 | create mode 100755 tests/qemu-iotests/174 | 13 | create mode 100755 tests/qemu-iotests/259 |
16 | create mode 100644 tests/qemu-iotests/174.out | 14 | create mode 100644 tests/qemu-iotests/259.out |
17 | 15 | ||
18 | diff --git a/tests/qemu-iotests/174 b/tests/qemu-iotests/174 | 16 | diff --git a/tests/qemu-iotests/259 b/tests/qemu-iotests/259 |
19 | new file mode 100755 | 17 | new file mode 100755 |
20 | index XXXXXXX..XXXXXXX | 18 | index XXXXXXX..XXXXXXX |
21 | --- /dev/null | 19 | --- /dev/null |
22 | +++ b/tests/qemu-iotests/174 | 20 | +++ b/tests/qemu-iotests/259 |
23 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ |
24 | +#!/bin/bash | 22 | +#!/usr/bin/env bash |
25 | +# | 23 | +# |
26 | +# Test that qemu-io fail with non-zero exit code | 24 | +# Test generic image creation fallback (by using NBD) |
27 | +# | 25 | +# |
28 | +# Copyright (C) 2017 Nir Soffer <nirsof@gmail.com> | 26 | +# Copyright (C) 2019 Red Hat, Inc. |
29 | +# | 27 | +# |
30 | +# This program is free software; you can redistribute it and/or modify | 28 | +# This program is free software; you can redistribute it and/or modify |
31 | +# it under the terms of the GNU General Public License as published by | 29 | +# it under the terms of the GNU General Public License as published by |
32 | +# the Free Software Foundation; either version 2 of the License, or | 30 | +# the Free Software Foundation; either version 2 of the License, or |
33 | +# (at your option) any later version. | 31 | +# (at your option) any later version. |
... | ... | ||
40 | +# You should have received a copy of the GNU General Public License | 38 | +# You should have received a copy of the GNU General Public License |
41 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | 39 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
42 | +# | 40 | +# |
43 | + | 41 | + |
44 | +# creator | 42 | +# creator |
45 | +owner=nirsof@gmail.com | 43 | +owner=mreitz@redhat.com |
46 | + | 44 | + |
47 | +seq=`basename $0` | 45 | +seq=$(basename $0) |
48 | +echo "QA output created by $seq" | 46 | +echo "QA output created by $seq" |
49 | + | 47 | + |
50 | +here=`pwd` | ||
51 | +status=1 # failure is the default! | 48 | +status=1 # failure is the default! |
52 | + | 49 | + |
53 | +_cleanup() | 50 | +_cleanup() |
54 | +{ | 51 | +{ |
55 | + _cleanup_test_img | 52 | + _cleanup_test_img |
56 | +} | 53 | +} |
57 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | 54 | +trap "_cleanup; exit \$status" 0 1 2 3 15 |
58 | + | 55 | + |
59 | +# get standard environment, filters and checks | 56 | +# get standard environment, filters and checks |
60 | +. ./common.rc | 57 | +. ./common.rc |
61 | +. ./common.filter | 58 | +. ./common.filter |
62 | + | 59 | + |
63 | +_unsupported_fmt raw | 60 | +_supported_fmt raw |
61 | +_supported_proto nbd | ||
62 | +_supported_os Linux | ||
64 | + | 63 | + |
65 | + | 64 | + |
66 | +size=256K | 65 | +_make_test_img 64M |
67 | +IMGFMT=raw IMGOPTS= _make_test_img $size | _filter_imgfmt | ||
68 | + | 66 | + |
69 | +echo | 67 | +echo |
70 | +echo "== reading wrong format should fail ==" | 68 | +echo '--- Testing creation ---' |
71 | +$QEMU_IO -f $IMGFMT -c "read 0 $size" "$TEST_IMG" 2>/dev/null | 69 | + |
72 | +test $? -eq 1 || _fail "did not fail" | 70 | +$QEMU_IMG create -f qcow2 "$TEST_IMG" 64M | _filter_img_create |
71 | +$QEMU_IMG info "$TEST_IMG" | _filter_img_info | ||
73 | + | 72 | + |
74 | +echo | 73 | +echo |
75 | +echo "== reading missing file should fail ==" | 74 | +echo '--- Testing creation for which the node would need to grow ---' |
76 | +$QEMU_IO -c "read 0 $size" "$TEST_DIR/missing" 2>/dev/null | 75 | + |
77 | +test $? -eq 1 || _fail "did not fail" | 76 | +# NBD does not support resizing, so this will fail |
77 | +$QEMU_IMG create -f qcow2 -o preallocation=metadata "$TEST_IMG" 64M 2>&1 \ | ||
78 | + | _filter_img_create | ||
78 | + | 79 | + |
79 | +# success, all done | 80 | +# success, all done |
80 | +echo "*** done" | 81 | +echo "*** done" |
81 | +rm -f $seq.full | 82 | +rm -f $seq.full |
82 | +status=0 | 83 | +status=0 |
83 | diff --git a/tests/qemu-iotests/174.out b/tests/qemu-iotests/174.out | 84 | diff --git a/tests/qemu-iotests/259.out b/tests/qemu-iotests/259.out |
84 | new file mode 100644 | 85 | new file mode 100644 |
85 | index XXXXXXX..XXXXXXX | 86 | index XXXXXXX..XXXXXXX |
86 | --- /dev/null | 87 | --- /dev/null |
87 | +++ b/tests/qemu-iotests/174.out | 88 | +++ b/tests/qemu-iotests/259.out |
88 | @@ -XXX,XX +XXX,XX @@ | 89 | @@ -XXX,XX +XXX,XX @@ |
89 | +QA output created by 174 | 90 | +QA output created by 259 |
90 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=262144 | 91 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 |
91 | + | 92 | + |
92 | +== reading wrong format should fail == | 93 | +--- Testing creation --- |
94 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=qcow2 size=67108864 | ||
95 | +image: TEST_DIR/t.IMGFMT | ||
96 | +file format: qcow2 | ||
97 | +virtual size: 64 MiB (67108864 bytes) | ||
98 | +disk size: unavailable | ||
93 | + | 99 | + |
94 | +== reading missing file should fail == | 100 | +--- Testing creation for which the node would need to grow --- |
101 | +qemu-img: TEST_DIR/t.IMGFMT: Could not resize image: Image format driver does not support resize | ||
102 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=qcow2 size=67108864 preallocation=metadata | ||
95 | +*** done | 103 | +*** done |
96 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | 104 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group |
97 | index XXXXXXX..XXXXXXX 100644 | 105 | index XXXXXXX..XXXXXXX 100644 |
98 | --- a/tests/qemu-iotests/group | 106 | --- a/tests/qemu-iotests/group |
99 | +++ b/tests/qemu-iotests/group | 107 | +++ b/tests/qemu-iotests/group |
100 | @@ -XXX,XX +XXX,XX @@ | 108 | @@ -XXX,XX +XXX,XX @@ |
101 | 171 rw auto quick | 109 | 256 rw auto quick |
102 | 172 auto | 110 | 257 rw |
103 | 173 rw auto | 111 | 258 rw quick |
104 | +174 auto | 112 | +259 rw auto quick |
113 | 260 rw quick | ||
114 | 261 rw | ||
115 | 262 rw quick migration | ||
105 | -- | 116 | -- |
106 | 2.11.0 | 117 | 2.24.1 |
107 | 118 | ||
108 | 119 | diff view generated by jsdifflib |
1 | From: Peter Maydell <peter.maydell@linaro.org> | 1 | s.target_has_backing does not reflect whether the target BDS has a |
---|---|---|---|
2 | backing file; it only tells whether we should use a backing file during | ||
3 | conversion (specified by -B). | ||
2 | 4 | ||
3 | Coverity points out that we assign the return value from | 5 | As such, if you use convert -n, the target does not necessarily actually |
4 | bdrv_snapshot_load_tmp() to 'ret' in img_convert(), but then | 6 | have a backing file, and then dereferencing out_bs->backing fails here. |
5 | never use that variable. (We check for failure by looking | ||
6 | at local_err instead.) Drop the unused assignment, bringing | ||
7 | the call into line with the following call to | ||
8 | bdrv_snapshot_laod_tmp_by_id_or_name(). | ||
9 | 7 | ||
10 | (Fixes CID 1247240.) | 8 | When converting to an existing file, we should set |
9 | target_backing_sectors to a negative value, because first, as the | ||
10 | comment explains, this value is only used for optimization, so it is | ||
11 | always fine to do that. | ||
11 | 12 | ||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 13 | Second, we use this value to determine where the target must be |
13 | Message-id: 1486744104-15590-3-git-send-email-peter.maydell@linaro.org | 14 | initialized to zeroes (overlays are initialized to zero after the end of |
14 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 15 | their backing file). When converting to an existing file, we cannot |
16 | assume that to be true. | ||
17 | |||
18 | Cc: qemu-stable@nongnu.org | ||
19 | Fixes: 351c8efff9ad809c822d55620df54d575d536f68 | ||
20 | ("qemu-img: Special post-backing convert handling") | ||
21 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
22 | Message-Id: <20200121155915.98232-2-mreitz@redhat.com> | ||
23 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 24 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
16 | --- | 25 | --- |
17 | qemu-img.c | 8 ++++---- | 26 | qemu-img.c | 2 +- |
18 | 1 file changed, 4 insertions(+), 4 deletions(-) | 27 | 1 file changed, 1 insertion(+), 1 deletion(-) |
19 | 28 | ||
20 | diff --git a/qemu-img.c b/qemu-img.c | 29 | diff --git a/qemu-img.c b/qemu-img.c |
21 | index XXXXXXX..XXXXXXX 100644 | 30 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/qemu-img.c | 31 | --- a/qemu-img.c |
23 | +++ b/qemu-img.c | 32 | +++ b/qemu-img.c |
24 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | 33 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) |
34 | } | ||
25 | } | 35 | } |
26 | 36 | ||
27 | if (sn_opts) { | 37 | - if (s.target_has_backing) { |
28 | - ret = bdrv_snapshot_load_tmp(bs[0], | 38 | + if (s.target_has_backing && s.target_is_new) { |
29 | - qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID), | 39 | /* Errors are treated as "backing length unknown" (which means |
30 | - qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME), | 40 | * s.target_backing_sectors has to be negative, which it will |
31 | - &local_err); | 41 | * be automatically). The backing file length is used only |
32 | + bdrv_snapshot_load_tmp(bs[0], | ||
33 | + qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID), | ||
34 | + qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME), | ||
35 | + &local_err); | ||
36 | } else if (snapshot_name != NULL) { | ||
37 | if (bs_n > 1) { | ||
38 | error_report("No support for concatenating multiple snapshot"); | ||
39 | -- | 42 | -- |
40 | 2.11.0 | 43 | 2.24.1 |
41 | 44 | ||
42 | 45 | diff view generated by jsdifflib |
1 | From: Nir Soffer <nirsof@gmail.com> | 1 | This must not crash. |
---|---|---|---|
2 | 2 | ||
3 | The result of openfile was not checked, leading to failure deep in the | 3 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
4 | actual command with confusing error message, and exiting with exit code 0. | 4 | Message-Id: <20200121155915.98232-3-mreitz@redhat.com> |
5 | 5 | Reviewed-by: John Snow <jsnow@redhat.com> | |
6 | Here is a simple example - trying to read with the wrong format: | ||
7 | |||
8 | $ touch file | ||
9 | $ qemu-io -f qcow2 -c 'read -P 1 0 1024' file; echo $? | ||
10 | can't open device file: Image is not in qcow2 format | ||
11 | no file open, try 'help open' | ||
12 | 0 | ||
13 | |||
14 | With this patch, we fail earlier with exit code 1: | ||
15 | |||
16 | $ ./qemu-io -f qcow2 -c 'read -P 1 0 1024' file; echo $? | ||
17 | can't open device file: Image is not in qcow2 format | ||
18 | 1 | ||
19 | |||
20 | Failing earlier, we don't log this error now: | ||
21 | |||
22 | no file open, try 'help open' | ||
23 | |||
24 | But some tests expected it; the line was removed from the test output. | ||
25 | |||
26 | Signed-off-by: Nir Soffer <nirsof@gmail.com> | ||
27 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
28 | Message-id: 20170201003120.23378-2-nirsof@gmail.com | ||
29 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
30 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 6 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
31 | --- | 7 | --- |
32 | qemu-io.c | 8 ++++++-- | 8 | tests/qemu-iotests/122 | 14 ++++++++++++++ |
33 | tests/qemu-iotests/059.out | 3 --- | 9 | tests/qemu-iotests/122.out | 5 +++++ |
34 | tests/qemu-iotests/070.out | 1 - | 10 | 2 files changed, 19 insertions(+) |
35 | tests/qemu-iotests/075.out | 7 ------- | ||
36 | tests/qemu-iotests/076.out | 3 --- | ||
37 | tests/qemu-iotests/078.out | 6 ------ | ||
38 | tests/qemu-iotests/080.out | 18 ------------------ | ||
39 | tests/qemu-iotests/083.out | 17 ----------------- | ||
40 | tests/qemu-iotests/088.out | 6 ------ | ||
41 | tests/qemu-iotests/092.out | 12 ------------ | ||
42 | tests/qemu-iotests/116.out | 7 ------- | ||
43 | tests/qemu-iotests/131.out | 1 - | ||
44 | tests/qemu-iotests/140.out | 1 - | ||
45 | 13 files changed, 6 insertions(+), 84 deletions(-) | ||
46 | 11 | ||
47 | diff --git a/qemu-io.c b/qemu-io.c | 12 | diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122 |
13 | index XXXXXXX..XXXXXXX 100755 | ||
14 | --- a/tests/qemu-iotests/122 | ||
15 | +++ b/tests/qemu-iotests/122 | ||
16 | @@ -XXX,XX +XXX,XX @@ $QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG".orig | ||
17 | |||
18 | $QEMU_IMG compare "$TEST_IMG" "$TEST_IMG".orig | ||
19 | |||
20 | +echo | ||
21 | +echo '=== -n -B to an image without a backing file ===' | ||
22 | +echo | ||
23 | + | ||
24 | +# Base for the output | ||
25 | +TEST_IMG="$TEST_IMG".base _make_test_img 64M | ||
26 | + | ||
27 | +# Output that does have $TEST_IMG.base set as its (implicit) backing file | ||
28 | +TEST_IMG="$TEST_IMG".orig _make_test_img 64M | ||
29 | + | ||
30 | +# Convert with -n, which should not confuse -B with "target BDS has a | ||
31 | +# backing file" | ||
32 | +$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -n "$TEST_IMG" "$TEST_IMG".orig | ||
33 | + | ||
34 | # success, all done | ||
35 | echo '*** done' | ||
36 | rm -f $seq.full | ||
37 | diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out | ||
48 | index XXXXXXX..XXXXXXX 100644 | 38 | index XXXXXXX..XXXXXXX 100644 |
49 | --- a/qemu-io.c | 39 | --- a/tests/qemu-iotests/122.out |
50 | +++ b/qemu-io.c | 40 | +++ b/tests/qemu-iotests/122.out |
51 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) | 41 | @@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864 |
52 | exit(1); | 42 | wrote 65536/65536 bytes at offset 0 |
53 | } | ||
54 | opts = qemu_opts_to_qdict(qopts, NULL); | ||
55 | - openfile(NULL, flags, writethrough, opts); | ||
56 | + if (openfile(NULL, flags, writethrough, opts)) { | ||
57 | + exit(1); | ||
58 | + } | ||
59 | } else { | ||
60 | if (format) { | ||
61 | opts = qdict_new(); | ||
62 | qdict_put(opts, "driver", qstring_from_str(format)); | ||
63 | } | ||
64 | - openfile(argv[optind], flags, writethrough, opts); | ||
65 | + if (openfile(argv[optind], flags, writethrough, opts)) { | ||
66 | + exit(1); | ||
67 | + } | ||
68 | } | ||
69 | } | ||
70 | command_loop(); | ||
71 | diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/tests/qemu-iotests/059.out | ||
74 | +++ b/tests/qemu-iotests/059.out | ||
75 | @@ -XXX,XX +XXX,XX @@ QA output created by 059 | ||
76 | === Testing invalid granularity === | ||
77 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
78 | can't open device TEST_DIR/t.vmdk: Invalid granularity, image may be corrupt | ||
79 | -no file open, try 'help open' | ||
80 | |||
81 | === Testing too big L2 table size === | ||
82 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
83 | can't open device TEST_DIR/t.vmdk: L2 table size too big | ||
84 | -no file open, try 'help open' | ||
85 | |||
86 | === Testing too big L1 table size === | ||
87 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
88 | can't open device TEST_DIR/t.vmdk: L1 size too big | ||
89 | -no file open, try 'help open' | ||
90 | |||
91 | === Testing monolithicFlat creation and opening === | ||
92 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 subformat=monolithicFlat | ||
93 | diff --git a/tests/qemu-iotests/070.out b/tests/qemu-iotests/070.out | ||
94 | index XXXXXXX..XXXXXXX 100644 | ||
95 | --- a/tests/qemu-iotests/070.out | ||
96 | +++ b/tests/qemu-iotests/070.out | ||
97 | @@ -XXX,XX +XXX,XX @@ QA output created by 070 | ||
98 | can't open device TEST_DIR/iotest-dirtylog-10G-4M.vhdx: VHDX image file 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx' opened read-only, but contains a log that needs to be replayed | ||
99 | To replay the log, run: | ||
100 | qemu-img check -r all 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx' | ||
101 | - no file open, try 'help open' | ||
102 | === Verify open image replays log === | ||
103 | read 18874368/18874368 bytes at offset 0 | ||
104 | 18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
105 | diff --git a/tests/qemu-iotests/075.out b/tests/qemu-iotests/075.out | ||
106 | index XXXXXXX..XXXXXXX 100644 | ||
107 | --- a/tests/qemu-iotests/075.out | ||
108 | +++ b/tests/qemu-iotests/075.out | ||
109 | @@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 1048064 | ||
110 | |||
111 | == block_size must be a multiple of 512 == | ||
112 | can't open device TEST_DIR/simple-pattern.cloop: block_size 513 must be a multiple of 512 | ||
113 | -no file open, try 'help open' | ||
114 | |||
115 | == block_size cannot be zero == | ||
116 | can't open device TEST_DIR/simple-pattern.cloop: block_size cannot be zero | ||
117 | -no file open, try 'help open' | ||
118 | |||
119 | == huge block_size === | ||
120 | can't open device TEST_DIR/simple-pattern.cloop: block_size 4294966784 must be 64 MB or less | ||
121 | -no file open, try 'help open' | ||
122 | |||
123 | == offsets_size overflow === | ||
124 | can't open device TEST_DIR/simple-pattern.cloop: n_blocks 4294967295 must be 536870911 or less | ||
125 | -no file open, try 'help open' | ||
126 | |||
127 | == refuse images that require too many offsets === | ||
128 | can't open device TEST_DIR/simple-pattern.cloop: image requires too many offsets, try increasing block size | ||
129 | -no file open, try 'help open' | ||
130 | |||
131 | == refuse images with non-monotonically increasing offsets == | ||
132 | can't open device TEST_DIR/simple-pattern.cloop: offsets not monotonically increasing at index 1, image file is corrupt | ||
133 | -no file open, try 'help open' | ||
134 | |||
135 | == refuse images with invalid compressed block size == | ||
136 | can't open device TEST_DIR/simple-pattern.cloop: invalid compressed block size at index 1, image file is corrupt | ||
137 | -no file open, try 'help open' | ||
138 | *** done | ||
139 | diff --git a/tests/qemu-iotests/076.out b/tests/qemu-iotests/076.out | ||
140 | index XXXXXXX..XXXXXXX 100644 | ||
141 | --- a/tests/qemu-iotests/076.out | ||
142 | +++ b/tests/qemu-iotests/076.out | ||
143 | @@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0 | ||
144 | |||
145 | == Negative catalog size == | ||
146 | can't open device TEST_DIR/parallels-v1: Catalog too large | ||
147 | -no file open, try 'help open' | ||
148 | |||
149 | == Overflow in catalog allocation == | ||
150 | can't open device TEST_DIR/parallels-v1: Catalog too large | ||
151 | -no file open, try 'help open' | ||
152 | |||
153 | == Zero sectors per track == | ||
154 | can't open device TEST_DIR/parallels-v1: Invalid image: Zero sectors per track | ||
155 | -no file open, try 'help open' | ||
156 | |||
157 | == Read from a valid v2 image == | ||
158 | read 65536/65536 bytes at offset 0 | ||
159 | diff --git a/tests/qemu-iotests/078.out b/tests/qemu-iotests/078.out | ||
160 | index XXXXXXX..XXXXXXX 100644 | ||
161 | --- a/tests/qemu-iotests/078.out | ||
162 | +++ b/tests/qemu-iotests/078.out | ||
163 | @@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0 | ||
164 | |||
165 | == Negative catalog size == | ||
166 | can't open device TEST_DIR/empty.bochs: Catalog size is too large | ||
167 | -no file open, try 'help open' | ||
168 | |||
169 | == Overflow for catalog size * sizeof(uint32_t) == | ||
170 | can't open device TEST_DIR/empty.bochs: Catalog size is too large | ||
171 | -no file open, try 'help open' | ||
172 | |||
173 | == Too small catalog bitmap for image size == | ||
174 | can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size | ||
175 | -no file open, try 'help open' | ||
176 | can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size | ||
177 | -no file open, try 'help open' | ||
178 | |||
179 | == Negative extent size == | ||
180 | can't open device TEST_DIR/empty.bochs: Extent size 2147483648 is too large | ||
181 | -no file open, try 'help open' | ||
182 | |||
183 | == Zero extent size == | ||
184 | can't open device TEST_DIR/empty.bochs: Extent size must be at least 512 | ||
185 | -no file open, try 'help open' | ||
186 | *** done | ||
187 | diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out | ||
188 | index XXXXXXX..XXXXXXX 100644 | ||
189 | --- a/tests/qemu-iotests/080.out | ||
190 | +++ b/tests/qemu-iotests/080.out | ||
191 | @@ -XXX,XX +XXX,XX @@ QA output created by 080 | ||
192 | == Huge header size == | ||
193 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
194 | can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size | ||
195 | -no file open, try 'help open' | ||
196 | can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size | ||
197 | -no file open, try 'help open' | ||
198 | |||
199 | == Huge unknown header extension == | ||
200 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
201 | can't open device TEST_DIR/t.qcow2: Invalid backing file offset | ||
202 | -no file open, try 'help open' | ||
203 | can't open device TEST_DIR/t.qcow2: Header extension too large | ||
204 | -no file open, try 'help open' | ||
205 | can't open device TEST_DIR/t.qcow2: Header extension too large | ||
206 | -no file open, try 'help open' | ||
207 | |||
208 | == Huge refcount table size == | ||
209 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
210 | can't open device TEST_DIR/t.qcow2: Reference count table too large | ||
211 | -no file open, try 'help open' | ||
212 | can't open device TEST_DIR/t.qcow2: Reference count table too large | ||
213 | -no file open, try 'help open' | ||
214 | |||
215 | == Misaligned refcount table == | ||
216 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
217 | can't open device TEST_DIR/t.qcow2: Invalid reference count table offset | ||
218 | -no file open, try 'help open' | ||
219 | |||
220 | == Huge refcount offset == | ||
221 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
222 | can't open device TEST_DIR/t.qcow2: Invalid reference count table offset | ||
223 | -no file open, try 'help open' | ||
224 | |||
225 | == Invalid snapshot table == | ||
226 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
227 | can't open device TEST_DIR/t.qcow2: Too many snapshots | ||
228 | -no file open, try 'help open' | ||
229 | can't open device TEST_DIR/t.qcow2: Too many snapshots | ||
230 | -no file open, try 'help open' | ||
231 | can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset | ||
232 | -no file open, try 'help open' | ||
233 | can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset | ||
234 | -no file open, try 'help open' | ||
235 | |||
236 | == Hitting snapshot table size limit == | ||
237 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
238 | @@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0 | ||
239 | == Invalid L1 table == | ||
240 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
241 | can't open device TEST_DIR/t.qcow2: Active L1 table too large | ||
242 | -no file open, try 'help open' | ||
243 | can't open device TEST_DIR/t.qcow2: Active L1 table too large | ||
244 | -no file open, try 'help open' | ||
245 | can't open device TEST_DIR/t.qcow2: Invalid L1 table offset | ||
246 | -no file open, try 'help open' | ||
247 | can't open device TEST_DIR/t.qcow2: Invalid L1 table offset | ||
248 | -no file open, try 'help open' | ||
249 | |||
250 | == Invalid L1 table (with internal snapshot in the image) == | ||
251 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
252 | @@ -XXX,XX +XXX,XX @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': L1 table is too small | ||
253 | == Invalid backing file size == | ||
254 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
255 | can't open device TEST_DIR/t.qcow2: Backing file name too long | ||
256 | -no file open, try 'help open' | ||
257 | |||
258 | == Invalid L2 entry (huge physical offset) == | ||
259 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
260 | diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out | ||
261 | index XXXXXXX..XXXXXXX 100644 | ||
262 | --- a/tests/qemu-iotests/083.out | ||
263 | +++ b/tests/qemu-iotests/083.out | ||
264 | @@ -XXX,XX +XXX,XX @@ QA output created by 083 | ||
265 | === Check disconnect before neg1 === | ||
266 | |||
267 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
268 | -no file open, try 'help open' | ||
269 | |||
270 | === Check disconnect after neg1 === | ||
271 | |||
272 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
273 | -no file open, try 'help open' | ||
274 | |||
275 | === Check disconnect 8 neg1 === | ||
276 | |||
277 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
278 | -no file open, try 'help open' | ||
279 | |||
280 | === Check disconnect 16 neg1 === | ||
281 | |||
282 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
283 | -no file open, try 'help open' | ||
284 | |||
285 | === Check disconnect before export === | ||
286 | |||
287 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
288 | -no file open, try 'help open' | ||
289 | |||
290 | === Check disconnect after export === | ||
291 | |||
292 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
293 | -no file open, try 'help open' | ||
294 | |||
295 | === Check disconnect 4 export === | ||
296 | |||
297 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
298 | -no file open, try 'help open' | ||
299 | |||
300 | === Check disconnect 12 export === | ||
301 | |||
302 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
303 | -no file open, try 'help open' | ||
304 | |||
305 | === Check disconnect 16 export === | ||
306 | |||
307 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
308 | -no file open, try 'help open' | ||
309 | |||
310 | === Check disconnect before neg2 === | ||
311 | |||
312 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
313 | -no file open, try 'help open' | ||
314 | |||
315 | === Check disconnect after neg2 === | ||
316 | |||
317 | @@ -XXX,XX +XXX,XX @@ read failed: Input/output error | ||
318 | === Check disconnect 8 neg2 === | ||
319 | |||
320 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
321 | -no file open, try 'help open' | ||
322 | |||
323 | === Check disconnect 10 neg2 === | ||
324 | |||
325 | can't open device nbd:127.0.0.1:PORT:exportname=foo | ||
326 | -no file open, try 'help open' | ||
327 | |||
328 | === Check disconnect before request === | ||
329 | |||
330 | @@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0 | ||
331 | === Check disconnect before neg-classic === | ||
332 | |||
333 | can't open device nbd:127.0.0.1:PORT | ||
334 | -no file open, try 'help open' | ||
335 | |||
336 | === Check disconnect 8 neg-classic === | ||
337 | |||
338 | can't open device nbd:127.0.0.1:PORT | ||
339 | -no file open, try 'help open' | ||
340 | |||
341 | === Check disconnect 16 neg-classic === | ||
342 | |||
343 | can't open device nbd:127.0.0.1:PORT | ||
344 | -no file open, try 'help open' | ||
345 | |||
346 | === Check disconnect 24 neg-classic === | ||
347 | |||
348 | can't open device nbd:127.0.0.1:PORT | ||
349 | -no file open, try 'help open' | ||
350 | |||
351 | === Check disconnect 28 neg-classic === | ||
352 | |||
353 | can't open device nbd:127.0.0.1:PORT | ||
354 | -no file open, try 'help open' | ||
355 | |||
356 | === Check disconnect after neg-classic === | ||
357 | |||
358 | diff --git a/tests/qemu-iotests/088.out b/tests/qemu-iotests/088.out | ||
359 | index XXXXXXX..XXXXXXX 100644 | ||
360 | --- a/tests/qemu-iotests/088.out | ||
361 | +++ b/tests/qemu-iotests/088.out | ||
362 | @@ -XXX,XX +XXX,XX @@ QA output created by 088 | ||
363 | == Invalid block size == | ||
364 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
365 | can't open device TEST_DIR/t.vpc: Invalid block size 0 | ||
366 | -no file open, try 'help open' | ||
367 | can't open device TEST_DIR/t.vpc: Invalid block size 0 | ||
368 | -no file open, try 'help open' | ||
369 | can't open device TEST_DIR/t.vpc: Invalid block size 128 | ||
370 | -no file open, try 'help open' | ||
371 | can't open device TEST_DIR/t.vpc: Invalid block size 128 | ||
372 | -no file open, try 'help open' | ||
373 | can't open device TEST_DIR/t.vpc: Invalid block size 305419896 | ||
374 | -no file open, try 'help open' | ||
375 | can't open device TEST_DIR/t.vpc: Invalid block size 305419896 | ||
376 | -no file open, try 'help open' | ||
377 | *** done | ||
378 | diff --git a/tests/qemu-iotests/092.out b/tests/qemu-iotests/092.out | ||
379 | index XXXXXXX..XXXXXXX 100644 | ||
380 | --- a/tests/qemu-iotests/092.out | ||
381 | +++ b/tests/qemu-iotests/092.out | ||
382 | @@ -XXX,XX +XXX,XX @@ QA output created by 092 | ||
383 | == Invalid cluster size == | ||
384 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
385 | can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k | ||
386 | -no file open, try 'help open' | ||
387 | can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k | ||
388 | -no file open, try 'help open' | ||
389 | can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k | ||
390 | -no file open, try 'help open' | ||
391 | can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k | ||
392 | -no file open, try 'help open' | ||
393 | |||
394 | == Invalid L2 table size == | ||
395 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
396 | can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k | ||
397 | -no file open, try 'help open' | ||
398 | can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k | ||
399 | -no file open, try 'help open' | ||
400 | can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k | ||
401 | -no file open, try 'help open' | ||
402 | can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k | ||
403 | -no file open, try 'help open' | ||
404 | |||
405 | == Invalid size == | ||
406 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
407 | can't open device TEST_DIR/t.qcow: Image too large | ||
408 | -no file open, try 'help open' | ||
409 | can't open device TEST_DIR/t.qcow: Image too large | ||
410 | -no file open, try 'help open' | ||
411 | |||
412 | == Invalid backing file length == | ||
413 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
414 | can't open device TEST_DIR/t.qcow: Backing file name too long | ||
415 | -no file open, try 'help open' | ||
416 | can't open device TEST_DIR/t.qcow: Backing file name too long | ||
417 | -no file open, try 'help open' | ||
418 | *** done | ||
419 | diff --git a/tests/qemu-iotests/116.out b/tests/qemu-iotests/116.out | ||
420 | index XXXXXXX..XXXXXXX 100644 | ||
421 | --- a/tests/qemu-iotests/116.out | ||
422 | +++ b/tests/qemu-iotests/116.out | ||
423 | @@ -XXX,XX +XXX,XX @@ QA output created by 116 | ||
424 | == truncated header cluster == | ||
425 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
426 | can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument | ||
427 | -no file open, try 'help open' | ||
428 | |||
429 | == invalid header magic == | ||
430 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
431 | can't open device TEST_DIR/t.qed: Image not in QED format | ||
432 | -no file open, try 'help open' | ||
433 | |||
434 | == invalid cluster size == | ||
435 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
436 | can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument | ||
437 | -no file open, try 'help open' | ||
438 | |||
439 | == invalid table size == | ||
440 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
441 | can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument | ||
442 | -no file open, try 'help open' | ||
443 | |||
444 | == invalid header size == | ||
445 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
446 | can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument | ||
447 | -no file open, try 'help open' | ||
448 | |||
449 | == invalid L1 table offset == | ||
450 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
451 | can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument | ||
452 | -no file open, try 'help open' | ||
453 | |||
454 | == invalid image size == | ||
455 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
456 | can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument | ||
457 | -no file open, try 'help open' | ||
458 | *** done | ||
459 | diff --git a/tests/qemu-iotests/131.out b/tests/qemu-iotests/131.out | ||
460 | index XXXXXXX..XXXXXXX 100644 | ||
461 | --- a/tests/qemu-iotests/131.out | ||
462 | +++ b/tests/qemu-iotests/131.out | ||
463 | @@ -XXX,XX +XXX,XX @@ read 32768/32768 bytes at offset 0 | ||
464 | 32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
465 | == Corrupt image == | ||
466 | can't open device TEST_DIR/t.parallels: parallels: Image was not closed correctly; cannot be opened read/write | ||
467 | -no file open, try 'help open' | ||
468 | ERROR image was not closed correctly | ||
469 | |||
470 | 1 errors were found on the image. | ||
471 | diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out | ||
472 | index XXXXXXX..XXXXXXX 100644 | ||
473 | --- a/tests/qemu-iotests/140.out | ||
474 | +++ b/tests/qemu-iotests/140.out | ||
475 | @@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0 | ||
476 | 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | 43 | 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) |
477 | {"return": {}} | 44 | Images are identical. |
478 | can't open device nbd+unix:///drv?socket=TEST_DIR/nbd: No export with name 'drv' available | 45 | + |
479 | -no file open, try 'help open' | 46 | +=== -n -B to an image without a backing file === |
480 | {"return": {}} | 47 | + |
481 | {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} | 48 | +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 |
49 | +Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864 | ||
482 | *** done | 50 | *** done |
483 | -- | 51 | -- |
484 | 2.11.0 | 52 | 2.24.1 |
485 | 53 | ||
486 | 54 | diff view generated by jsdifflib |
1 | From: Fam Zheng <famz@redhat.com> | 1 | When printing the snapshot list (e.g. with qemu-img snapshot -l), the VM |
---|---|---|---|
2 | size field is only seven characters wide. As of de38b5005e9, this is | ||
3 | not necessarily sufficient: We generally print three digits, and this | ||
4 | may require a decimal point. Also, the unit field grew from something | ||
5 | as plain as "M" to " MiB". This means that number and unit may take up | ||
6 | eight characters in total; but we also want spaces in front. | ||
2 | 7 | ||
3 | @bs doesn't always have a device name, such as when it comes from | 8 | Considering previously the maximum width was four characters and the |
4 | "qemu-img info". Report file name instead. | 9 | field width was chosen to be three characters wider, let us adjust the |
10 | field width to be eleven now. | ||
5 | 11 | ||
6 | Signed-off-by: Fam Zheng <famz@redhat.com> | 12 | Fixes: de38b5005e946aa3714963ea4c501e279e7d3666 |
7 | Message-id: 20170119130759.28319-2-famz@redhat.com | 13 | Buglink: https://bugs.launchpad.net/qemu/+bug/1859989 |
14 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
15 | Message-Id: <20200117105859.241818-2-mreitz@redhat.com> | ||
8 | Reviewed-by: Eric Blake <eblake@redhat.com> | 16 | Reviewed-by: Eric Blake <eblake@redhat.com> |
9 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 17 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
10 | --- | 18 | --- |
11 | block/qapi.c | 4 ++-- | 19 | block/qapi.c | 4 ++-- |
12 | 1 file changed, 2 insertions(+), 2 deletions(-) | 20 | 1 file changed, 2 insertions(+), 2 deletions(-) |
13 | 21 | ||
14 | diff --git a/block/qapi.c b/block/qapi.c | 22 | diff --git a/block/qapi.c b/block/qapi.c |
15 | index XXXXXXX..XXXXXXX 100644 | 23 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/block/qapi.c | 24 | --- a/block/qapi.c |
17 | +++ b/block/qapi.c | 25 | +++ b/block/qapi.c |
18 | @@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs, | 26 | @@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) |
19 | 27 | char *sizing = NULL; | |
20 | size = bdrv_getlength(bs); | 28 | |
21 | if (size < 0) { | 29 | if (!sn) { |
22 | - error_setg_errno(errp, -size, "Can't get size of device '%s'", | 30 | - qemu_printf("%-10s%-20s%7s%20s%15s", |
23 | - bdrv_get_device_name(bs)); | 31 | + qemu_printf("%-10s%-20s%11s%20s%15s", |
24 | + error_setg_errno(errp, -size, "Can't get image size '%s'", | 32 | "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); |
25 | + bs->exact_filename); | 33 | } else { |
26 | goto out; | 34 | ti = sn->date_sec; |
27 | } | 35 | @@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) |
28 | 36 | (int)(secs % 60), | |
37 | (int)((sn->vm_clock_nsec / 1000000) % 1000)); | ||
38 | sizing = size_to_str(sn->vm_state_size); | ||
39 | - qemu_printf("%-10s%-20s%7s%20s%15s", | ||
40 | + qemu_printf("%-10s%-20s%11s%20s%15s", | ||
41 | sn->id_str, sn->name, | ||
42 | sizing, | ||
43 | date_buf, | ||
29 | -- | 44 | -- |
30 | 2.11.0 | 45 | 2.24.1 |
31 | 46 | ||
32 | 47 | diff view generated by jsdifflib |
1 | From: Peter Lieven <pl@kamp.de> | 1 | Add a test that all fields in "qemu-img snapshot -l"s output are |
---|---|---|---|
2 | separated by spaces. | ||
2 | 3 | ||
3 | parse_uint_full wants to put the parsed value into the | 4 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
4 | variable passed via its second argument which is NULL. | 5 | Message-Id: <20200117105859.241818-3-mreitz@redhat.com> |
5 | |||
6 | Fixes: 94d6a7a76e9df9919629428f6c598e2b97d9426c | ||
7 | Cc: qemu-stable@nongnu.org | ||
8 | Signed-off-by: Peter Lieven <pl@kamp.de> | ||
9 | Reviewed-by: Eric Blake <eblake@redhat.com> | 6 | Reviewed-by: Eric Blake <eblake@redhat.com> |
10 | Message-id: 1485942829-10756-2-git-send-email-pl@kamp.de | 7 | [mreitz: Renamed test from 284 to 286] |
11 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 8 | Signed-off-by: Max Reitz <mreitz@redhat.com> |
12 | --- | 9 | --- |
13 | block/nfs.c | 3 ++- | 10 | tests/qemu-iotests/286 | 76 ++++++++++++++++++++++++++++++++++++++ |
14 | 1 file changed, 2 insertions(+), 1 deletion(-) | 11 | tests/qemu-iotests/286.out | 8 ++++ |
12 | tests/qemu-iotests/group | 1 + | ||
13 | 3 files changed, 85 insertions(+) | ||
14 | create mode 100755 tests/qemu-iotests/286 | ||
15 | create mode 100644 tests/qemu-iotests/286.out | ||
15 | 16 | ||
16 | diff --git a/block/nfs.c b/block/nfs.c | 17 | diff --git a/tests/qemu-iotests/286 b/tests/qemu-iotests/286 |
18 | new file mode 100755 | ||
19 | index XXXXXXX..XXXXXXX | ||
20 | --- /dev/null | ||
21 | +++ b/tests/qemu-iotests/286 | ||
22 | @@ -XXX,XX +XXX,XX @@ | ||
23 | +#!/usr/bin/env bash | ||
24 | +# | ||
25 | +# Test qemu-img snapshot -l | ||
26 | +# | ||
27 | +# Copyright (C) 2019 Red Hat, Inc. | ||
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 | +seq=$(basename "$0") | ||
44 | +echo "QA output created by $seq" | ||
45 | + | ||
46 | +status=1 # failure is the default! | ||
47 | + | ||
48 | +_cleanup() | ||
49 | +{ | ||
50 | + _cleanup_test_img | ||
51 | +} | ||
52 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
53 | + | ||
54 | +# get standard environment, filters and checks | ||
55 | +. ./common.rc | ||
56 | +. ./common.filter | ||
57 | +. ./common.qemu | ||
58 | + | ||
59 | +_supported_fmt qcow2 | ||
60 | +_supported_proto file | ||
61 | +# Internal snapshots are (currently) impossible with refcount_bits=1, | ||
62 | +# and generally impossible with external data files | ||
63 | +_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file | ||
64 | + | ||
65 | +_make_test_img 64M | ||
66 | + | ||
67 | +# Should be so long as to take up the whole field width | ||
68 | +sn_name=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz | ||
69 | + | ||
70 | +# More memory will give us a larger VM state, i.e. one above 1 MB. | ||
71 | +# This way, we get a number with a decimal point. | ||
72 | +qemu_comm_method=monitor _launch_qemu -m 512 "$TEST_IMG" | ||
73 | + | ||
74 | +_send_qemu_cmd $QEMU_HANDLE "savevm $sn_name" '(qemu)' | ||
75 | +_send_qemu_cmd $QEMU_HANDLE 'quit' '(qemu)' | ||
76 | +wait=yes _cleanup_qemu | ||
77 | + | ||
78 | +# Check that all fields are separated by spaces. | ||
79 | +# We first collapse all space sequences into one space each; | ||
80 | +# then we turn every space-separated field into a '.'; | ||
81 | +# and finally, we name the '.'s so the output is not just a confusing | ||
82 | +# sequence of dots. | ||
83 | + | ||
84 | +echo 'Output structure:' | ||
85 | +$QEMU_IMG snapshot -l "$TEST_IMG" | tail -n 1 | tr -s ' ' \ | ||
86 | + | sed -e 's/\S\+/./g' \ | ||
87 | + | sed -e 's/\./(snapshot ID)/' \ | ||
88 | + -e 's/\./(snapshot name)/' \ | ||
89 | + -e 's/\./(VM state size value)/' \ | ||
90 | + -e 's/\./(VM state size unit)/' \ | ||
91 | + -e 's/\./(snapshot date)/' \ | ||
92 | + -e 's/\./(snapshot time)/' \ | ||
93 | + -e 's/\./(VM clock)/' | ||
94 | + | ||
95 | +# success, all done | ||
96 | +echo "*** done" | ||
97 | +rm -f $seq.full | ||
98 | +status=0 | ||
99 | diff --git a/tests/qemu-iotests/286.out b/tests/qemu-iotests/286.out | ||
100 | new file mode 100644 | ||
101 | index XXXXXXX..XXXXXXX | ||
102 | --- /dev/null | ||
103 | +++ b/tests/qemu-iotests/286.out | ||
104 | @@ -XXX,XX +XXX,XX @@ | ||
105 | +QA output created by 286 | ||
106 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
107 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
108 | +(qemu) savevm abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz | ||
109 | +(qemu) quit | ||
110 | +Output structure: | ||
111 | +(snapshot ID) (snapshot name) (VM state size value) (VM state size unit) (snapshot date) (snapshot time) (VM clock) | ||
112 | +*** done | ||
113 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
17 | index XXXXXXX..XXXXXXX 100644 | 114 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/block/nfs.c | 115 | --- a/tests/qemu-iotests/group |
19 | +++ b/block/nfs.c | 116 | +++ b/tests/qemu-iotests/group |
20 | @@ -XXX,XX +XXX,XX @@ static int nfs_parse_uri(const char *filename, QDict *options, Error **errp) | 117 | @@ -XXX,XX +XXX,XX @@ |
21 | qdict_put(options, "path", qstring_from_str(uri->path)); | 118 | 281 rw quick |
22 | 119 | 283 auto quick | |
23 | for (i = 0; i < qp->n; i++) { | 120 | 284 rw |
24 | + unsigned long long val; | 121 | +286 rw quick |
25 | if (!qp->p[i].value) { | ||
26 | error_setg(errp, "Value for NFS parameter expected: %s", | ||
27 | qp->p[i].name); | ||
28 | goto out; | ||
29 | } | ||
30 | - if (parse_uint_full(qp->p[i].value, NULL, 0)) { | ||
31 | + if (parse_uint_full(qp->p[i].value, &val, 0)) { | ||
32 | error_setg(errp, "Illegal value for NFS parameter: %s", | ||
33 | qp->p[i].name); | ||
34 | goto out; | ||
35 | -- | 122 | -- |
36 | 2.11.0 | 123 | 2.24.1 |
37 | 124 | ||
38 | 125 | diff view generated by jsdifflib |