1
The following changes since commit 672f9d0df10a68a5c5f2b32cbc8284abf9f5ee18:
1
The following changes since commit 754f756cc4c6d9d14b7230c62b5bb20f9d655888:
2
2
3
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2020-02-18 14:23:43 +0000)
3
Merge tag 'pull-target-arm-20220422-1' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2022-04-22 08:03:18 -0700)
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/hreitz/qemu.git tags/pull-block-2022-04-25
8
8
9
for you to fetch changes up to dff8d44c96f128480430b0c59ed8760917dbd427:
9
for you to fetch changes up to 348a0740afc5b313599533eb69bbb2b95d2f1bba:
10
10
11
iotests: Test snapshot -l field separation (2020-02-20 16:43:42 +0100)
11
iotests/108: Fix when missing user_allow_other (2022-04-25 14:46:45 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Block patches:
15
- qemu-img convert: New --target-is-zero parameter
15
- New @force parameter for blockdev-change-medium
16
- qcow2: Specify non-default compression type flag
16
- Improvements to the iotests to help with debugging
17
- optionally flat output for query-named-block-nodes
17
- Fix iotest 108 on systems without user_allow_other in fuse.conf
18
- some fixes
19
- pseudo-creation of images on block devices is now done by a generic
20
block layer function
21
18
22
----------------------------------------------------------------
19
----------------------------------------------------------------
23
Daniel P. Berrangé (1):
20
Denis V. Lunev (1):
24
block: always fill entire LUKS header space with zeros
21
block: add 'force' parameter to 'blockdev-change-medium' command
25
22
26
David Edmondson (1):
23
Hanna Reitz (1):
27
qemu-img: Add --target-is-zero to convert
24
iotests/108: Fix when missing user_allow_other
28
25
29
Max Reitz (11):
26
John Snow (12):
30
iotests/147: Fix drive parameters
27
iotests: replace calls to log(qemu_io(...)) with qemu_io_log()
31
iotests/279: Fix for non-qcow2 formats
28
iotests/163: Fix broken qemu-io invocation
32
block/nbd: Fix hang in .bdrv_close()
29
iotests: Don't check qemu_io() output for specific error strings
33
block: Generic file creation fallback
30
iotests/040: Don't check image pattern on zero-length image
34
file-posix: Drop hdev_co_create_opts()
31
iotests/040: Fix TestCommitWithFilters test
35
iscsi: Drop iscsi_co_create_opts()
32
iotests: create generic qemu_tool() function
36
iotests: Add test for image creation fallback
33
iotests: rebase qemu_io() on top of qemu_tool()
37
qemu-img: Fix convert -n -B for backing-less targets
34
iotests/migration-permissions: use assertRaises() for qemu_io()
38
iotests: Test convert -n -B to backing-less target
35
negative test
39
block: Fix VM size field width in snapshot dump
36
iotests/image-fleecing: switch to qemu_io()
40
iotests: Test snapshot -l field separation
37
iotests: remove qemu_io_pipe_and_status()
38
iotests: remove qemu_io_silent() and qemu_io_silent_check().
39
iotests: make qemu_io_log() check return codes by default
41
40
42
Peter Krempa (1):
41
qapi/block.json | 6 ++
43
qapi: Allow getting flat output from 'query-named-block-nodes'
42
block/qapi-sysemu.c | 3 +-
44
43
monitor/hmp-cmds.c | 4 +-
45
Thomas Huth (1):
44
hmp-commands.hx | 11 ++-
46
iotests: Remove the superfluous 2nd check for the availability of
45
tests/qemu-iotests/030 | 85 +++++++++++--------
47
quorum
46
tests/qemu-iotests/040 | 53 +++++++-----
48
47
tests/qemu-iotests/056 | 2 +-
49
Vladimir Sementsov-Ogievskiy (3):
48
tests/qemu-iotests/108 | 2 +-
50
docs: improve qcow2 spec about extending image header
49
tests/qemu-iotests/149 | 6 +-
51
docs: qcow2: introduce compression type feature
50
tests/qemu-iotests/163 | 5 +-
52
block/backup-top: fix flags handling
51
tests/qemu-iotests/205 | 4 +-
53
52
tests/qemu-iotests/216 | 12 +--
54
block.c | 164 +++++++++++++++++++++++++++++++++----
53
tests/qemu-iotests/218 | 5 +-
55
block/backup-top.c | 31 ++++---
54
tests/qemu-iotests/224 | 4 +-
56
block/file-posix.c | 67 ---------------
55
tests/qemu-iotests/242 | 6 +-
57
block/iscsi.c | 56 -------------
56
tests/qemu-iotests/245 | 17 ++--
58
block/nbd.c | 14 +++-
57
tests/qemu-iotests/255 | 4 +-
59
block/qapi.c | 15 +++-
58
tests/qemu-iotests/258 | 11 ++-
60
block/qcow2.c | 11 ++-
59
tests/qemu-iotests/298 | 17 ++--
61
blockdev.c | 8 +-
60
tests/qemu-iotests/303 | 4 +-
62
docs/interop/qcow2.txt | 64 ++++++++++++++-
61
tests/qemu-iotests/310 | 22 ++---
63
docs/interop/qemu-img.rst | 9 +-
62
tests/qemu-iotests/iotests.py | 69 ++++++++-------
64
include/block/block.h | 2 +-
63
tests/qemu-iotests/tests/image-fleecing | 30 ++++---
65
include/block/qapi.h | 4 +-
64
.../qemu-iotests/tests/migration-permissions | 28 +++---
66
monitor/hmp-cmds.c | 2 +-
65
.../tests/mirror-ready-cancel-error | 2 +-
67
qapi/block-core.json | 7 +-
66
.../qemu-iotests/tests/nbd-reconnect-on-open | 2 +-
68
qemu-img-cmds.hx | 4 +-
67
.../qemu-iotests/tests/stream-error-on-reset | 4 +-
69
qemu-img.c | 28 ++++++-
68
ui/cocoa.m | 1 +
70
tests/qemu-iotests/122 | 14 ++++
69
28 files changed, 231 insertions(+), 188 deletions(-)
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
70
90
--
71
--
91
2.24.1
72
2.35.1
92
93
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
1
From: Peter Krempa <pkrempa@redhat.com>
1
From: "Denis V. Lunev" <den@openvz.org>
2
2
3
When a management application manages node names there's no reason to
3
'blockdev-change-medium' is a convinient wrapper for the following
4
recurse into backing images in the output of query-named-block-nodes.
4
sequence of commands:
5
* blockdev-open-tray
6
* blockdev-remove-medium
7
* blockdev-insert-medium
8
* blockdev-close-tray
9
and should be used f.e. to change ISO image inside the CD-ROM tray.
10
Though the guest could lock the tray and some linux guests like
11
CentOS 8.5 actually does that. In this case the execution if this
12
command results in the error like the following:
13
Device 'scsi0-0-1-0' is locked and force was not specified,
14
wait for tray to open and try again.
5
15
6
Add a parameter to the command which will return just the top level
16
This situation is could be resolved 'blockdev-open-tray' by passing
7
structs.
17
flag 'force' inside. Thus is seems reasonable to add the same
18
capability for 'blockdev-change-medium' too.
8
19
9
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
20
Signed-off-by: Denis V. Lunev <den@openvz.org>
10
Message-Id: <4470f8c779abc404dcf65e375db195cd91a80651.1579509782.git.pkrempa@redhat.com>
21
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@openvz.org>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
22
Acked-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
12
[mreitz: Fixed coding style]
23
CC: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
CC: Hanna Reitz <hreitz@redhat.com>
25
CC: Eric Blake <eblake@redhat.com>
26
CC: Markus Armbruster <armbru@redhat.com>
27
Message-Id: <20220412221846.280723-1-den@openvz.org>
28
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
29
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
---
30
---
15
block.c | 5 +++--
31
qapi/block.json | 6 ++++++
16
block/qapi.c | 11 +++++++++--
32
block/qapi-sysemu.c | 3 ++-
17
blockdev.c | 8 ++++++--
33
monitor/hmp-cmds.c | 4 +++-
18
include/block/block.h | 2 +-
34
hmp-commands.hx | 11 +++++++----
19
include/block/qapi.h | 4 +++-
35
ui/cocoa.m | 1 +
20
monitor/hmp-cmds.c | 2 +-
36
5 files changed, 19 insertions(+), 6 deletions(-)
21
qapi/block-core.json | 7 ++++++-
22
7 files changed, 29 insertions(+), 10 deletions(-)
23
37
24
diff --git a/block.c b/block.c
38
diff --git a/qapi/block.json b/qapi/block.json
25
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
26
--- a/block.c
40
--- a/qapi/block.json
27
+++ b/block.c
41
+++ b/qapi/block.json
28
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_node(const char *node_name)
42
@@ -XXX,XX +XXX,XX @@
29
}
43
# @read-only-mode: change the read-only mode of the device; defaults
30
44
# to 'retain'
31
/* Put this QMP function here so it can access the static graph_bdrv_states. */
45
#
32
-BlockDeviceInfoList *bdrv_named_nodes_list(Error **errp)
46
+# @force: if false (the default), an eject request through blockdev-open-tray
33
+BlockDeviceInfoList *bdrv_named_nodes_list(bool flat,
47
+# will be sent to the guest if it has locked the tray (and the tray
34
+ Error **errp)
48
+# will not be opened immediately); if true, the tray will be opened
35
{
49
+# regardless of whether it is locked. (since 7.1)
36
BlockDeviceInfoList *list, *entry;
50
+#
37
BlockDriverState *bs;
51
# Features:
38
52
# @deprecated: Member @device is deprecated. Use @id instead.
39
list = NULL;
53
#
40
QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) {
54
@@ -XXX,XX +XXX,XX @@
41
- BlockDeviceInfo *info = bdrv_block_device_info(NULL, bs, errp);
55
'*id': 'str',
42
+ BlockDeviceInfo *info = bdrv_block_device_info(NULL, bs, flat, errp);
56
'filename': 'str',
43
if (!info) {
57
'*format': 'str',
44
qapi_free_BlockDeviceInfoList(list);
58
+ '*force': 'bool',
45
return NULL;
59
'*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
46
diff --git a/block/qapi.c b/block/qapi.c
60
61
62
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
47
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
48
--- a/block/qapi.c
64
--- a/block/qapi-sysemu.c
49
+++ b/block/qapi.c
65
+++ b/block/qapi-sysemu.c
50
@@ -XXX,XX +XXX,XX @@
66
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
51
#include "qemu/cutils.h"
67
bool has_id, const char *id,
52
68
const char *filename,
53
BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
69
bool has_format, const char *format,
54
- BlockDriverState *bs, Error **errp)
70
+ bool has_force, bool force,
55
+ BlockDriverState *bs,
71
bool has_read_only,
56
+ bool flat,
72
BlockdevChangeReadOnlyMode read_only,
57
+ Error **errp)
73
Error **errp)
58
{
74
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
59
ImageInfo **p_image_info;
75
60
BlockDriverState *bs0;
76
rc = do_open_tray(has_device ? device : NULL,
61
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
77
has_id ? id : NULL,
62
return NULL;
78
- false, &err);
63
}
79
+ force, &err);
64
80
if (rc && rc != -ENOSYS) {
65
+ /* stop gathering data for flat output */
81
error_propagate(errp, err);
66
+ if (flat) {
82
goto fail;
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
83
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
131
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
132
--- a/monitor/hmp-cmds.c
85
--- a/monitor/hmp-cmds.c
133
+++ b/monitor/hmp-cmds.c
86
+++ b/monitor/hmp-cmds.c
134
@@ -XXX,XX +XXX,XX @@ void hmp_info_block(Monitor *mon, const QDict *qdict)
87
@@ -XXX,XX +XXX,XX @@ void hmp_change(Monitor *mon, const QDict *qdict)
88
const char *target = qdict_get_str(qdict, "target");
89
const char *arg = qdict_get_try_str(qdict, "arg");
90
const char *read_only = qdict_get_try_str(qdict, "read-only-mode");
91
+ bool force = qdict_get_try_bool(qdict, "force", false);
92
BlockdevChangeReadOnlyMode read_only_mode = 0;
93
Error *err = NULL;
94
95
@@ -XXX,XX +XXX,XX @@ void hmp_change(Monitor *mon, const QDict *qdict)
96
}
97
98
qmp_blockdev_change_medium(true, device, false, NULL, target,
99
- !!arg, arg, !!read_only, read_only_mode,
100
+ !!arg, arg, true, force,
101
+ !!read_only, read_only_mode,
102
&err);
135
}
103
}
136
104
137
/* Print node information */
105
diff --git a/hmp-commands.hx b/hmp-commands.hx
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
106
index XXXXXXX..XXXXXXX 100644
145
--- a/qapi/block-core.json
107
--- a/hmp-commands.hx
146
+++ b/qapi/block-core.json
108
+++ b/hmp-commands.hx
147
@@ -XXX,XX +XXX,XX @@
109
@@ -XXX,XX +XXX,XX @@ ERST
148
#
110
149
# Get the named block driver list
111
{
150
#
112
.name = "change",
151
+# @flat: Omit the nested data about backing image ("backing-image" key) if true.
113
- .args_type = "device:B,target:F,arg:s?,read-only-mode:s?",
152
+# Default is false (Since 5.0)
114
- .params = "device filename [format [read-only-mode]]",
153
+#
115
- .help = "change a removable medium, optional format",
154
# Returns: the list of BlockDeviceInfo
116
+ .args_type = "device:B,force:-f,target:F,arg:s?,read-only-mode:s?",
155
#
117
+ .params = "device [-f] filename [format [read-only-mode]]",
156
# Since: 2.0
118
+ .help = "change a removable medium, optional format, use -f to force the operation",
157
@@ -XXX,XX +XXX,XX @@
119
.cmd = hmp_change,
158
# } } ] }
120
},
159
#
121
160
##
122
@@ -XXX,XX +XXX,XX @@ SRST
161
-{ 'command': 'query-named-block-nodes', 'returns': [ 'BlockDeviceInfo' ] }
123
``change`` *device* *setting*
162
+{ 'command': 'query-named-block-nodes',
124
Change the configuration of a device.
163
+ 'returns': [ 'BlockDeviceInfo' ],
125
164
+ 'data': { '*flat': 'bool' } }
126
- ``change`` *diskdevice* *filename* [*format* [*read-only-mode*]]
165
127
+ ``change`` *diskdevice* [-f] *filename* [*format* [*read-only-mode*]]
166
##
128
Change the medium for a removable disk device to point to *filename*. eg::
167
# @XDbgBlockGraphNodeType:
129
130
(qemu) change ide1-cd0 /path/to/some.iso
131
132
+ ``-f``
133
+ forces the operation even if the guest has locked the tray.
134
+
135
*format* is optional.
136
137
*read-only-mode* may be used to change the read-only status of the device.
138
diff --git a/ui/cocoa.m b/ui/cocoa.m
139
index XXXXXXX..XXXXXXX 100644
140
--- a/ui/cocoa.m
141
+++ b/ui/cocoa.m
142
@@ -XXX,XX +XXX,XX @@ - (void)changeDeviceMedia:(id)sender
143
[file cStringUsingEncoding:
144
NSASCIIStringEncoding],
145
true, "raw",
146
+ true, false,
147
false, 0,
148
&err);
149
});
168
--
150
--
169
2.24.1
151
2.35.1
170
152
171
153
diff view generated by jsdifflib
1
Add a test that all fields in "qemu-img snapshot -l"s output are
1
From: John Snow <jsnow@redhat.com>
2
separated by spaces.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
This makes these callsites a little simpler, but the real motivation is
5
Message-Id: <20200117105859.241818-3-mreitz@redhat.com>
4
a forthcoming commit will change the return type of qemu_io(), so removing
5
users of the return value now is helpful.
6
7
Signed-off-by: John Snow <jsnow@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
7
[mreitz: Renamed test from 284 to 286]
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20220418211504.943969-2-jsnow@redhat.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
9
---
12
---
10
tests/qemu-iotests/286 | 76 ++++++++++++++++++++++++++++++++++++++
13
tests/qemu-iotests/242 | 6 +++---
11
tests/qemu-iotests/286.out | 8 ++++
14
tests/qemu-iotests/255 | 4 +---
12
tests/qemu-iotests/group | 1 +
15
tests/qemu-iotests/303 | 4 ++--
13
3 files changed, 85 insertions(+)
16
3 files changed, 6 insertions(+), 8 deletions(-)
14
create mode 100755 tests/qemu-iotests/286
15
create mode 100644 tests/qemu-iotests/286.out
16
17
17
diff --git a/tests/qemu-iotests/286 b/tests/qemu-iotests/286
18
diff --git a/tests/qemu-iotests/242 b/tests/qemu-iotests/242
18
new file mode 100755
19
index XXXXXXX..XXXXXXX 100755
19
index XXXXXXX..XXXXXXX
20
--- a/tests/qemu-iotests/242
20
--- /dev/null
21
+++ b/tests/qemu-iotests/242
21
+++ b/tests/qemu-iotests/286
22
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
23
+#!/usr/bin/env bash
23
import iotests
24
+#
24
import json
25
+# Test qemu-img snapshot -l
25
import struct
26
+#
26
-from iotests import qemu_img_create, qemu_io, qemu_img_info, \
27
+# Copyright (C) 2019 Red Hat, Inc.
27
- file_path, img_info_log, log, filter_qemu_io
28
+#
28
+from iotests import qemu_img_create, qemu_io_log, qemu_img_info, \
29
+# This program is free software; you can redistribute it and/or modify
29
+ file_path, img_info_log, log
30
+# it under the terms of the GNU General Public License as published by
30
31
+# the Free Software Foundation; either version 2 of the License, or
31
iotests.script_initialize(supported_fmts=['qcow2'],
32
+# (at your option) any later version.
32
supported_protocols=['file'],
33
+#
33
@@ -XXX,XX +XXX,XX @@ def add_bitmap(bitmap_number, persistent, disabled):
34
+# This program is distributed in the hope that it will be useful,
34
35
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
35
def write_to_disk(offset, size):
36
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36
write = 'write {} {}'.format(offset, size)
37
+# GNU General Public License for more details.
37
- log(qemu_io('-c', write, disk), filters=[filter_qemu_io])
38
+#
38
+ qemu_io_log('-c', write, disk)
39
+# You should have received a copy of the GNU General Public License
39
40
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
40
41
+#
41
def toggle_flag(offset):
42
+
42
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
43
+seq=$(basename "$0")
43
index XXXXXXX..XXXXXXX 100755
44
+echo "QA output created by $seq"
44
--- a/tests/qemu-iotests/255
45
+
45
+++ b/tests/qemu-iotests/255
46
+status=1    # failure is the default!
46
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('src.qcow2') as src_path, \
47
+
47
iotests.qemu_img_create('-f', iotests.imgfmt, src_path, size_str)
48
+_cleanup()
48
iotests.qemu_img_create('-f', iotests.imgfmt, dst_path, size_str)
49
+{
49
50
+ _cleanup_test_img
50
- iotests.log(iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write 0 1M',
51
+}
51
- src_path),
52
+trap "_cleanup; exit \$status" 0 1 2 3 15
52
- filters=[iotests.filter_test_dir, iotests.filter_qemu_io])
53
+
53
+ iotests.qemu_io_log('-f', iotests.imgfmt, '-c', 'write 0 1M', src_path),
54
+# get standard environment, filters and checks
54
55
+. ./common.rc
55
vm.add_object('throttle-group,x-bps-read=4096,id=throttle0')
56
+. ./common.filter
56
57
+. ./common.qemu
57
diff --git a/tests/qemu-iotests/303 b/tests/qemu-iotests/303
58
+
58
index XXXXXXX..XXXXXXX 100755
59
+_supported_fmt qcow2
59
--- a/tests/qemu-iotests/303
60
+_supported_proto file
60
+++ b/tests/qemu-iotests/303
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 @@
61
@@ -XXX,XX +XXX,XX @@
105
+QA output created by 286
62
106
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
63
import iotests
107
+QEMU X.Y.Z monitor - type 'help' for more information
64
import subprocess
108
+(qemu) savevm abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
65
-from iotests import qemu_img_create, qemu_io, file_path, log, filter_qemu_io, \
109
+(qemu) quit
66
+from iotests import qemu_img_create, qemu_io_log, file_path, log, \
110
+Output structure:
67
verify_qcow2_zstd_compression
111
+(snapshot ID) (snapshot name) (VM state size value) (VM state size unit) (snapshot date) (snapshot time) (VM clock)
68
112
+*** done
69
iotests.script_initialize(supported_fmts=['qcow2'],
113
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
70
@@ -XXX,XX +XXX,XX @@ def create_bitmap(bitmap_number, disabled):
114
index XXXXXXX..XXXXXXX 100644
71
115
--- a/tests/qemu-iotests/group
72
def write_to_disk(offset, size):
116
+++ b/tests/qemu-iotests/group
73
write = f'write {offset} {size}'
117
@@ -XXX,XX +XXX,XX @@
74
- log(qemu_io('-c', write, disk), filters=[filter_qemu_io])
118
281 rw quick
75
+ qemu_io_log('-c', write, disk)
119
283 auto quick
76
120
284 rw
77
121
+286 rw quick
78
def add_bitmap(num, begin, end, disabled):
122
--
79
--
123
2.24.1
80
2.35.1
124
125
diff view generated by jsdifflib
1
When printing the snapshot list (e.g. with qemu-img snapshot -l), the VM
1
From: John Snow <jsnow@redhat.com>
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
2
8
Considering previously the maximum width was four characters and the
3
The 'read' commands to qemu-io were malformed, and this invocation only
9
field width was chosen to be three characters wider, let us adjust the
4
worked by coincidence because the error messages were identical. Oops.
10
field width to be eleven now.
11
5
12
Fixes: de38b5005e946aa3714963ea4c501e279e7d3666
6
There's no point in checking the patterning of the reference image, so
13
Buglink: https://bugs.launchpad.net/qemu/+bug/1859989
7
just check the empty image by itself instead.
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
15
Message-Id: <20200117105859.241818-2-mreitz@redhat.com>
9
(Note: as of this commit, nothing actually enforces that this command
10
completes successfully, but a forthcoming commit in this series will
11
enforce that qemu_io() must have a zero status code.)
12
13
Signed-off-by: John Snow <jsnow@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
16
Message-Id: <20220418211504.943969-3-jsnow@redhat.com>
17
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
18
---
18
---
19
block/qapi.c | 4 ++--
19
tests/qemu-iotests/163 | 5 +----
20
1 file changed, 2 insertions(+), 2 deletions(-)
20
1 file changed, 1 insertion(+), 4 deletions(-)
21
21
22
diff --git a/block/qapi.c b/block/qapi.c
22
diff --git a/tests/qemu-iotests/163 b/tests/qemu-iotests/163
23
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100755
24
--- a/block/qapi.c
24
--- a/tests/qemu-iotests/163
25
+++ b/block/qapi.c
25
+++ b/tests/qemu-iotests/163
26
@@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn)
26
@@ -XXX,XX +XXX,XX @@ class ShrinkBaseClass(iotests.QMPTestCase):
27
char *sizing = NULL;
27
qemu_img('resize', '-f', iotests.imgfmt, '--shrink', test_img,
28
28
self.shrink_size)
29
if (!sn) {
29
30
- qemu_printf("%-10s%-20s%7s%20s%15s",
30
- self.assertEqual(
31
+ qemu_printf("%-10s%-20s%11s%20s%15s",
31
- qemu_io('-c', 'read -P 0x00 %s'%self.shrink_size, test_img),
32
"ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
32
- qemu_io('-c', 'read -P 0x00 %s'%self.shrink_size, check_img),
33
} else {
33
- "Verifying image content")
34
ti = sn->date_sec;
34
+ qemu_io('-c', f"read -P 0x00 0 {self.shrink_size}", test_img)
35
@@ -XXX,XX +XXX,XX @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn)
35
36
(int)(secs % 60),
36
self.image_verify()
37
(int)((sn->vm_clock_nsec / 1000000) % 1000));
37
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
--
38
--
45
2.24.1
39
2.35.1
46
47
diff view generated by jsdifflib
1
This must not crash.
1
From: John Snow <jsnow@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
A forthcoming commit updates qemu_io() to raise an exception on non-zero
4
Message-Id: <20200121155915.98232-3-mreitz@redhat.com>
4
return by default, and changes its return type.
5
Reviewed-by: John Snow <jsnow@redhat.com>
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
In preparation, simplify some calls to qemu_io() that assert that
7
specific error message strings do not appear in qemu-io's
8
output. Asserting that all of these calls return a status code of zero
9
will be a more robust way to guard against failure.
10
11
Signed-off-by: John Snow <jsnow@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
14
Message-Id: <20220418211504.943969-4-jsnow@redhat.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
---
16
---
8
tests/qemu-iotests/122 | 14 ++++++++++++++
17
tests/qemu-iotests/040 | 33 ++++++++++++++++-----------------
9
tests/qemu-iotests/122.out | 5 +++++
18
tests/qemu-iotests/056 | 2 +-
10
2 files changed, 19 insertions(+)
19
2 files changed, 17 insertions(+), 18 deletions(-)
11
20
12
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
21
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
13
index XXXXXXX..XXXXXXX 100755
22
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/122
23
--- a/tests/qemu-iotests/040
15
+++ b/tests/qemu-iotests/122
24
+++ b/tests/qemu-iotests/040
16
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG".orig
25
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
17
26
18
$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG".orig
27
def test_commit(self):
19
28
self.run_commit_test(mid_img, backing_img)
20
+echo
29
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
21
+echo '=== -n -B to an image without a backing file ==='
30
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
22
+echo
31
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
23
+
32
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
24
+# Base for the output
33
25
+TEST_IMG="$TEST_IMG".base _make_test_img 64M
34
def test_commit_node(self):
26
+
35
self.run_commit_test("mid", "base", node_names=True)
27
+# Output that does have $TEST_IMG.base set as its (implicit) backing file
36
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
28
+TEST_IMG="$TEST_IMG".orig _make_test_img 64M
37
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
29
+
38
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
30
+# Convert with -n, which should not confuse -B with "target BDS has a
39
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
31
+# backing file"
40
32
+$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -n "$TEST_IMG" "$TEST_IMG".orig
41
@iotests.skip_if_unsupported(['throttle'])
33
+
42
def test_commit_with_filter_and_quit(self):
34
# success, all done
43
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
35
echo '*** done'
44
36
rm -f $seq.full
45
def test_top_is_active(self):
37
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
46
self.run_commit_test(test_img, backing_img, need_ready=True)
38
index XXXXXXX..XXXXXXX 100644
47
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
39
--- a/tests/qemu-iotests/122.out
48
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
40
+++ b/tests/qemu-iotests/122.out
49
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
41
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864
50
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
42
wrote 65536/65536 bytes at offset 0
51
43
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
52
def test_top_is_default_active(self):
44
Images are identical.
53
self.run_default_commit_test()
45
+
54
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
46
+=== -n -B to an image without a backing file ===
55
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
47
+
56
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
48
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
57
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
49
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864
58
50
*** done
59
def test_top_and_base_reversed(self):
60
self.assert_no_active_block_jobs()
61
@@ -XXX,XX +XXX,XX @@ class TestRelativePaths(ImageCommitTestCase):
62
63
def test_commit(self):
64
self.run_commit_test(self.mid_img, self.backing_img)
65
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed"))
66
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed"))
67
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs)
68
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs)
69
70
def test_device_not_found(self):
71
result = self.vm.qmp('block-commit', device='nonexistent', top='%s' % self.mid_img)
72
@@ -XXX,XX +XXX,XX @@ class TestRelativePaths(ImageCommitTestCase):
73
74
def test_top_is_active(self):
75
self.run_commit_test(self.test_img, self.backing_img)
76
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs).find("verification failed"))
77
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed"))
78
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', self.backing_img_abs)
79
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', self.backing_img_abs)
80
81
def test_top_and_base_reversed(self):
82
self.assert_no_active_block_jobs()
83
@@ -XXX,XX +XXX,XX @@ class TestCommitWithFilters(iotests.QMPTestCase):
84
85
def do_test_io(self, read_or_write):
86
for index, pattern_file in enumerate(self.pattern_files):
87
- result = qemu_io('-f', iotests.imgfmt,
88
- '-c',
89
- f'{read_or_write} -P {index + 1} {index}M 1M',
90
- pattern_file)
91
- self.assertFalse('Pattern verification failed' in result)
92
+ qemu_io('-f', iotests.imgfmt,
93
+ '-c',
94
+ f'{read_or_write} -P {index + 1} {index}M 1M',
95
+ pattern_file)
96
97
@iotests.skip_if_unsupported(['throttle'])
98
def setUp(self):
99
diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
100
index XXXXXXX..XXXXXXX 100755
101
--- a/tests/qemu-iotests/056
102
+++ b/tests/qemu-iotests/056
103
@@ -XXX,XX +XXX,XX @@ class TestSyncModesNoneAndTop(iotests.QMPTestCase):
104
105
self.vm.shutdown()
106
time.sleep(1)
107
- self.assertEqual(-1, qemu_io('-c', 'read -P0x41 0 512', target_img).find("verification failed"))
108
+ qemu_io('-c', 'read -P0x41 0 512', target_img)
109
110
class TestBeforeWriteNotifier(iotests.QMPTestCase):
111
def setUp(self):
51
--
112
--
52
2.24.1
113
2.35.1
53
54
diff view generated by jsdifflib
1
If a protocol driver does not support image creation, we can see whether
1
From: John Snow <jsnow@redhat.com>
2
maybe the file exists already. If so, just truncating it will be
3
sufficient.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
qemu-io fails on read/write beyond end-of-file on raw images, so skip
6
Message-Id: <20200122164532.178040-3-mreitz@redhat.com>
4
these invocations when running the zero-length image tests.
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20220418211504.943969-5-jsnow@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
11
---
9
block.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
12
tests/qemu-iotests/040 | 14 ++++++++++++--
10
1 file changed, 147 insertions(+), 12 deletions(-)
13
1 file changed, 12 insertions(+), 2 deletions(-)
11
14
12
diff --git a/block.c b/block.c
15
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100755
14
--- a/block.c
17
--- a/tests/qemu-iotests/040
15
+++ b/block.c
18
+++ b/tests/qemu-iotests/040
16
@@ -XXX,XX +XXX,XX @@ out:
19
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
17
return ret;
20
qemu_img('create', '-f', iotests.imgfmt,
18
}
21
'-o', 'backing_file=%s' % mid_img,
19
22
'-F', iotests.imgfmt, test_img)
20
-int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
23
- qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img)
21
+/**
24
- qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img)
22
+ * Helper function for bdrv_create_file_fallback(): Resize @blk to at
25
+ if self.image_len:
23
+ * least the given @minimum_size.
26
+ qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img)
24
+ *
27
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288',
25
+ * On success, return @blk's actual length.
28
+ mid_img)
26
+ * Otherwise, return -errno.
29
self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=mid,backing.backing.node-name=base", interface="none")
27
+ */
30
self.vm.add_device('virtio-scsi')
28
+static int64_t create_file_fallback_truncate(BlockBackend *blk,
31
self.vm.add_device("scsi-hd,id=scsi0,drive=drive0")
29
+ int64_t minimum_size, Error **errp)
32
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
30
{
33
31
- BlockDriver *drv;
34
def test_commit(self):
32
+ Error *local_err = NULL;
35
self.run_commit_test(mid_img, backing_img)
33
+ int64_t size;
36
+ if not self.image_len:
34
+ int ret;
37
+ return
35
+
38
qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
36
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
39
qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
37
+ if (ret < 0 && ret != -ENOTSUP) {
40
38
+ error_propagate(errp, local_err);
41
def test_commit_node(self):
39
+ return ret;
42
self.run_commit_test("mid", "base", node_names=True)
40
+ }
43
+ if not self.image_len:
41
+
44
+ return
42
+ size = blk_getlength(blk);
45
qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
43
+ if (size < 0) {
46
qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
44
+ error_free(local_err);
47
45
+ error_setg_errno(errp, -size,
48
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
46
+ "Failed to inquire the new image file's length");
49
47
+ return size;
50
def test_top_is_active(self):
48
+ }
51
self.run_commit_test(test_img, backing_img, need_ready=True)
49
+
52
+ if not self.image_len:
50
+ if (size < minimum_size) {
53
+ return
51
+ /* Need to grow the image, but we failed to do that */
54
qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
52
+ error_propagate(errp, local_err);
55
qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
53
+ return -ENOTSUP;
56
54
+ }
57
def test_top_is_default_active(self):
55
+
58
self.run_default_commit_test()
56
+ error_free(local_err);
59
+ if not self.image_len:
57
+ local_err = NULL;
60
+ return
58
+
61
qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
59
+ return size;
62
qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
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
63
207
--
64
--
208
2.24.1
65
2.35.1
209
210
diff view generated by jsdifflib
1
When nbd_close() is called from a coroutine, the connection_co never
1
From: John Snow <jsnow@redhat.com>
2
gets to run, and thus nbd_teardown_connection() hangs.
3
2
4
This is because aio_co_enter() only puts the connection_co into the main
3
Without this change, asserting that qemu_io always returns 0 causes this
5
coroutine's wake-up queue, so this main coroutine needs to yield and
4
test to fail in a way we happened not to be catching previously:
6
wait for connection_co to terminate.
7
5
8
Suggested-by: Kevin Wolf <kwolf@redhat.com>
6
qemu.utils.VerboseProcessError: Command
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
'('/home/jsnow/src/qemu/bin/git/tests/qemu-iotests/../../qemu-io',
10
Message-Id: <20200122164532.178040-2-mreitz@redhat.com>
8
'--cache', 'writeback', '--aio', 'threads', '-f', 'qcow2', '-c',
9
'read -P 4 3M 1M',
10
'/home/jsnow/src/qemu/bin/git/tests/qemu-iotests/scratch/3.img')'
11
returned non-zero exit status 1.
12
┏━ output ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
13
┃ qemu-io: can't open device
14
┃ /home/jsnow/src/qemu/bin/git/tests/qemu-iotests/scratch/3.img:
15
┃ Could not open backing file: Could not open backing file: Throttle
16
┃ group 'tg' does not exist
17
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
18
19
The commit jobs changes the backing file string stored in the image file
20
header belonging to the node above the commit’s top node to point to the
21
commit target (the base node). QEMU tries to be as accurate as
22
possible, and so in these test cases will include the filter that is
23
part of the block graph in that backing file string (by virtue of making
24
it a json:{} description of the post-commit subgraph). This makes
25
little sense outside of QEMU, though: Specifically, the throttle node in
26
that subgraph will dearly miss its supposedly associated throttle group
27
object.
28
29
When starting the commit job, we can specify a custom backing file
30
string to write into said image file, so let’s use that feature to write
31
the plain filename of the backing chain’s next actual image file there.
32
33
Explicitly provide the backing file so that opening the file outside of
34
QEMU (Where we will not have throttle groups) will succeed.
35
36
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
37
Signed-off-by: John Snow <jsnow@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
38
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
39
Message-Id: <20220418211504.943969-6-jsnow@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
40
---
15
block/nbd.c | 14 +++++++++++++-
41
tests/qemu-iotests/040 | 6 ++++--
16
1 file changed, 13 insertions(+), 1 deletion(-)
42
1 file changed, 4 insertions(+), 2 deletions(-)
17
43
18
diff --git a/block/nbd.c b/block/nbd.c
44
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
19
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100755
20
--- a/block/nbd.c
46
--- a/tests/qemu-iotests/040
21
+++ b/block/nbd.c
47
+++ b/tests/qemu-iotests/040
22
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVNBDState {
48
@@ -XXX,XX +XXX,XX @@ class TestCommitWithFilters(iotests.QMPTestCase):
23
CoMutex send_mutex;
49
job_id='commit',
24
CoQueue free_sema;
50
device='top-filter',
25
Coroutine *connection_co;
51
top_node='cow-2',
26
+ Coroutine *teardown_co;
52
- base_node='cow-1')
27
QemuCoSleepState *connection_co_sleep_ns_state;
53
+ base_node='cow-1',
28
bool drained;
54
+ backing_file=self.img1)
29
bool wait_drained_end;
55
self.assert_qmp(result, 'return', {})
30
@@ -XXX,XX +XXX,XX @@ static void nbd_teardown_connection(BlockDriverState *bs)
56
self.wait_until_completed(drive='commit')
31
qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
57
32
}
58
@@ -XXX,XX +XXX,XX @@ class TestCommitWithFilters(iotests.QMPTestCase):
33
}
59
job_id='commit',
34
- BDRV_POLL_WHILE(bs, s->connection_co);
60
device='top-filter',
35
+ if (qemu_in_coroutine()) {
61
top_node='cow-1',
36
+ s->teardown_co = qemu_coroutine_self();
62
- base_node='cow-0')
37
+ /* connection_co resumes us when it terminates */
63
+ base_node='cow-0',
38
+ qemu_coroutine_yield();
64
+ backing_file=self.img0)
39
+ s->teardown_co = NULL;
65
self.assert_qmp(result, 'return', {})
40
+ } else {
66
self.wait_until_completed(drive='commit')
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
67
57
--
68
--
58
2.24.1
69
2.35.1
59
70
60
71
diff view generated by jsdifflib
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
Message-Id: <20200122164532.178040-6-mreitz@redhat.com>
2
3
reimplement qemu_img() in terms of qemu_tool() in preparation for doing
4
the same with qemu_io().
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
5
[mreitz: Added a note that NBD does not support resizing, which is why
9
Message-Id: <20220418211504.943969-7-jsnow@redhat.com>
6
the second case is expected to fail]
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
11
---
9
tests/qemu-iotests/259 | 62 ++++++++++++++++++++++++++++++++++++++
12
tests/qemu-iotests/iotests.py | 32 +++++++++++++++++++++-----------
10
tests/qemu-iotests/259.out | 14 +++++++++
13
1 file changed, 21 insertions(+), 11 deletions(-)
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
14
16
diff --git a/tests/qemu-iotests/259 b/tests/qemu-iotests/259
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
new file mode 100755
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX
17
--- a/tests/qemu-iotests/iotests.py
19
--- /dev/null
18
+++ b/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/259
19
@@ -XXX,XX +XXX,XX @@ def qemu_img_create_prepare_args(args: List[str]) -> List[str]:
21
@@ -XXX,XX +XXX,XX @@
20
22
+#!/usr/bin/env bash
21
return result
23
+#
22
24
+# Test generic image creation fallback (by using NBD)
23
-def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
25
+#
24
- ) -> 'subprocess.CompletedProcess[str]':
26
+# Copyright (C) 2019 Red Hat, Inc.
25
- """
27
+#
26
- Run qemu_img and return the status code and console output.
28
+# This program is free software; you can redistribute it and/or modify
27
29
+# it under the terms of the GNU General Public License as published by
28
- This function always prepends QEMU_IMG_OPTIONS and may further alter
30
+# the Free Software Foundation; either version 2 of the License, or
29
- the args for 'create' commands.
31
+# (at your option) any later version.
30
+def qemu_tool(*args: str, check: bool = True, combine_stdio: bool = True
32
+#
31
+ ) -> 'subprocess.CompletedProcess[str]':
33
+# This program is distributed in the hope that it will be useful,
32
+ """
34
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
33
+ Run a qemu tool and return its status code and console output.
35
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
36
+# GNU General Public License for more details.
35
- :param args: command-line arguments to qemu-img.
37
+#
36
+ :param args: full command line to run.
38
+# You should have received a copy of the GNU General Public License
37
:param check: Enforce a return code of zero.
39
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
38
:param combine_stdio: set to False to keep stdout/stderr separated.
40
+#
39
40
@@ -XXX,XX +XXX,XX @@ def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
41
properties. If streams are not combined, it will also have a
42
stderr property.
43
"""
44
- full_args = qemu_img_args + qemu_img_create_prepare_args(list(args))
45
-
46
subp = subprocess.run(
47
- full_args,
48
+ args,
49
stdout=subprocess.PIPE,
50
stderr=subprocess.STDOUT if combine_stdio else subprocess.PIPE,
51
universal_newlines=True,
52
@@ -XXX,XX +XXX,XX @@ def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
53
54
if check and subp.returncode or (subp.returncode < 0):
55
raise VerboseProcessError(
56
- subp.returncode, full_args,
57
+ subp.returncode, args,
58
output=subp.stdout,
59
stderr=subp.stderr,
60
)
61
@@ -XXX,XX +XXX,XX @@ def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
62
return subp
63
64
65
+def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
66
+ ) -> 'subprocess.CompletedProcess[str]':
67
+ """
68
+ Run QEMU_IMG_PROG and return its status code and console output.
41
+
69
+
42
+# creator
70
+ This function always prepends QEMU_IMG_OPTIONS and may further alter
43
+owner=mreitz@redhat.com
71
+ the args for 'create' commands.
44
+
72
+
45
+seq=$(basename $0)
73
+ See `qemu_tool()` for greater detail.
46
+echo "QA output created by $seq"
74
+ """
47
+
75
+ full_args = qemu_img_args + qemu_img_create_prepare_args(list(args))
48
+status=1    # failure is the default!
76
+ return qemu_tool(*full_args, check=check, combine_stdio=combine_stdio)
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
+
77
+
64
+
78
+
65
+_make_test_img 64M
79
def ordered_qmp(qmsg, conv_keys=True):
66
+
80
# Dictionaries are not ordered prior to 3.6, therefore:
67
+echo
81
if isinstance(qmsg, list):
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
--
82
--
117
2.24.1
83
2.35.1
118
119
diff view generated by jsdifflib
1
From: Daniel P. Berrangé <berrange@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
When initializing the LUKS header the size with default encryption
3
Rework qemu_io() to be analogous to qemu_img(); a function that requires
4
parameters will currently be 2068480 bytes. This is rounded up to
4
a return code of zero by default unless disabled explicitly.
5
a multiple of the cluster size, 2081792, with 64k sectors. If the
5
6
end of the header is not the same as the end of the cluster we fill
6
Tests that use qemu_io():
7
the extra space with zeros. This was forgetting that not even the
7
030 040 041 044 055 056 093 124 129 132 136 148 149 151 152 163 165 205
8
space allocated for the header will be fully initialized, as we
8
209 219 236 245 248 254 255 257 260 264 280 298 300 302 304
9
only write key material for the first key slot. The space left
9
image-fleecing migrate-bitmaps-postcopy-test migrate-bitmaps-test
10
for the other 7 slots is never written to.
10
migrate-during-backup migration-permissions
11
11
12
An optimization to the ref count checking code:
12
Test that use qemu_io_log():
13
13
242 245 255 274 303 307 nbd-reconnect-on-open
14
commit a5fff8d4b4d928311a5005efa12d0991fe3b66f9 (refs/bisect/bad)
14
15
Author: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Copy-pastables for testing/verification:
16
Date: Wed Feb 27 16:14:30 2019 +0300
16
17
17
./check -qcow2 030 040 041 044 055 056 124 129 132 151 152 163 165 209 \
18
qcow2-refcount: avoid eating RAM
18
219 236 242 245 248 254 255 257 260 264 274 \
19
19
280 298 300 302 303 304 307 image-fleecing \
20
made the assumption that every cluster which was allocated would
20
migrate-bitmaps-postcopy-test migrate-bitmaps-test \
21
have at least some data written to it. This was violated by way
21
migrate-during-backup nbd-reconnect-on-open
22
the LUKS header is only partially written, with much space simply
22
./check -raw 093 136 148 migration-permissions
23
reserved for future use.
23
./check -nbd 205
24
24
25
Depending on the cluster size this problem was masked by the
25
# ./configure configure --disable-gnutls --enable-gcrypt
26
logic which wrote zeros between the end of the LUKS header and
26
# this ALSO requires passwordless sudo.
27
the end of the cluster.
27
./check -luks 149
28
28
29
$ qemu-img create --object secret,id=cluster_encrypt0,data=123456 \
29
# Just the tests that were edited in this commit:
30
-f qcow2 -o cluster_size=2k,encrypt.iter-time=1,\
30
./check -qcow2 030 040 242 245
31
encrypt.format=luks,encrypt.key-secret=cluster_encrypt0 \
31
./check -raw migration-permissions
32
cluster_size_check.qcow2 100M
32
./check -nbd 205
33
Formatting 'cluster_size_check.qcow2', fmt=qcow2 size=104857600
33
./check -luks 149
34
encrypt.format=luks encrypt.key-secret=cluster_encrypt0
34
35
encrypt.iter-time=1 cluster_size=2048 lazy_refcounts=off refcount_bits=16
35
Signed-off-by: John Snow <jsnow@redhat.com>
36
36
Message-Id: <20220418211504.943969-8-jsnow@redhat.com>
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>
37
Reviewed-by: Eric Blake <eblake@redhat.com>
69
Signed-off-by: Max Reitz <mreitz@redhat.com>
38
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
70
---
39
---
71
block/qcow2.c | 11 +++--
40
tests/qemu-iotests/030 | 85 +++++++++++--------
72
tests/qemu-iotests/284 | 97 ++++++++++++++++++++++++++++++++++++++
41
tests/qemu-iotests/149 | 6 +-
73
tests/qemu-iotests/284.out | 62 ++++++++++++++++++++++++
42
tests/qemu-iotests/205 | 4 +-
74
tests/qemu-iotests/group | 1 +
43
tests/qemu-iotests/245 | 17 ++--
75
4 files changed, 167 insertions(+), 4 deletions(-)
44
tests/qemu-iotests/iotests.py | 19 +++--
76
create mode 100755 tests/qemu-iotests/284
45
.../qemu-iotests/tests/migration-permissions | 4 +-
77
create mode 100644 tests/qemu-iotests/284.out
46
6 files changed, 81 insertions(+), 54 deletions(-)
78
47
79
diff --git a/block/qcow2.c b/block/qcow2.c
48
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
49
index XXXXXXX..XXXXXXX 100755
50
--- a/tests/qemu-iotests/030
51
+++ b/tests/qemu-iotests/030
52
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
53
self.assert_no_active_block_jobs()
54
self.vm.shutdown()
55
56
- self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
57
- qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
58
- 'image file map does not match backing file after streaming')
59
+ self.assertEqual(
60
+ qemu_io('-f', 'raw', '-c', 'map', backing_img).stdout,
61
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img).stdout,
62
+ 'image file map does not match backing file after streaming')
63
64
def test_stream_intermediate(self):
65
self.assert_no_active_block_jobs()
66
67
- self.assertNotEqual(qemu_io('-f', 'raw', '-rU', '-c', 'map', backing_img),
68
- qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', mid_img),
69
- 'image file map matches backing file before streaming')
70
+ self.assertNotEqual(
71
+ qemu_io('-f', 'raw', '-rU', '-c', 'map', backing_img).stdout,
72
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', mid_img).stdout,
73
+ 'image file map matches backing file before streaming')
74
75
result = self.vm.qmp('block-stream', device='mid', job_id='stream-mid')
76
self.assert_qmp(result, 'return', {})
77
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
78
self.assert_no_active_block_jobs()
79
self.vm.shutdown()
80
81
- self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
82
- qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
83
- 'image file map does not match backing file after streaming')
84
+ self.assertEqual(
85
+ qemu_io('-f', 'raw', '-c', 'map', backing_img).stdout,
86
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img).stdout,
87
+ 'image file map does not match backing file after streaming')
88
89
def test_stream_pause(self):
90
self.assert_no_active_block_jobs()
91
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
92
self.assert_no_active_block_jobs()
93
self.vm.shutdown()
94
95
- self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
96
- qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
97
- 'image file map does not match backing file after streaming')
98
+ self.assertEqual(
99
+ qemu_io('-f', 'raw', '-c', 'map', backing_img).stdout,
100
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img).stdout,
101
+ 'image file map does not match backing file after streaming')
102
103
def test_stream_no_op(self):
104
self.assert_no_active_block_jobs()
105
106
# The image map is empty before the operation
107
- empty_map = qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', test_img)
108
+ empty_map = qemu_io(
109
+ '-f', iotests.imgfmt, '-rU', '-c', 'map', test_img).stdout
110
111
# This is a no-op: no data should ever be copied from the base image
112
result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
113
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
114
self.assert_no_active_block_jobs()
115
self.vm.shutdown()
116
117
- self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
118
- empty_map, 'image file map changed after a no-op')
119
+ self.assertEqual(
120
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img).stdout,
121
+ empty_map, 'image file map changed after a no-op')
122
123
def test_stream_partial(self):
124
self.assert_no_active_block_jobs()
125
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
126
self.assert_no_active_block_jobs()
127
self.vm.shutdown()
128
129
- self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
130
- qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
131
- 'image file map does not match backing file after streaming')
132
+ self.assertEqual(
133
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img).stdout,
134
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img).stdout,
135
+ 'image file map does not match backing file after streaming')
136
137
def test_device_not_found(self):
138
result = self.vm.qmp('block-stream', device='nonexistent')
139
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
140
141
# Check that the maps don't match before the streaming operations
142
for i in range(2, self.num_imgs, 2):
143
- self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i]),
144
- qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i-1]),
145
- 'image file map matches backing file before streaming')
146
+ self.assertNotEqual(
147
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i]).stdout,
148
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i-1]).stdout,
149
+ 'image file map matches backing file before streaming')
150
151
# Create all streaming jobs
152
pending_jobs = []
153
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
154
155
# Check that all maps match now
156
for i in range(2, self.num_imgs, 2):
157
- self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i]),
158
- qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i-1]),
159
- 'image file map does not match backing file after streaming')
160
+ self.assertEqual(
161
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i]).stdout,
162
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i-1]).stdout,
163
+ 'image file map does not match backing file after streaming')
164
165
# Test that it's not possible to perform two block-stream
166
# operations if there are nodes involved in both.
167
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
168
def test_stream_base_node_name(self):
169
self.assert_no_active_block_jobs()
170
171
- self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[4]),
172
- qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[3]),
173
- 'image file map matches backing file before streaming')
174
+ self.assertNotEqual(
175
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[4]).stdout,
176
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[3]).stdout,
177
+ 'image file map matches backing file before streaming')
178
179
# Error: the base node does not exist
180
result = self.vm.qmp('block-stream', device='node4', base_node='none', job_id='stream')
181
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
182
self.assert_no_active_block_jobs()
183
self.vm.shutdown()
184
185
- self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[4]),
186
- qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[3]),
187
- 'image file map matches backing file after streaming')
188
+ self.assertEqual(
189
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[4]).stdout,
190
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[3]).stdout,
191
+ 'image file map matches backing file after streaming')
192
193
class TestQuorum(iotests.QMPTestCase):
194
num_children = 3
195
@@ -XXX,XX +XXX,XX @@ class TestQuorum(iotests.QMPTestCase):
196
os.remove(img)
197
198
def test_stream_quorum(self):
199
- self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.children[0]),
200
- qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.backing[0]),
201
- 'image file map matches backing file before streaming')
202
+ self.assertNotEqual(
203
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.children[0]).stdout,
204
+ qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.backing[0]).stdout,
205
+ 'image file map matches backing file before streaming')
206
207
self.assert_no_active_block_jobs()
208
209
@@ -XXX,XX +XXX,XX @@ class TestQuorum(iotests.QMPTestCase):
210
self.assert_no_active_block_jobs()
211
self.vm.shutdown()
212
213
- self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.children[0]),
214
- qemu_io('-f', iotests.imgfmt, '-c', 'map', self.backing[0]),
215
- 'image file map does not match backing file after streaming')
216
+ self.assertEqual(
217
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', self.children[0]).stdout,
218
+ qemu_io('-f', iotests.imgfmt, '-c', 'map', self.backing[0]).stdout,
219
+ 'image file map does not match backing file after streaming')
220
221
class TestSmallerBackingFile(iotests.QMPTestCase):
222
backing_len = 1 * 1024 * 1024 # MB
223
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
224
index XXXXXXX..XXXXXXX 100755
225
--- a/tests/qemu-iotests/149
226
+++ b/tests/qemu-iotests/149
227
@@ -XXX,XX +XXX,XX @@ def qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False):
228
args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
229
args.extend(qemu_io_image_args(config, dev))
230
iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
231
- iotests.log(check_cipher_support(config, iotests.qemu_io(*args)),
232
+ output = iotests.qemu_io(*args, check=False).stdout
233
+ iotests.log(check_cipher_support(config, output),
234
filters=[iotests.filter_test_dir, iotests.filter_qemu_io])
235
236
237
@@ -XXX,XX +XXX,XX @@ def qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False):
238
args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
239
args.extend(qemu_io_image_args(config, dev))
240
iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
241
- iotests.log(check_cipher_support(config, iotests.qemu_io(*args)),
242
+ output = iotests.qemu_io(*args, check=False).stdout
243
+ iotests.log(check_cipher_support(config, output),
244
filters=[iotests.filter_test_dir, iotests.filter_qemu_io])
245
246
247
diff --git a/tests/qemu-iotests/205 b/tests/qemu-iotests/205
248
index XXXXXXX..XXXXXXX 100755
249
--- a/tests/qemu-iotests/205
250
+++ b/tests/qemu-iotests/205
251
@@ -XXX,XX +XXX,XX @@ class TestNbdServerRemove(iotests.QMPTestCase):
252
253
def do_test_connect_after_remove(self, mode=None):
254
args = ('-r', '-f', 'raw', '-c', 'read 0 512', nbd_uri)
255
- self.assertReadOk(qemu_io(*args))
256
+ self.assertReadOk(qemu_io(*args).stdout)
257
258
result = self.remove_export('exp', mode)
259
self.assert_qmp(result, 'return', {})
260
261
self.assertExportNotFound('exp')
262
- self.assertConnectFailed(qemu_io(*args))
263
+ self.assertConnectFailed(qemu_io(*args, check=False).stdout)
264
265
def test_connect_after_remove_default(self):
266
self.do_test_connect_after_remove()
267
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
268
index XXXXXXX..XXXXXXX 100755
269
--- a/tests/qemu-iotests/245
270
+++ b/tests/qemu-iotests/245
271
@@ -XXX,XX +XXX,XX @@
272
# along with this program. If not, see <http://www.gnu.org/licenses/>.
273
#
274
275
+import copy
276
+import json
277
import os
278
import re
279
+from subprocess import CalledProcessError
280
+
281
import iotests
282
-import copy
283
-import json
284
from iotests import qemu_img, qemu_io
285
286
hd_path = [
287
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
288
289
# Reopen an image several times changing some of its options
290
def test_reopen(self):
291
- # Check whether the filesystem supports O_DIRECT
292
- if 'O_DIRECT' in qemu_io('-f', 'raw', '-t', 'none', '-c', 'quit', hd_path[0]):
293
- supports_direct = False
294
- else:
295
+ try:
296
+ qemu_io('-f', 'raw', '-t', 'none', '-c', 'quit', hd_path[0])
297
supports_direct = True
298
+ except CalledProcessError as exc:
299
+ if 'O_DIRECT' in exc.stdout:
300
+ supports_direct = False
301
+ else:
302
+ raise
303
304
# Open the hd1 image passing all backing options
305
opts = hd_opts(1)
306
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
80
index XXXXXXX..XXXXXXX 100644
307
index XXXXXXX..XXXXXXX 100644
81
--- a/block/qcow2.c
308
--- a/tests/qemu-iotests/iotests.py
82
+++ b/block/qcow2.c
309
+++ b/tests/qemu-iotests/iotests.py
83
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
310
@@ -XXX,XX +XXX,XX @@ def qemu_io_wrap_args(args: Sequence[str]) -> List[str]:
84
s->crypto_header.length = headerlen;
311
def qemu_io_popen(*args):
85
s->crypto_header.offset = ret;
312
return qemu_tool_popen(qemu_io_wrap_args(args))
86
313
87
- /* Zero fill remaining space in cluster so it has predictable
314
-def qemu_io(*args):
88
- * content in case of future spec changes */
315
- '''Run qemu-io and return the stdout data'''
89
+ /*
316
- return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))[0]
90
+ * Zero fill all space in cluster so it has predictable
317
+def qemu_io(*args: str, check: bool = True, combine_stdio: bool = True
91
+ * content, as we may not initialize some regions of the
318
+ ) -> 'subprocess.CompletedProcess[str]':
92
+ * header (eg only 1 out of 8 key slots will be initialized)
319
+ """
93
+ */
320
+ Run QEMU_IO_PROG and return the status code and console output.
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
+
321
+
130
+# creator
322
+ This function always prepends either QEMU_IO_OPTIONS or
131
+owner=berrange@redhat.com
323
+ QEMU_IO_OPTIONS_NO_FMT.
132
+
324
+ """
133
+seq=`basename $0`
325
+ return qemu_tool(*qemu_io_wrap_args(args),
134
+echo "QA output created by $seq"
326
+ check=check, combine_stdio=combine_stdio)
135
+
327
136
+status=1 # failure is the default!
328
def qemu_io_pipe_and_status(*args):
137
+
329
return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))
138
+_cleanup()
330
139
+{
331
-def qemu_io_log(*args):
140
+ _cleanup_test_img
332
- result = qemu_io(*args)
141
+}
333
- log(result, filters=[filter_testfiles, filter_qemu_io])
142
+trap "_cleanup; exit \$status" 0 1 2 3 15
334
+def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
143
+
335
+ result = qemu_io(*args, check=False)
144
+# get standard environment, filters and checks
336
+ log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
145
+. ./common.rc
337
return result
146
+. ./common.filter
338
147
+
339
def qemu_io_silent(*args):
148
+_supported_fmt qcow2
340
diff --git a/tests/qemu-iotests/tests/migration-permissions b/tests/qemu-iotests/tests/migration-permissions
149
+_supported_proto generic
341
index XXXXXXX..XXXXXXX 100755
150
+_supported_os Linux
342
--- a/tests/qemu-iotests/tests/migration-permissions
151
+
343
+++ b/tests/qemu-iotests/tests/migration-permissions
152
+
344
@@ -XXX,XX +XXX,XX @@ class TestMigrationPermissions(iotests.QMPTestCase):
153
+size=1M
345
def test_post_migration_permissions(self):
154
+
346
# Try to access the image R/W, which should fail because virtio-blk
155
+SECRET="secret,id=sec0,data=astrochicken"
347
# has not been configured with share-rw=on
156
+
348
- log = qemu_io('-f', imgfmt, '-c', 'quit', test_img)
157
+IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
349
+ log = qemu_io('-f', imgfmt, '-c', 'quit', test_img, check=False).stdout
158
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
350
if not log.strip():
159
+
351
print('ERROR (pre-migration): qemu-io should not be able to '
160
+_run_test()
352
'access this image, but it reported no error')
161
+{
353
@@ -XXX,XX +XXX,XX @@ class TestMigrationPermissions(iotests.QMPTestCase):
162
+ IMGOPTSSYNTAX=true
354
163
+ OLD_TEST_IMG="$TEST_IMG"
355
# Try the same qemu-io access again, verifying that the WRITE
164
+ TEST_IMG="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
356
# permission remains unshared
165
+ QEMU_IMG_EXTRA_ARGS="--image-opts --object $SECRET"
357
- log = qemu_io('-f', imgfmt, '-c', 'quit', test_img)
166
+
358
+ log = qemu_io('-f', imgfmt, '-c', 'quit', test_img, check=False).stdout
167
+ echo
359
if not log.strip():
168
+ echo "== cluster size $csize"
360
print('ERROR (post-migration): qemu-io should not be able to '
169
+ echo "== checking image refcounts =="
361
'access this image, but it reported no error')
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
--
362
--
285
2.24.1
363
2.35.1
286
287
diff view generated by jsdifflib
1
8dff69b94 added an aio parameter to the drive parameter but forgot to
1
From: John Snow <jsnow@redhat.com>
2
add a comma before, thus breaking the test. Fix it again.
3
2
4
Fixes: 8dff69b9415b4287e900358744b732195e1ab2e2
3
Modify this test to use assertRaises for its negative testing of
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
qemu_io. If the exception raised does not match the one we tell it to
6
Message-Id: <20200206130812.612960-1-mreitz@redhat.com>
5
expect, we get *that* exception unhandled. If we get no exception, we
6
get a unittest assertion failure and the provided emsg printed to
7
screen.
8
9
If we get the CalledProcessError exception but the output is not what we
10
expect, we re-raise the original CalledProcessError.
11
12
Tidy.
13
14
(Note: Yes, you can reference "with" objects after that block ends; it
15
just means that ctx.__exit__(...) will have been called on it. It does
16
not *actually* go out of scope. unittests expects you to want to inspect
17
the Exception object, so they leave it defined post-exit.)
18
19
Signed-off-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
20
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Tested-by: Eric Blake <eblake@redhat.com>
21
Tested-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
23
Message-Id: <20220418211504.943969-9-jsnow@redhat.com>
24
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
25
---
11
tests/qemu-iotests/147 | 2 +-
26
.../qemu-iotests/tests/migration-permissions | 28 +++++++++----------
12
1 file changed, 1 insertion(+), 1 deletion(-)
27
1 file changed, 14 insertions(+), 14 deletions(-)
13
28
14
diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
29
diff --git a/tests/qemu-iotests/tests/migration-permissions b/tests/qemu-iotests/tests/migration-permissions
15
index XXXXXXX..XXXXXXX 100755
30
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/147
31
--- a/tests/qemu-iotests/tests/migration-permissions
17
+++ b/tests/qemu-iotests/147
32
+++ b/tests/qemu-iotests/tests/migration-permissions
18
@@ -XXX,XX +XXX,XX @@ class BuiltinNBD(NBDBlockdevAddBase):
33
@@ -XXX,XX +XXX,XX @@
19
self.server.add_drive_raw('if=none,id=nbd-export,' +
34
#
20
'file=%s,' % test_img +
35
21
'format=%s,' % imgfmt +
36
import os
22
- 'cache=%s' % cachemode +
37
+from subprocess import CalledProcessError
23
+ 'cache=%s,' % cachemode +
38
+
24
'aio=%s' % aiomode)
39
import iotests
25
self.server.launch()
40
from iotests import imgfmt, qemu_img_create, qemu_io
26
41
42
@@ -XXX,XX +XXX,XX @@ class TestMigrationPermissions(iotests.QMPTestCase):
43
def test_post_migration_permissions(self):
44
# Try to access the image R/W, which should fail because virtio-blk
45
# has not been configured with share-rw=on
46
- log = qemu_io('-f', imgfmt, '-c', 'quit', test_img, check=False).stdout
47
- if not log.strip():
48
- print('ERROR (pre-migration): qemu-io should not be able to '
49
- 'access this image, but it reported no error')
50
- else:
51
- # This is the expected output
52
- assert 'Is another process using the image' in log
53
+ emsg = ('ERROR (pre-migration): qemu-io should not be able to '
54
+ 'access this image, but it reported no error')
55
+ with self.assertRaises(CalledProcessError, msg=emsg) as ctx:
56
+ qemu_io('-f', imgfmt, '-c', 'quit', test_img)
57
+ if 'Is another process using the image' not in ctx.exception.stdout:
58
+ raise ctx.exception
59
60
# Now migrate the VM
61
self.vm_s.qmp('migrate', uri=f'unix:{mig_sock}')
62
@@ -XXX,XX +XXX,XX @@ class TestMigrationPermissions(iotests.QMPTestCase):
63
64
# Try the same qemu-io access again, verifying that the WRITE
65
# permission remains unshared
66
- log = qemu_io('-f', imgfmt, '-c', 'quit', test_img, check=False).stdout
67
- if not log.strip():
68
- print('ERROR (post-migration): qemu-io should not be able to '
69
- 'access this image, but it reported no error')
70
- else:
71
- # This is the expected output
72
- assert 'Is another process using the image' in log
73
+ emsg = ('ERROR (post-migration): qemu-io should not be able to '
74
+ 'access this image, but it reported no error')
75
+ with self.assertRaises(CalledProcessError, msg=emsg) as ctx:
76
+ qemu_io('-f', imgfmt, '-c', 'quit', test_img)
77
+ if 'Is another process using the image' not in ctx.exception.stdout:
78
+ raise ctx.exception
79
80
81
if __name__ == '__main__':
27
--
82
--
28
2.24.1
83
2.35.1
29
30
diff view generated by jsdifflib
1
The generic fallback implementation effectively does the same.
1
From: John Snow <jsnow@redhat.com>
2
2
3
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
3
This test expects failure ... but only sometimes. When? Why?
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
5
Message-Id: <20200122164532.178040-5-mreitz@redhat.com>
5
It's for reads of a region not defined by a bitmap. Adjust the test to
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
be more explicit about what it expects to fail and why.
7
8
Signed-off-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220418211504.943969-10-jsnow@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
---
13
---
8
block/iscsi.c | 56 ---------------------------------------------------
14
tests/qemu-iotests/tests/image-fleecing | 28 +++++++++++++++++--------
9
1 file changed, 56 deletions(-)
15
1 file changed, 19 insertions(+), 9 deletions(-)
10
16
11
diff --git a/block/iscsi.c b/block/iscsi.c
17
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100755
13
--- a/block/iscsi.c
19
--- a/tests/qemu-iotests/tests/image-fleecing
14
+++ b/block/iscsi.c
20
+++ b/tests/qemu-iotests/tests/image-fleecing
15
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
21
@@ -XXX,XX +XXX,XX @@
16
return 0;
22
#
17
}
23
# Creator/Owner: John Snow <jsnow@redhat.com>
18
24
19
-static int coroutine_fn iscsi_co_create_opts(const char *filename, QemuOpts *opts,
25
+from subprocess import CalledProcessError
20
- Error **errp)
26
+
21
-{
27
import iotests
22
- int ret = 0;
28
-from iotests import log, qemu_img, qemu_io, qemu_io_silent, \
23
- int64_t total_size = 0;
29
- qemu_io_pipe_and_status
24
- BlockDriverState *bs;
30
+from iotests import log, qemu_img, qemu_io, qemu_io_silent
25
- IscsiLun *iscsilun = NULL;
31
26
- QDict *bs_options;
32
iotests.script_initialize(
27
- Error *local_err = NULL;
33
supported_fmts=['qcow2'],
28
-
34
@@ -XXX,XX +XXX,XX @@ def do_test(vm, use_cbw, use_snapshot_access_filter, base_img_path,
29
- bs = bdrv_new();
35
for p in patterns + zeroes:
30
-
36
cmd = 'read -P%s %s %s' % p
31
- /* Read out options */
37
log(cmd)
32
- total_size = DIV_ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
38
- out, ret = qemu_io_pipe_and_status('-r', '-f', 'raw', '-c', cmd,
33
- BDRV_SECTOR_SIZE);
39
- nbd_uri)
34
- bs->opaque = g_new0(struct IscsiLun, 1);
40
- if ret != 0:
35
- iscsilun = bs->opaque;
41
- print(out)
36
-
42
+
37
- bs_options = qdict_new();
43
+ try:
38
- iscsi_parse_filename(filename, bs_options, &local_err);
44
+ qemu_io('-r', '-f', 'raw', '-c', cmd, nbd_uri)
39
- if (local_err) {
45
+ except CalledProcessError as exc:
40
- error_propagate(errp, local_err);
46
+ if bitmap and p in zeroes:
41
- ret = -EINVAL;
47
+ log(exc.stdout)
42
- } else {
48
+ else:
43
- ret = iscsi_open(bs, bs_options, 0, NULL);
49
+ raise
44
- }
50
45
- qobject_unref(bs_options);
51
log('')
46
-
52
log('--- Testing COW ---')
47
- if (ret != 0) {
53
@@ -XXX,XX +XXX,XX @@ def do_test(vm, use_cbw, use_snapshot_access_filter, base_img_path,
48
- goto out;
54
args += [target_img_path]
49
- }
55
else:
50
- iscsi_detach_aio_context(bs);
56
args += ['-f', 'raw', nbd_uri]
51
- if (iscsilun->type != TYPE_DISK) {
57
- out, ret = qemu_io_pipe_and_status(*args)
52
- ret = -ENODEV;
58
- if ret != 0:
53
- goto out;
59
- print(out)
54
- }
60
+
55
- if (bs->total_sectors < total_size) {
61
+ try:
56
- ret = -ENOSPC;
62
+ qemu_io(*args)
57
- goto out;
63
+ except CalledProcessError as exc:
58
- }
64
+ if bitmap and p in zeroes:
59
-
65
+ log(exc.stdout)
60
- ret = 0;
66
+ else:
61
-out:
67
+ raise
62
- if (iscsilun->iscsi != NULL) {
68
63
- iscsi_destroy_context(iscsilun->iscsi);
69
log('')
64
- }
70
log('--- Cleanup ---')
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
--
71
--
93
2.24.1
72
2.35.1
94
95
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
Commit d9df28e7b07 ("iotests: check whitelisted formats") added the
3
I know we just added it, sorry. This is done in favor of qemu_io() which
4
modern @iotests.skip_if_unsupported() to the functions in this test,
4
*also* returns the console output and status, but with more robust error
5
so we don't need the old explicit test here anymore.
5
handling on failure.
6
6
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Signed-off-by: John Snow <jsnow@redhat.com>
8
Message-Id: <20200129141751.32652-1-thuth@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
10
Message-Id: <20220418211504.943969-11-jsnow@redhat.com>
11
Tested-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
12
---
14
tests/qemu-iotests/139 | 3 ---
13
tests/qemu-iotests/iotests.py | 3 ---
15
1 file changed, 3 deletions(-)
14
1 file changed, 3 deletions(-)
16
15
17
diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
18
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/139
18
--- a/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/139
19
+++ b/tests/qemu-iotests/iotests.py
21
@@ -XXX,XX +XXX,XX @@ class TestBlockdevDel(iotests.QMPTestCase):
20
@@ -XXX,XX +XXX,XX @@ def qemu_io(*args: str, check: bool = True, combine_stdio: bool = True
22
21
return qemu_tool(*qemu_io_wrap_args(args),
23
@iotests.skip_if_unsupported(['quorum'])
22
check=check, combine_stdio=combine_stdio)
24
def testQuorum(self):
23
25
- if not iotests.supports_quorum():
24
-def qemu_io_pipe_and_status(*args):
26
- return
25
- return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))
27
-
26
-
28
self.addQuorum('quorum0', 'node0', 'node1')
27
def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
29
# We cannot remove the children of a Quorum device
28
result = qemu_io(*args, check=False)
30
self.delBlockDriverState('node0', expect_error = True)
29
log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
31
--
30
--
32
2.24.1
31
2.35.1
33
34
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: 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
1
The generic fallback implementation effectively does the same.
1
From: John Snow <jsnow@redhat.com>
2
2
3
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
3
Like qemu-img, qemu-io returning 0 should be the norm and not the
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
exception. Remove all calls to qemu_io_silent that just assert the
5
Message-Id: <20200122164532.178040-4-mreitz@redhat.com>
5
return code is zero (That's every last call, as it turns out), and
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
replace them with a normal qemu_io() call.
7
8
qemu_io_silent_check() appeared to have been unused already.
9
10
Signed-off-by: John Snow <jsnow@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
Message-Id: <20220418211504.943969-12-jsnow@redhat.com>
14
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
---
15
---
8
block/file-posix.c | 67 ----------------------------------------------
16
tests/qemu-iotests/216 | 12 +++++-----
9
1 file changed, 67 deletions(-)
17
tests/qemu-iotests/218 | 5 ++---
18
tests/qemu-iotests/224 | 4 ++--
19
tests/qemu-iotests/258 | 11 +++++-----
20
tests/qemu-iotests/298 | 17 ++++++--------
21
tests/qemu-iotests/310 | 22 +++++++++----------
22
tests/qemu-iotests/iotests.py | 16 --------------
23
tests/qemu-iotests/tests/image-fleecing | 4 ++--
24
.../tests/mirror-ready-cancel-error | 2 +-
25
.../qemu-iotests/tests/stream-error-on-reset | 4 ++--
26
10 files changed, 38 insertions(+), 59 deletions(-)
10
27
11
diff --git a/block/file-posix.c b/block/file-posix.c
28
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
29
index XXXXXXX..XXXXXXX 100755
30
--- a/tests/qemu-iotests/216
31
+++ b/tests/qemu-iotests/216
32
@@ -XXX,XX +XXX,XX @@
33
# Creator/Owner: Hanna Reitz <hreitz@redhat.com>
34
35
import iotests
36
-from iotests import log, qemu_img, qemu_io_silent
37
+from iotests import log, qemu_img, qemu_io
38
39
# Need backing file support
40
iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'],
41
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
42
log('')
43
44
qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M')
45
- assert qemu_io_silent(base_img_path, '-c', 'write -P 1 0M 1M') == 0
46
+ qemu_io(base_img_path, '-c', 'write -P 1 0M 1M')
47
qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
48
'-F', iotests.imgfmt, top_img_path)
49
- assert qemu_io_silent(top_img_path, '-c', 'write -P 2 1M 1M') == 0
50
+ qemu_io(top_img_path, '-c', 'write -P 2 1M 1M')
51
52
log('Done')
53
54
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
55
log('--- Checking COR result ---')
56
log('')
57
58
- assert qemu_io_silent(base_img_path, '-c', 'discard 0 64M') == 0
59
- assert qemu_io_silent(top_img_path, '-c', 'read -P 1 0M 1M') == 0
60
- assert qemu_io_silent(top_img_path, '-c', 'read -P 2 1M 1M') == 0
61
+ qemu_io(base_img_path, '-c', 'discard 0 64M')
62
+ qemu_io(top_img_path, '-c', 'read -P 1 0M 1M')
63
+ qemu_io(top_img_path, '-c', 'read -P 2 1M 1M')
64
65
log('Done')
66
diff --git a/tests/qemu-iotests/218 b/tests/qemu-iotests/218
67
index XXXXXXX..XXXXXXX 100755
68
--- a/tests/qemu-iotests/218
69
+++ b/tests/qemu-iotests/218
70
@@ -XXX,XX +XXX,XX @@
71
# Creator/Owner: Hanna Reitz <hreitz@redhat.com>
72
73
import iotests
74
-from iotests import log, qemu_img, qemu_io_silent
75
+from iotests import log, qemu_img, qemu_io
76
77
iotests.script_initialize(supported_fmts=['qcow2', 'raw'])
78
79
@@ -XXX,XX +XXX,XX @@ with iotests.VM() as vm, \
80
iotests.FilePath('src.img') as src_img_path:
81
82
qemu_img('create', '-f', iotests.imgfmt, src_img_path, '64M')
83
- assert qemu_io_silent('-f', iotests.imgfmt, src_img_path,
84
- '-c', 'write -P 42 0M 64M') == 0
85
+ qemu_io('-f', iotests.imgfmt, src_img_path, '-c', 'write -P 42 0M 64M')
86
87
vm.launch()
88
89
diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224
90
index XXXXXXX..XXXXXXX 100755
91
--- a/tests/qemu-iotests/224
92
+++ b/tests/qemu-iotests/224
93
@@ -XXX,XX +XXX,XX @@
94
# Creator/Owner: Hanna Reitz <hreitz@redhat.com>
95
96
import iotests
97
-from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
98
+from iotests import log, qemu_img, qemu_io, filter_qmp_testfiles, \
99
filter_qmp_imgfmt
100
import json
101
102
@@ -XXX,XX +XXX,XX @@ for filter_node_name in False, True:
103
'-F', iotests.imgfmt, top_img_path)
104
105
# Something to commit
106
- assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0
107
+ qemu_io(mid_img_path, '-c', 'write -P 1 0 1M')
108
109
vm.launch()
110
111
diff --git a/tests/qemu-iotests/258 b/tests/qemu-iotests/258
112
index XXXXXXX..XXXXXXX 100755
113
--- a/tests/qemu-iotests/258
114
+++ b/tests/qemu-iotests/258
115
@@ -XXX,XX +XXX,XX @@
116
# Creator/Owner: Hanna Reitz <hreitz@redhat.com>
117
118
import iotests
119
-from iotests import log, qemu_img, qemu_io_silent, \
120
+from iotests import log, qemu_img, qemu_io, \
121
filter_qmp_testfiles, filter_qmp_imgfmt
122
123
# Returns a node for blockdev-add
124
@@ -XXX,XX +XXX,XX @@ def test_concurrent_finish(write_to_stream_node):
125
if write_to_stream_node:
126
# This is what (most of the time) makes commit finish
127
# earlier and then pull in stream
128
- assert qemu_io_silent(node2_path,
129
- '-c', 'write %iK 64K' % (65536 - 192),
130
- '-c', 'write %iK 64K' % (65536 - 64)) == 0
131
+ qemu_io(node2_path,
132
+ '-c', 'write %iK 64K' % (65536 - 192),
133
+ '-c', 'write %iK 64K' % (65536 - 64))
134
135
stream_throttle='tg'
136
else:
137
# And this makes stream finish earlier
138
- assert qemu_io_silent(node1_path,
139
- '-c', 'write %iK 64K' % (65536 - 64)) == 0
140
+ qemu_io(node1_path, '-c', 'write %iK 64K' % (65536 - 64))
141
142
commit_throttle='tg'
143
144
diff --git a/tests/qemu-iotests/298 b/tests/qemu-iotests/298
145
index XXXXXXX..XXXXXXX 100755
146
--- a/tests/qemu-iotests/298
147
+++ b/tests/qemu-iotests/298
148
@@ -XXX,XX +XXX,XX @@ class TestTruncate(iotests.QMPTestCase):
149
os.remove(refdisk)
150
151
def do_test(self, prealloc_mode, new_size):
152
- ret = iotests.qemu_io_silent('--image-opts', '-c', 'write 0 10M', '-c',
153
- f'truncate -m {prealloc_mode} {new_size}',
154
- drive_opts)
155
- self.assertEqual(ret, 0)
156
-
157
- ret = iotests.qemu_io_silent('-f', iotests.imgfmt, '-c', 'write 0 10M',
158
- '-c',
159
- f'truncate -m {prealloc_mode} {new_size}',
160
- refdisk)
161
- self.assertEqual(ret, 0)
162
+ iotests.qemu_io('--image-opts', '-c', 'write 0 10M', '-c',
163
+ f'truncate -m {prealloc_mode} {new_size}',
164
+ drive_opts)
165
+
166
+ iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write 0 10M',
167
+ '-c', f'truncate -m {prealloc_mode} {new_size}',
168
+ refdisk)
169
170
stat = os.stat(disk)
171
refstat = os.stat(refdisk)
172
diff --git a/tests/qemu-iotests/310 b/tests/qemu-iotests/310
173
index XXXXXXX..XXXXXXX 100755
174
--- a/tests/qemu-iotests/310
175
+++ b/tests/qemu-iotests/310
176
@@ -XXX,XX +XXX,XX @@
177
#
178
179
import iotests
180
-from iotests import log, qemu_img, qemu_io_silent
181
+from iotests import log, qemu_img, qemu_io
182
183
# Need backing file support
184
iotests.script_initialize(supported_fmts=['qcow2'],
185
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
186
log('')
187
188
qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M')
189
- assert qemu_io_silent(base_img_path, '-c', 'write -P 1 0M 1M') == 0
190
- assert qemu_io_silent(base_img_path, '-c', 'write -P 1 3M 1M') == 0
191
+ qemu_io(base_img_path, '-c', 'write -P 1 0M 1M')
192
+ qemu_io(base_img_path, '-c', 'write -P 1 3M 1M')
193
qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
194
'-F', iotests.imgfmt, mid_img_path)
195
- assert qemu_io_silent(mid_img_path, '-c', 'write -P 3 2M 1M') == 0
196
- assert qemu_io_silent(mid_img_path, '-c', 'write -P 3 4M 1M') == 0
197
+ qemu_io(mid_img_path, '-c', 'write -P 3 2M 1M')
198
+ qemu_io(mid_img_path, '-c', 'write -P 3 4M 1M')
199
qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
200
'-F', iotests.imgfmt, top_img_path)
201
- assert qemu_io_silent(top_img_path, '-c', 'write -P 2 1M 1M') == 0
202
+ qemu_io(top_img_path, '-c', 'write -P 2 1M 1M')
203
204
# 0 1 2 3 4
205
# top 2
206
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
207
# Detach backing to check that we can read the data from the top level now
208
qemu_img('rebase', '-u', '-b', '', '-f', iotests.imgfmt, top_img_path)
209
210
- assert qemu_io_silent(top_img_path, '-c', 'read -P 0 0 1M') == 0
211
- assert qemu_io_silent(top_img_path, '-c', 'read -P 2 1M 1M') == 0
212
- assert qemu_io_silent(top_img_path, '-c', 'read -P 3 2M 1M') == 0
213
- assert qemu_io_silent(top_img_path, '-c', 'read -P 0 3M 1M') == 0
214
- assert qemu_io_silent(top_img_path, '-c', 'read -P 3 4M 1M') == 0
215
+ qemu_io(top_img_path, '-c', 'read -P 0 0 1M')
216
+ qemu_io(top_img_path, '-c', 'read -P 2 1M 1M')
217
+ qemu_io(top_img_path, '-c', 'read -P 3 2M 1M')
218
+ qemu_io(top_img_path, '-c', 'read -P 0 3M 1M')
219
+ qemu_io(top_img_path, '-c', 'read -P 3 4M 1M')
220
221
log('Done')
222
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
index XXXXXXX..XXXXXXX 100644
223
index XXXXXXX..XXXXXXX 100644
13
--- a/block/file-posix.c
224
--- a/tests/qemu-iotests/iotests.py
14
+++ b/block/file-posix.c
225
+++ b/tests/qemu-iotests/iotests.py
15
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
226
@@ -XXX,XX +XXX,XX @@ def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
16
return raw_do_pwrite_zeroes(bs, offset, bytes, flags, true);
227
log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
17
}
228
return result
18
229
19
-static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts,
230
-def qemu_io_silent(*args):
20
- Error **errp)
231
- '''Run qemu-io and return the exit code, suppressing stdout'''
21
-{
232
- args = qemu_io_wrap_args(args)
22
- int fd;
233
- result = subprocess.run(args, stdout=subprocess.DEVNULL, check=False)
23
- int ret = 0;
234
- if result.returncode < 0:
24
- struct stat stat_buf;
235
- sys.stderr.write('qemu-io received signal %i: %s\n' %
25
- int64_t total_size = 0;
236
- (-result.returncode, ' '.join(args)))
26
- bool has_prefix;
237
- return result.returncode
27
-
238
-
28
- /* This function is used by both protocol block drivers and therefore either
239
-def qemu_io_silent_check(*args):
29
- * of these prefixes may be given.
240
- '''Run qemu-io and return the true if subprocess returned 0'''
30
- * The return value has to be stored somewhere, otherwise this is an error
241
- args = qemu_io_wrap_args(args)
31
- * due to -Werror=unused-value. */
242
- result = subprocess.run(args, stdout=subprocess.DEVNULL,
32
- has_prefix =
243
- stderr=subprocess.STDOUT, check=False)
33
- strstart(filename, "host_device:", &filename) ||
244
- return result.returncode == 0
34
- strstart(filename, "host_cdrom:" , &filename);
35
-
245
-
36
- (void)has_prefix;
246
class QemuIoInteractive:
37
-
247
def __init__(self, *args):
38
- ret = raw_normalize_devicepath(&filename, errp);
248
self.args = qemu_io_wrap_args(args)
39
- if (ret < 0) {
249
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
40
- return ret;
250
index XXXXXXX..XXXXXXX 100755
41
- }
251
--- a/tests/qemu-iotests/tests/image-fleecing
42
-
252
+++ b/tests/qemu-iotests/tests/image-fleecing
43
- /* Read out options */
253
@@ -XXX,XX +XXX,XX @@
44
- total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
254
from subprocess import CalledProcessError
45
- BDRV_SECTOR_SIZE);
255
46
-
256
import iotests
47
- fd = qemu_open(filename, O_WRONLY | O_BINARY);
257
-from iotests import log, qemu_img, qemu_io, qemu_io_silent
48
- if (fd < 0) {
258
+from iotests import log, qemu_img, qemu_io
49
- ret = -errno;
259
50
- error_setg_errno(errp, -ret, "Could not open device");
260
iotests.script_initialize(
51
- return ret;
261
supported_fmts=['qcow2'],
52
- }
262
@@ -XXX,XX +XXX,XX @@ def do_test(vm, use_cbw, use_snapshot_access_filter, base_img_path,
53
-
263
for p in overwrite + remainder:
54
- if (fstat(fd, &stat_buf) < 0) {
264
cmd = 'read -P%s %s %s' % p
55
- ret = -errno;
265
log(cmd)
56
- error_setg_errno(errp, -ret, "Could not stat device");
266
- assert qemu_io_silent(base_img_path, '-c', cmd) == 0
57
- } else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode)) {
267
+ qemu_io(base_img_path, '-c', cmd)
58
- error_setg(errp,
268
59
- "The given file is neither a block nor a character device");
269
log('')
60
- ret = -ENODEV;
270
log('Done')
61
- } else if (lseek(fd, 0, SEEK_END) < total_size) {
271
diff --git a/tests/qemu-iotests/tests/mirror-ready-cancel-error b/tests/qemu-iotests/tests/mirror-ready-cancel-error
62
- error_setg(errp, "Device is too small");
272
index XXXXXXX..XXXXXXX 100755
63
- ret = -ENOSPC;
273
--- a/tests/qemu-iotests/tests/mirror-ready-cancel-error
64
- }
274
+++ b/tests/qemu-iotests/tests/mirror-ready-cancel-error
65
-
275
@@ -XXX,XX +XXX,XX @@ class TestMirrorReadyCancelError(iotests.QMPTestCase):
66
- if (!ret && total_size) {
276
# Ensure that mirror will copy something before READY so the
67
- uint8_t buf[BDRV_SECTOR_SIZE] = { 0 };
277
# target format layer will forward the pre-READY flush to its
68
- int64_t zero_size = MIN(BDRV_SECTOR_SIZE, total_size);
278
# file child
69
- if (lseek(fd, 0, SEEK_SET) == -1) {
279
- assert iotests.qemu_io_silent('-c', 'write -P 1 0 64k', source) == 0
70
- ret = -errno;
280
+ iotests.qemu_io('-c', 'write -P 1 0 64k', source)
71
- } else {
281
72
- ret = qemu_write_full(fd, buf, zero_size);
282
self.vm = iotests.VM()
73
- ret = ret == zero_size ? 0 : -errno;
283
self.vm.launch()
74
- }
284
diff --git a/tests/qemu-iotests/tests/stream-error-on-reset b/tests/qemu-iotests/tests/stream-error-on-reset
75
- }
285
index XXXXXXX..XXXXXXX 100755
76
- qemu_close(fd);
286
--- a/tests/qemu-iotests/tests/stream-error-on-reset
77
- return ret;
287
+++ b/tests/qemu-iotests/tests/stream-error-on-reset
78
-}
288
@@ -XXX,XX +XXX,XX @@
79
-
289
80
static BlockDriver bdrv_host_device = {
290
import os
81
.format_name = "host_device",
291
import iotests
82
.protocol_name = "host_device",
292
-from iotests import imgfmt, qemu_img_create, qemu_io_silent, QMPTestCase
83
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
293
+from iotests import imgfmt, qemu_img_create, qemu_io, QMPTestCase
84
.bdrv_reopen_prepare = raw_reopen_prepare,
294
85
.bdrv_reopen_commit = raw_reopen_commit,
295
86
.bdrv_reopen_abort = raw_reopen_abort,
296
image_size = 1 * 1024 * 1024
87
- .bdrv_co_create_opts = hdev_co_create_opts,
297
@@ -XXX,XX +XXX,XX @@ class TestStreamErrorOnReset(QMPTestCase):
88
- .create_opts = &raw_create_opts,
298
- top image is attached to a virtio-scsi device
89
.mutable_opts = mutable_opts,
299
"""
90
.bdrv_co_invalidate_cache = raw_co_invalidate_cache,
300
qemu_img_create('-f', imgfmt, base, str(image_size))
91
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,
301
- assert qemu_io_silent('-c', f'write 0 {data_size}', base) == 0
92
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
302
+ qemu_io('-c', f'write 0 {data_size}', base)
93
.bdrv_reopen_prepare = raw_reopen_prepare,
303
qemu_img_create('-f', imgfmt, top, str(image_size))
94
.bdrv_reopen_commit = raw_reopen_commit,
304
95
.bdrv_reopen_abort = raw_reopen_abort,
305
self.vm = iotests.VM()
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
--
306
--
111
2.24.1
307
2.35.1
112
113
diff view generated by jsdifflib
1
First, driver=qcow2 will not work so well with non-qcow2 formats (and
1
From: John Snow <jsnow@redhat.com>
2
this test claims to support qcow, qed, and vmdk).
3
2
4
Second, vmdk will always report the backing file format to be vmdk.
3
Just like qemu_img_log(), upgrade qemu_io_log() to enforce a return code
5
Filter that out so the output looks like for all other formats.
4
of zero by default.
6
5
7
Third, the flat vmdk subformats do not support backing files, so they
6
Tests that use qemu_io_log(): 242 245 255 274 303 307 nbd-reconnect-on-open
8
will not work with this test.
9
7
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: John Snow <jsnow@redhat.com>
11
Message-Id: <20191219144243.1763246-1-mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Tested-by: Thomas Huth <thuth@redhat.com>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20220418211504.943969-13-jsnow@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
---
13
---
15
tests/qemu-iotests/279 | 7 +++++--
14
tests/qemu-iotests/iotests.py | 5 +++--
16
1 file changed, 5 insertions(+), 2 deletions(-)
15
tests/qemu-iotests/tests/nbd-reconnect-on-open | 2 +-
16
2 files changed, 4 insertions(+), 3 deletions(-)
17
17
18
diff --git a/tests/qemu-iotests/279 b/tests/qemu-iotests/279
18
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/iotests.py
21
+++ b/tests/qemu-iotests/iotests.py
22
@@ -XXX,XX +XXX,XX @@ def qemu_io(*args: str, check: bool = True, combine_stdio: bool = True
23
return qemu_tool(*qemu_io_wrap_args(args),
24
check=check, combine_stdio=combine_stdio)
25
26
-def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
27
- result = qemu_io(*args, check=False)
28
+def qemu_io_log(*args: str, check: bool = True
29
+ ) -> 'subprocess.CompletedProcess[str]':
30
+ result = qemu_io(*args, check=check)
31
log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
32
return result
33
34
diff --git a/tests/qemu-iotests/tests/nbd-reconnect-on-open b/tests/qemu-iotests/tests/nbd-reconnect-on-open
19
index XXXXXXX..XXXXXXX 100755
35
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/279
36
--- a/tests/qemu-iotests/tests/nbd-reconnect-on-open
21
+++ b/tests/qemu-iotests/279
37
+++ b/tests/qemu-iotests/tests/nbd-reconnect-on-open
22
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
38
@@ -XXX,XX +XXX,XX @@ def check_fail_to_connect(open_timeout):
23
_supported_fmt qcow qcow2 vmdk qed
39
log(f'Check fail to connect with {open_timeout} seconds of timeout')
24
_supported_proto file
40
25
_supported_os Linux
41
start_t = time.time()
26
+_unsupported_imgopts "subformat=monolithicFlat" \
42
- qemu_io_log(*create_args(open_timeout))
27
+ "subformat=twoGbMaxExtentFlat" \
43
+ qemu_io_log(*create_args(open_timeout), check=False)
28
44
delta_t = time.time() - start_t
29
TEST_IMG="$TEST_IMG.base" _make_test_img 64M
45
30
TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base"
46
max_delta = open_timeout + 0.2
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
--
47
2.24.1
48
2.35.1
48
49
diff view generated by jsdifflib
1
s.target_has_backing does not reflect whether the target BDS has a
1
FUSE exports' allow-other option defaults to "auto", which means that it
2
backing file; it only tells whether we should use a backing file during
2
will try passing allow_other as a mount option, and fall back to not
3
conversion (specified by -B).
3
using it when an error occurs. We make no effort to hide fusermount's
4
error message (because it would be difficult, and because users might
5
want to know about the fallback occurring), and so when allow_other does
6
not work (primarily when /etc/fuse.conf does not contain
7
user_allow_other), this error message will appear and break the
8
reference output.
4
9
5
As such, if you use convert -n, the target does not necessarily actually
10
We do not need allow_other here, though, so we can just pass
6
have a backing file, and then dereferencing out_bs->backing fails here.
11
allow-other=off to fix that.
7
12
8
When converting to an existing file, we should set
13
Reported-by: Markus Armbruster <armbru@redhat.com>
9
target_backing_sectors to a negative value, because first, as the
14
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
comment explains, this value is only used for optimization, so it is
15
Message-Id: <20220421142435.569600-1-hreitz@redhat.com>
11
always fine to do that.
16
Tested-by: Markus Armbruster <armbru@redhat.com>
12
17
Tested-by: Eric Blake <eblake@redhat.com>
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
---
18
---
26
qemu-img.c | 2 +-
19
tests/qemu-iotests/108 | 2 +-
27
1 file changed, 1 insertion(+), 1 deletion(-)
20
1 file changed, 1 insertion(+), 1 deletion(-)
28
21
29
diff --git a/qemu-img.c b/qemu-img.c
22
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
30
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100755
31
--- a/qemu-img.c
24
--- a/tests/qemu-iotests/108
32
+++ b/qemu-img.c
25
+++ b/tests/qemu-iotests/108
33
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
26
@@ -XXX,XX +XXX,XX @@ else
34
}
27
35
}
28
$QSD \
36
29
--blockdev file,node-name=export-node,filename="$TEST_IMG" \
37
- if (s.target_has_backing) {
30
- --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=off \
38
+ if (s.target_has_backing && s.target_is_new) {
31
+ --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=off,allow-other=off \
39
/* Errors are treated as "backing length unknown" (which means
32
--pidfile "$TEST_DIR/qsd.pid" \
40
* s.target_backing_sectors has to be negative, which it will
33
--daemonize
41
* be automatically). The backing file length is used only
34
fi
42
--
35
--
43
2.24.1
36
2.35.1
44
45
diff view generated by jsdifflib