1 | The following changes since commit 672f9d0df10a68a5c5f2b32cbc8284abf9f5ee18: | 1 | The following changes since commit a3607def89f9cd68c1b994e1030527df33aa91d0: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2020-02-18 14:23:43 +0000) | 3 | Update version for v6.2.0-rc4 release (2021-12-07 17:51:38 -0800) |
4 | 4 | ||
5 | are available in the Git repository at: | 5 | are available in the Git repository at: |
6 | 6 | ||
7 | https://github.com/XanClic/qemu.git tags/pull-block-2020-02-20 | 7 | https://gitlab.com/stefanha/qemu.git tags/block-pull-request |
8 | 8 | ||
9 | for you to fetch changes up to dff8d44c96f128480430b0c59ed8760917dbd427: | 9 | for you to fetch changes up to cf4fbc3030c974fff726756a7ceef8386cdf500b: |
10 | 10 | ||
11 | iotests: Test snapshot -l field separation (2020-02-20 16:43:42 +0100) | 11 | block/nvme: fix infinite loop in nvme_free_req_queue_cb() (2021-12-09 09:19:49 +0000) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block patches: | 14 | Pull request |
15 | - qemu-img convert: New --target-is-zero parameter | 15 | |
16 | - qcow2: Specify non-default compression type flag | 16 | An infinite loop fix for the userspace NVMe driver. |
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 | ||
21 | 17 | ||
22 | ---------------------------------------------------------------- | 18 | ---------------------------------------------------------------- |
23 | Daniel P. Berrangé (1): | ||
24 | block: always fill entire LUKS header space with zeros | ||
25 | 19 | ||
26 | David Edmondson (1): | 20 | Stefan Hajnoczi (1): |
27 | qemu-img: Add --target-is-zero to convert | 21 | block/nvme: fix infinite loop in nvme_free_req_queue_cb() |
28 | 22 | ||
29 | Max Reitz (11): | 23 | block/nvme.c | 5 +++-- |
30 | iotests/147: Fix drive parameters | 24 | 1 file changed, 3 insertions(+), 2 deletions(-) |
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 | ||
41 | |||
42 | Peter Krempa (1): | ||
43 | qapi: Allow getting flat output from 'query-named-block-nodes' | ||
44 | |||
45 | Thomas Huth (1): | ||
46 | iotests: Remove the superfluous 2nd check for the availability of | ||
47 | quorum | ||
48 | |||
49 | Vladimir Sementsov-Ogievskiy (3): | ||
50 | docs: improve qcow2 spec about extending image header | ||
51 | docs: qcow2: introduce compression type feature | ||
52 | block/backup-top: fix flags handling | ||
53 | |||
54 | block.c | 164 +++++++++++++++++++++++++++++++++---- | ||
55 | block/backup-top.c | 31 ++++--- | ||
56 | block/file-posix.c | 67 --------------- | ||
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 | ||
89 | 25 | ||
90 | -- | 26 | -- |
91 | 2.24.1 | 27 | 2.33.1 |
92 | 28 | ||
93 | 29 | ||
30 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
2 | 1 | ||
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 |
Deleted patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
2 | 1 | ||
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 |
Deleted patch | |||
---|---|---|---|
1 | From: Thomas Huth <thuth@redhat.com> | ||
2 | 1 | ||
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 |
Deleted patch | |||
---|---|---|---|
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. | ||
3 | 1 | ||
4 | Fixes: 8dff69b9415b4287e900358744b732195e1ab2e2 | ||
5 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
6 | Message-Id: <20200206130812.612960-1-mreitz@redhat.com> | ||
7 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
8 | Tested-by: Eric Blake <eblake@redhat.com> | ||
9 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
10 | --- | ||
11 | tests/qemu-iotests/147 | 2 +- | ||
12 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147 | ||
15 | index XXXXXXX..XXXXXXX 100755 | ||
16 | --- a/tests/qemu-iotests/147 | ||
17 | +++ b/tests/qemu-iotests/147 | ||
18 | @@ -XXX,XX +XXX,XX @@ class BuiltinNBD(NBDBlockdevAddBase): | ||
19 | self.server.add_drive_raw('if=none,id=nbd-export,' + | ||
20 | 'file=%s,' % test_img + | ||
21 | 'format=%s,' % imgfmt + | ||
22 | - 'cache=%s' % cachemode + | ||
23 | + 'cache=%s,' % cachemode + | ||
24 | 'aio=%s' % aiomode) | ||
25 | self.server.launch() | ||
26 | |||
27 | -- | ||
28 | 2.24.1 | ||
29 | |||
30 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Peter Krempa <pkrempa@redhat.com> | ||
2 | 1 | ||
3 | When a management application manages node names there's no reason to | ||
4 | recurse into backing images in the output of query-named-block-nodes. | ||
5 | |||
6 | Add a parameter to the command which will return just the top level | ||
7 | structs. | ||
8 | |||
9 | Signed-off-by: Peter Krempa <pkrempa@redhat.com> | ||
10 | Message-Id: <4470f8c779abc404dcf65e375db195cd91a80651.1579509782.git.pkrempa@redhat.com> | ||
11 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
12 | [mreitz: Fixed coding style] | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | block.c | 5 +++-- | ||
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(-) | ||
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; | ||
46 | diff --git a/block/qapi.c b/block/qapi.c | ||
47 | index XXXXXXX..XXXXXXX 100644 | ||
48 | --- a/block/qapi.c | ||
49 | +++ b/block/qapi.c | ||
50 | @@ -XXX,XX +XXX,XX @@ | ||
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); | ||
88 | } | ||
89 | |||
90 | -BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp) | ||
91 | +BlockDeviceInfoList *qmp_query_named_block_nodes(bool has_flat, | ||
92 | + bool flat, | ||
93 | + Error **errp) | ||
94 | { | ||
95 | - return bdrv_named_nodes_list(errp); | ||
96 | + bool return_flat = has_flat && flat; | ||
97 | + | ||
98 | + return bdrv_named_nodes_list(return_flat, errp); | ||
99 | } | ||
100 | |||
101 | XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp) | ||
102 | diff --git a/include/block/block.h b/include/block/block.h | ||
103 | index XXXXXXX..XXXXXXX 100644 | ||
104 | --- a/include/block/block.h | ||
105 | +++ b/include/block/block.h | ||
106 | @@ -XXX,XX +XXX,XX @@ void bdrv_lock_medium(BlockDriverState *bs, bool locked); | ||
107 | void bdrv_eject(BlockDriverState *bs, bool eject_flag); | ||
108 | const char *bdrv_get_format_name(BlockDriverState *bs); | ||
109 | BlockDriverState *bdrv_find_node(const char *node_name); | ||
110 | -BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp); | ||
111 | +BlockDeviceInfoList *bdrv_named_nodes_list(bool flat, Error **errp); | ||
112 | XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp); | ||
113 | BlockDriverState *bdrv_lookup_bs(const char *device, | ||
114 | const char *node_name, | ||
115 | diff --git a/include/block/qapi.h b/include/block/qapi.h | ||
116 | index XXXXXXX..XXXXXXX 100644 | ||
117 | --- a/include/block/qapi.h | ||
118 | +++ b/include/block/qapi.h | ||
119 | @@ -XXX,XX +XXX,XX @@ | ||
120 | #include "block/snapshot.h" | ||
121 | |||
122 | BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, | ||
123 | - BlockDriverState *bs, Error **errp); | ||
124 | + BlockDriverState *bs, | ||
125 | + bool flat, | ||
126 | + Error **errp); | ||
127 | int bdrv_query_snapshot_info_list(BlockDriverState *bs, | ||
128 | SnapshotInfoList **p_list, | ||
129 | Error **errp); | ||
130 | diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c | ||
131 | index XXXXXXX..XXXXXXX 100644 | ||
132 | --- a/monitor/hmp-cmds.c | ||
133 | +++ b/monitor/hmp-cmds.c | ||
134 | @@ -XXX,XX +XXX,XX @@ void hmp_info_block(Monitor *mon, const QDict *qdict) | ||
135 | } | ||
136 | |||
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: | ||
168 | -- | ||
169 | 2.24.1 | ||
170 | |||
171 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: David Edmondson <david.edmondson@oracle.com> | ||
2 | 1 | ||
3 | In many cases the target of a convert operation is a newly provisioned | ||
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. | ||
7 | |||
8 | Add a new option, --target-is-zero, allowing the user to indicate that | ||
9 | an existing target device will return zeros for all reads. | ||
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> | ||
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
16 | --- | ||
17 | docs/interop/qemu-img.rst | 9 ++++++++- | ||
18 | qemu-img-cmds.hx | 4 ++-- | ||
19 | qemu-img.c | 26 +++++++++++++++++++++++--- | ||
20 | 3 files changed, 33 insertions(+), 6 deletions(-) | ||
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, | ||
65 | diff --git a/qemu-img.c b/qemu-img.c | ||
66 | index XXXXXXX..XXXXXXX 100644 | ||
67 | --- a/qemu-img.c | ||
68 | +++ b/qemu-img.c | ||
69 | @@ -XXX,XX +XXX,XX @@ enum { | ||
70 | OPTION_PREALLOCATION = 265, | ||
71 | OPTION_SHRINK = 266, | ||
72 | OPTION_SALVAGE = 267, | ||
73 | + OPTION_TARGET_IS_ZERO = 268, | ||
74 | }; | ||
75 | |||
76 | typedef enum OutputFormat { | ||
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; | ||
110 | } | ||
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"); | ||
138 | -- | ||
139 | 2.24.1 | ||
140 | |||
141 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Daniel P. Berrangé <berrange@redhat.com> | ||
2 | 1 | ||
3 | When initializing the LUKS header the size with default encryption | ||
4 | parameters will currently be 2068480 bytes. This is rounded up to | ||
5 | a multiple of the cluster size, 2081792, with 64k sectors. If the | ||
6 | end of the header is not the same as the end of the cluster we fill | ||
7 | the extra space with zeros. This was forgetting that not even the | ||
8 | space allocated for the header will be fully initialized, as we | ||
9 | only write key material for the first key slot. The space left | ||
10 | for the other 7 slots is never written to. | ||
11 | |||
12 | An optimization to the ref count checking code: | ||
13 | |||
14 | commit a5fff8d4b4d928311a5005efa12d0991fe3b66f9 (refs/bisect/bad) | ||
15 | Author: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
16 | Date: Wed Feb 27 16:14:30 2019 +0300 | ||
17 | |||
18 | qcow2-refcount: avoid eating RAM | ||
19 | |||
20 | made the assumption that every cluster which was allocated would | ||
21 | have at least some data written to it. This was violated by way | ||
22 | the LUKS header is only partially written, with much space simply | ||
23 | reserved for future use. | ||
24 | |||
25 | Depending on the cluster size this problem was masked by the | ||
26 | logic which wrote zeros between the end of the LUKS header and | ||
27 | the end of the cluster. | ||
28 | |||
29 | $ qemu-img create --object secret,id=cluster_encrypt0,data=123456 \ | ||
30 | -f qcow2 -o cluster_size=2k,encrypt.iter-time=1,\ | ||
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> | ||
69 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
70 | --- | ||
71 | block/qcow2.c | 11 +++-- | ||
72 | tests/qemu-iotests/284 | 97 ++++++++++++++++++++++++++++++++++++++ | ||
73 | tests/qemu-iotests/284.out | 62 ++++++++++++++++++++++++ | ||
74 | tests/qemu-iotests/group | 1 + | ||
75 | 4 files changed, 167 insertions(+), 4 deletions(-) | ||
76 | create mode 100755 tests/qemu-iotests/284 | ||
77 | create mode 100644 tests/qemu-iotests/284.out | ||
78 | |||
79 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
80 | index XXXXXXX..XXXXXXX 100644 | ||
81 | --- a/block/qcow2.c | ||
82 | +++ b/block/qcow2.c | ||
83 | @@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen, | ||
84 | s->crypto_header.length = headerlen; | ||
85 | s->crypto_header.offset = ret; | ||
86 | |||
87 | - /* Zero fill remaining space in cluster so it has predictable | ||
88 | - * content in case of future spec changes */ | ||
89 | + /* | ||
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 | ||
284 | -- | ||
285 | 2.24.1 | ||
286 | |||
287 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
2 | 1 | ||
3 | backup-top "supports" write-unchanged, by skipping CBW operation in | ||
4 | backup_top_co_pwritev. But it forgets to do the same in | ||
5 | backup_top_co_pwrite_zeroes, as well as declare support for | ||
6 | BDRV_REQ_WRITE_UNCHANGED. | ||
7 | |||
8 | Fix this, and, while being here, declare also support for flags | ||
9 | supported by source child. | ||
10 | |||
11 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
12 | Message-Id: <20200207161231.32707-1-vsementsov@virtuozzo.com> | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | block/backup-top.c | 31 ++++++++++++++++++++----------- | ||
16 | 1 file changed, 20 insertions(+), 11 deletions(-) | ||
17 | |||
18 | diff --git a/block/backup-top.c b/block/backup-top.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/backup-top.c | ||
21 | +++ b/block/backup-top.c | ||
22 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_co_preadv( | ||
23 | } | ||
24 | |||
25 | static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset, | ||
26 | - uint64_t bytes) | ||
27 | + uint64_t bytes, BdrvRequestFlags flags) | ||
28 | { | ||
29 | BDRVBackupTopState *s = bs->opaque; | ||
30 | - uint64_t end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size); | ||
31 | - uint64_t off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size); | ||
32 | + uint64_t off, end; | ||
33 | + | ||
34 | + if (flags & BDRV_REQ_WRITE_UNCHANGED) { | ||
35 | + return 0; | ||
36 | + } | ||
37 | + | ||
38 | + off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size); | ||
39 | + end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size); | ||
40 | |||
41 | return block_copy(s->bcs, off, end - off, NULL); | ||
42 | } | ||
43 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset, | ||
44 | static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs, | ||
45 | int64_t offset, int bytes) | ||
46 | { | ||
47 | - int ret = backup_top_cbw(bs, offset, bytes); | ||
48 | + int ret = backup_top_cbw(bs, offset, bytes, 0); | ||
49 | if (ret < 0) { | ||
50 | return ret; | ||
51 | } | ||
52 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs, | ||
53 | static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs, | ||
54 | int64_t offset, int bytes, BdrvRequestFlags flags) | ||
55 | { | ||
56 | - int ret = backup_top_cbw(bs, offset, bytes); | ||
57 | + int ret = backup_top_cbw(bs, offset, bytes, flags); | ||
58 | if (ret < 0) { | ||
59 | return ret; | ||
60 | } | ||
61 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs, | ||
62 | uint64_t bytes, | ||
63 | QEMUIOVector *qiov, int flags) | ||
64 | { | ||
65 | - if (!(flags & BDRV_REQ_WRITE_UNCHANGED)) { | ||
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; | ||
73 | } | ||
74 | |||
75 | return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags); | ||
76 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | ||
77 | return NULL; | ||
78 | } | ||
79 | |||
80 | - top->total_sectors = source->total_sectors; | ||
81 | state = top->opaque; | ||
82 | + top->total_sectors = source->total_sectors; | ||
83 | + top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
84 | + (BDRV_REQ_FUA & source->supported_write_flags); | ||
85 | + top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
86 | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & | ||
87 | + source->supported_zero_flags); | ||
88 | |||
89 | bdrv_ref(target); | ||
90 | state->target = bdrv_attach_child(top, target, "target", &child_file, errp); | ||
91 | -- | ||
92 | 2.24.1 | ||
93 | |||
94 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | First, driver=qcow2 will not work so well with non-qcow2 formats (and | ||
2 | this test claims to support qcow, qed, and vmdk). | ||
3 | 1 | ||
4 | Second, vmdk will always report the backing file format to be vmdk. | ||
5 | Filter that out so the output looks like for all other formats. | ||
6 | |||
7 | Third, the flat vmdk subformats do not support backing files, so they | ||
8 | will not work with this test. | ||
9 | |||
10 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
11 | Message-Id: <20191219144243.1763246-1-mreitz@redhat.com> | ||
12 | Tested-by: Thomas Huth <thuth@redhat.com> | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | tests/qemu-iotests/279 | 7 +++++-- | ||
16 | 1 file changed, 5 insertions(+), 2 deletions(-) | ||
17 | |||
18 | diff --git a/tests/qemu-iotests/279 b/tests/qemu-iotests/279 | ||
19 | index XXXXXXX..XXXXXXX 100755 | ||
20 | --- a/tests/qemu-iotests/279 | ||
21 | +++ b/tests/qemu-iotests/279 | ||
22 | @@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
23 | _supported_fmt qcow qcow2 vmdk qed | ||
24 | _supported_proto file | ||
25 | _supported_os Linux | ||
26 | +_unsupported_imgopts "subformat=monolithicFlat" \ | ||
27 | + "subformat=twoGbMaxExtentFlat" \ | ||
28 | |||
29 | TEST_IMG="$TEST_IMG.base" _make_test_img 64M | ||
30 | TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base" | ||
31 | @@ -XXX,XX +XXX,XX @@ _make_test_img -b "$TEST_IMG.mid" | ||
32 | |||
33 | echo | ||
34 | echo '== qemu-img info --backing-chain ==' | ||
35 | -_img_info --backing-chain | _filter_img_info | ||
36 | +_img_info --backing-chain | _filter_img_info | grep -v 'backing file format' | ||
37 | |||
38 | echo | ||
39 | echo '== qemu-img info --backing-chain --image-opts ==' | ||
40 | -TEST_IMG="driver=qcow2,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts | _filter_img_info | ||
41 | +TEST_IMG="driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts \ | ||
42 | + | _filter_img_info | grep -v 'backing file format' | ||
43 | |||
44 | # success, all done | ||
45 | echo "*** done" | ||
46 | -- | ||
47 | 2.24.1 | ||
48 | |||
49 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | When nbd_close() is called from a coroutine, the connection_co never | ||
2 | gets to run, and thus nbd_teardown_connection() hangs. | ||
3 | 1 | ||
4 | This is because aio_co_enter() only puts the connection_co into the main | ||
5 | coroutine's wake-up queue, so this main coroutine needs to yield and | ||
6 | wait for connection_co to terminate. | ||
7 | |||
8 | Suggested-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
10 | Message-Id: <20200122164532.178040-2-mreitz@redhat.com> | ||
11 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
12 | Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | block/nbd.c | 14 +++++++++++++- | ||
16 | 1 file changed, 13 insertions(+), 1 deletion(-) | ||
17 | |||
18 | diff --git a/block/nbd.c b/block/nbd.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/block/nbd.c | ||
21 | +++ b/block/nbd.c | ||
22 | @@ -XXX,XX +XXX,XX @@ typedef struct BDRVNBDState { | ||
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); | ||
44 | } | ||
45 | |||
46 | static bool nbd_client_connecting(BDRVNBDState *s) | ||
47 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque) | ||
48 | s->ioc = NULL; | ||
49 | } | ||
50 | |||
51 | + if (s->teardown_co) { | ||
52 | + aio_co_wake(s->teardown_co); | ||
53 | + } | ||
54 | aio_wait_kick(); | ||
55 | } | ||
56 | |||
57 | -- | ||
58 | 2.24.1 | ||
59 | |||
60 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | If a protocol driver does not support image creation, we can see whether | ||
2 | maybe the file exists already. If so, just truncating it will be | ||
3 | sufficient. | ||
4 | 1 | ||
5 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
6 | Message-Id: <20200122164532.178040-3-mreitz@redhat.com> | ||
7 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
8 | --- | ||
9 | block.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++----- | ||
10 | 1 file changed, 147 insertions(+), 12 deletions(-) | ||
11 | |||
12 | diff --git a/block.c b/block.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/block.c | ||
15 | +++ b/block.c | ||
16 | @@ -XXX,XX +XXX,XX @@ out: | ||
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, | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | - if (!proto_drv->create_opts) { | ||
191 | - error_setg(errp, "Protocol driver '%s' does not support image creation", | ||
192 | - proto_drv->format_name); | ||
193 | - return; | ||
194 | - } | ||
195 | - | ||
196 | /* Create parameter list */ | ||
197 | create_opts = qemu_opts_append(create_opts, drv->create_opts); | ||
198 | - create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); | ||
199 | + if (proto_drv->create_opts) { | ||
200 | + create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); | ||
201 | + } else { | ||
202 | + create_opts = qemu_opts_append(create_opts, &fallback_create_opts); | ||
203 | + } | ||
204 | |||
205 | opts = qemu_opts_create(create_opts, NULL, 0, &error_abort); | ||
206 | |||
207 | -- | ||
208 | 2.24.1 | ||
209 | |||
210 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The generic fallback implementation effectively does the same. | ||
2 | 1 | ||
3 | Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> | ||
4 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
5 | Message-Id: <20200122164532.178040-4-mreitz@redhat.com> | ||
6 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
7 | --- | ||
8 | block/file-posix.c | 67 ---------------------------------------------- | ||
9 | 1 file changed, 67 deletions(-) | ||
10 | |||
11 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/block/file-posix.c | ||
14 | +++ b/block/file-posix.c | ||
15 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs, | ||
16 | return raw_do_pwrite_zeroes(bs, offset, bytes, flags, true); | ||
17 | } | ||
18 | |||
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, | ||
110 | -- | ||
111 | 2.24.1 | ||
112 | |||
113 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The generic fallback implementation effectively does the same. | ||
2 | 1 | ||
3 | Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> | ||
4 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
5 | Message-Id: <20200122164532.178040-5-mreitz@redhat.com> | ||
6 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
7 | --- | ||
8 | block/iscsi.c | 56 --------------------------------------------------- | ||
9 | 1 file changed, 56 deletions(-) | ||
10 | |||
11 | diff --git a/block/iscsi.c b/block/iscsi.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/block/iscsi.c | ||
14 | +++ b/block/iscsi.c | ||
15 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset, | ||
16 | return 0; | ||
17 | } | ||
18 | |||
19 | -static int coroutine_fn iscsi_co_create_opts(const char *filename, QemuOpts *opts, | ||
20 | - Error **errp) | ||
21 | -{ | ||
22 | - int ret = 0; | ||
23 | - int64_t total_size = 0; | ||
24 | - BlockDriverState *bs; | ||
25 | - IscsiLun *iscsilun = NULL; | ||
26 | - QDict *bs_options; | ||
27 | - Error *local_err = NULL; | ||
28 | - | ||
29 | - bs = bdrv_new(); | ||
30 | - | ||
31 | - /* Read out options */ | ||
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, | ||
92 | -- | ||
93 | 2.24.1 | ||
94 | |||
95 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
2 | Message-Id: <20200122164532.178040-6-mreitz@redhat.com> | ||
3 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
4 | Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> | ||
5 | [mreitz: Added a note that NBD does not support resizing, which is why | ||
6 | the second case is expected to fail] | ||
7 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
8 | --- | ||
9 | tests/qemu-iotests/259 | 62 ++++++++++++++++++++++++++++++++++++++ | ||
10 | tests/qemu-iotests/259.out | 14 +++++++++ | ||
11 | tests/qemu-iotests/group | 1 + | ||
12 | 3 files changed, 77 insertions(+) | ||
13 | create mode 100755 tests/qemu-iotests/259 | ||
14 | create mode 100644 tests/qemu-iotests/259.out | ||
15 | 1 | ||
16 | diff --git a/tests/qemu-iotests/259 b/tests/qemu-iotests/259 | ||
17 | new file mode 100755 | ||
18 | index XXXXXXX..XXXXXXX | ||
19 | --- /dev/null | ||
20 | +++ b/tests/qemu-iotests/259 | ||
21 | @@ -XXX,XX +XXX,XX @@ | ||
22 | +#!/usr/bin/env bash | ||
23 | +# | ||
24 | +# Test generic image creation fallback (by using NBD) | ||
25 | +# | ||
26 | +# Copyright (C) 2019 Red Hat, Inc. | ||
27 | +# | ||
28 | +# This program is free software; you can redistribute it and/or modify | ||
29 | +# it under the terms of the GNU General Public License as published by | ||
30 | +# the Free Software Foundation; either version 2 of the License, or | ||
31 | +# (at your option) any later version. | ||
32 | +# | ||
33 | +# This program is distributed in the hope that it will be useful, | ||
34 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
35 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
36 | +# GNU General Public License for more details. | ||
37 | +# | ||
38 | +# You should have received a copy of the GNU General Public License | ||
39 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
40 | +# | ||
41 | + | ||
42 | +# creator | ||
43 | +owner=mreitz@redhat.com | ||
44 | + | ||
45 | +seq=$(basename $0) | ||
46 | +echo "QA output created by $seq" | ||
47 | + | ||
48 | +status=1 # failure is the default! | ||
49 | + | ||
50 | +_cleanup() | ||
51 | +{ | ||
52 | + _cleanup_test_img | ||
53 | +} | ||
54 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
55 | + | ||
56 | +# get standard environment, filters and checks | ||
57 | +. ./common.rc | ||
58 | +. ./common.filter | ||
59 | + | ||
60 | +_supported_fmt raw | ||
61 | +_supported_proto nbd | ||
62 | +_supported_os Linux | ||
63 | + | ||
64 | + | ||
65 | +_make_test_img 64M | ||
66 | + | ||
67 | +echo | ||
68 | +echo '--- Testing creation ---' | ||
69 | + | ||
70 | +$QEMU_IMG create -f qcow2 "$TEST_IMG" 64M | _filter_img_create | ||
71 | +$QEMU_IMG info "$TEST_IMG" | _filter_img_info | ||
72 | + | ||
73 | +echo | ||
74 | +echo '--- Testing creation for which the node would need to grow ---' | ||
75 | + | ||
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 | ||
79 | + | ||
80 | +# success, all done | ||
81 | +echo "*** done" | ||
82 | +rm -f $seq.full | ||
83 | +status=0 | ||
84 | diff --git a/tests/qemu-iotests/259.out b/tests/qemu-iotests/259.out | ||
85 | new file mode 100644 | ||
86 | index XXXXXXX..XXXXXXX | ||
87 | --- /dev/null | ||
88 | +++ b/tests/qemu-iotests/259.out | ||
89 | @@ -XXX,XX +XXX,XX @@ | ||
90 | +QA output created by 259 | ||
91 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
92 | + | ||
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 | ||
99 | + | ||
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 | ||
103 | +*** done | ||
104 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
105 | index XXXXXXX..XXXXXXX 100644 | ||
106 | --- a/tests/qemu-iotests/group | ||
107 | +++ b/tests/qemu-iotests/group | ||
108 | @@ -XXX,XX +XXX,XX @@ | ||
109 | 256 rw auto quick | ||
110 | 257 rw | ||
111 | 258 rw quick | ||
112 | +259 rw auto quick | ||
113 | 260 rw quick | ||
114 | 261 rw | ||
115 | 262 rw quick migration | ||
116 | -- | ||
117 | 2.24.1 | ||
118 | |||
119 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
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). | ||
4 | 1 | ||
5 | As such, if you use convert -n, the target does not necessarily actually | ||
6 | have a backing file, and then dereferencing out_bs->backing fails here. | ||
7 | |||
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. | ||
12 | |||
13 | Second, we use this value to determine where the target must be | ||
14 | initialized to zeroes (overlays are initialized to zero after the end of | ||
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> | ||
24 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
25 | --- | ||
26 | qemu-img.c | 2 +- | ||
27 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
28 | |||
29 | diff --git a/qemu-img.c b/qemu-img.c | ||
30 | index XXXXXXX..XXXXXXX 100644 | ||
31 | --- a/qemu-img.c | ||
32 | +++ b/qemu-img.c | ||
33 | @@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv) | ||
34 | } | ||
35 | } | ||
36 | |||
37 | - if (s.target_has_backing) { | ||
38 | + if (s.target_has_backing && s.target_is_new) { | ||
39 | /* Errors are treated as "backing length unknown" (which means | ||
40 | * s.target_backing_sectors has to be negative, which it will | ||
41 | * be automatically). The backing file length is used only | ||
42 | -- | ||
43 | 2.24.1 | ||
44 | |||
45 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | This must not crash. | ||
2 | 1 | ||
3 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
4 | Message-Id: <20200121155915.98232-3-mreitz@redhat.com> | ||
5 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
6 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
7 | --- | ||
8 | tests/qemu-iotests/122 | 14 ++++++++++++++ | ||
9 | tests/qemu-iotests/122.out | 5 +++++ | ||
10 | 2 files changed, 19 insertions(+) | ||
11 | |||
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 | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/tests/qemu-iotests/122.out | ||
40 | +++ b/tests/qemu-iotests/122.out | ||
41 | @@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864 | ||
42 | wrote 65536/65536 bytes at offset 0 | ||
43 | 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
44 | Images are identical. | ||
45 | + | ||
46 | +=== -n -B to an image without a backing file === | ||
47 | + | ||
48 | +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 | ||
49 | +Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864 | ||
50 | *** done | ||
51 | -- | ||
52 | 2.24.1 | ||
53 | |||
54 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
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. | ||
7 | 1 | ||
8 | Considering previously the maximum width was four characters and the | ||
9 | field width was chosen to be three characters wider, let us adjust the | ||
10 | field width to be eleven now. | ||
11 | |||
12 | Fixes: de38b5005e946aa3714963ea4c501e279e7d3666 | ||
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> | ||
16 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
17 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
18 | --- | ||
19 | block/qapi.c | 4 ++-- | ||
20 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
21 | |||
22 | diff --git a/block/qapi.c b/block/qapi.c | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/block/qapi.c | ||
25 | +++ b/block/qapi.c | ||
26 | @@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) | ||
27 | char *sizing = NULL; | ||
28 | |||
29 | if (!sn) { | ||
30 | - qemu_printf("%-10s%-20s%7s%20s%15s", | ||
31 | + qemu_printf("%-10s%-20s%11s%20s%15s", | ||
32 | "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); | ||
33 | } else { | ||
34 | ti = sn->date_sec; | ||
35 | @@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) | ||
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, | ||
44 | -- | ||
45 | 2.24.1 | ||
46 | |||
47 | diff view generated by jsdifflib |
1 | Add a test that all fields in "qemu-img snapshot -l"s output are | 1 | When the request free list is exhausted the coroutine waits on |
---|---|---|---|
2 | separated by spaces. | 2 | q->free_req_queue for the next free request. Whenever a request is |
3 | completed a BH is scheduled to invoke nvme_free_req_queue_cb() and wake | ||
4 | up waiting coroutines. | ||
3 | 5 | ||
4 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 6 | 1. nvme_get_free_req() waits for a free request: |
5 | Message-Id: <20200117105859.241818-3-mreitz@redhat.com> | 7 | |
6 | Reviewed-by: Eric Blake <eblake@redhat.com> | 8 | while (q->free_req_head == -1) { |
7 | [mreitz: Renamed test from 284 to 286] | 9 | ... |
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 10 | trace_nvme_free_req_queue_wait(q->s, q->index); |
11 | qemu_co_queue_wait(&q->free_req_queue, &q->lock); | ||
12 | ... | ||
13 | } | ||
14 | |||
15 | 2. nvme_free_req_queue_cb() wakes up the coroutine: | ||
16 | |||
17 | while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) { | ||
18 | ^--- infinite loop when free_req_head == -1 | ||
19 | } | ||
20 | |||
21 | nvme_free_req_queue_cb() and the coroutine form an infinite loop when | ||
22 | q->free_req_head == -1. Fix this by checking q->free_req_head in | ||
23 | nvme_free_req_queue_cb(). If the free request list is exhausted, don't | ||
24 | wake waiting coroutines. Eventually an in-flight request will complete | ||
25 | and the BH will be scheduled again, guaranteeing forward progress. | ||
26 | |||
27 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
28 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
29 | Message-id: 20211208152246.244585-1-stefanha@redhat.com | ||
30 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
9 | --- | 31 | --- |
10 | tests/qemu-iotests/286 | 76 ++++++++++++++++++++++++++++++++++++++ | 32 | block/nvme.c | 5 +++-- |
11 | tests/qemu-iotests/286.out | 8 ++++ | 33 | 1 file changed, 3 insertions(+), 2 deletions(-) |
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 | ||
16 | 34 | ||
17 | diff --git a/tests/qemu-iotests/286 b/tests/qemu-iotests/286 | 35 | diff --git a/block/nvme.c b/block/nvme.c |
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 | ||
114 | index XXXXXXX..XXXXXXX 100644 | 36 | index XXXXXXX..XXXXXXX 100644 |
115 | --- a/tests/qemu-iotests/group | 37 | --- a/block/nvme.c |
116 | +++ b/tests/qemu-iotests/group | 38 | +++ b/block/nvme.c |
117 | @@ -XXX,XX +XXX,XX @@ | 39 | @@ -XXX,XX +XXX,XX @@ static void nvme_free_req_queue_cb(void *opaque) |
118 | 281 rw quick | 40 | NVMeQueuePair *q = opaque; |
119 | 283 auto quick | 41 | |
120 | 284 rw | 42 | qemu_mutex_lock(&q->lock); |
121 | +286 rw quick | 43 | - while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) { |
44 | - /* Retry all pending requests */ | ||
45 | + while (q->free_req_head != -1 && | ||
46 | + qemu_co_enter_next(&q->free_req_queue, &q->lock)) { | ||
47 | + /* Retry waiting requests */ | ||
48 | } | ||
49 | qemu_mutex_unlock(&q->lock); | ||
50 | } | ||
122 | -- | 51 | -- |
123 | 2.24.1 | 52 | 2.33.1 |
124 | 53 | ||
125 | 54 | diff view generated by jsdifflib |