1
The following changes since commit a0def594286d9110a6035e02eef558cf3cf5d847:
1
The following changes since commit 754f756cc4c6d9d14b7230c62b5bb20f9d655888:
2
2
3
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging (2017-01-30 10:23:20 +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/codyprime/qemu-kvm-jtc.git tags/block-pull-request
7
https://gitlab.com/hreitz/qemu.git tags/pull-block-2022-04-25
8
8
9
for you to fetch changes up to acf6e5f0962c4be670d4a93ede77423512521876:
9
for you to fetch changes up to 348a0740afc5b313599533eb69bbb2b95d2f1bba:
10
10
11
sheepdog: reorganize check for overlapping requests (2017-02-01 00:17:20 -0500)
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
- New @force parameter for blockdev-change-medium
16
- Improvements to the iotests to help with debugging
17
- Fix iotest 108 on systems without user_allow_other in fuse.conf
18
15
----------------------------------------------------------------
19
----------------------------------------------------------------
20
Denis V. Lunev (1):
21
block: add 'force' parameter to 'blockdev-change-medium' command
16
22
17
Paolo Bonzini (5):
23
Hanna Reitz (1):
18
sheepdog: remove unused cancellation support
24
iotests/108: Fix when missing user_allow_other
19
sheepdog: reorganize coroutine flow
20
sheepdog: do not use BlockAIOCB
21
sheepdog: simplify inflight_aio_head management
22
sheepdog: reorganize check for overlapping requests
23
25
24
block/sheepdog.c | 289 ++++++++++++++++---------------------------------------
26
John Snow (12):
25
1 file changed, 84 insertions(+), 205 deletions(-)
27
iotests: replace calls to log(qemu_io(...)) with qemu_io_log()
28
iotests/163: Fix broken qemu-io invocation
29
iotests: Don't check qemu_io() output for specific error strings
30
iotests/040: Don't check image pattern on zero-length image
31
iotests/040: Fix TestCommitWithFilters test
32
iotests: create generic qemu_tool() function
33
iotests: rebase qemu_io() on top of qemu_tool()
34
iotests/migration-permissions: use assertRaises() for qemu_io()
35
negative test
36
iotests/image-fleecing: switch to qemu_io()
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
40
41
qapi/block.json | 6 ++
42
block/qapi-sysemu.c | 3 +-
43
monitor/hmp-cmds.c | 4 +-
44
hmp-commands.hx | 11 ++-
45
tests/qemu-iotests/030 | 85 +++++++++++--------
46
tests/qemu-iotests/040 | 53 +++++++-----
47
tests/qemu-iotests/056 | 2 +-
48
tests/qemu-iotests/108 | 2 +-
49
tests/qemu-iotests/149 | 6 +-
50
tests/qemu-iotests/163 | 5 +-
51
tests/qemu-iotests/205 | 4 +-
52
tests/qemu-iotests/216 | 12 +--
53
tests/qemu-iotests/218 | 5 +-
54
tests/qemu-iotests/224 | 4 +-
55
tests/qemu-iotests/242 | 6 +-
56
tests/qemu-iotests/245 | 17 ++--
57
tests/qemu-iotests/255 | 4 +-
58
tests/qemu-iotests/258 | 11 ++-
59
tests/qemu-iotests/298 | 17 ++--
60
tests/qemu-iotests/303 | 4 +-
61
tests/qemu-iotests/310 | 22 ++---
62
tests/qemu-iotests/iotests.py | 69 ++++++++-------
63
tests/qemu-iotests/tests/image-fleecing | 30 ++++---
64
.../qemu-iotests/tests/migration-permissions | 28 +++---
65
.../tests/mirror-ready-cancel-error | 2 +-
66
.../qemu-iotests/tests/nbd-reconnect-on-open | 2 +-
67
.../qemu-iotests/tests/stream-error-on-reset | 4 +-
68
ui/cocoa.m | 1 +
69
28 files changed, 231 insertions(+), 188 deletions(-)
26
70
27
--
71
--
28
2.9.3
72
2.35.1
29
30
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: "Denis V. Lunev" <den@openvz.org>
2
2
3
Sheepdog's AIOCB are completely internal entities for a group of
3
'blockdev-change-medium' is a convinient wrapper for the following
4
requests and do not need dynamic allocation.
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
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
16
This situation is could be resolved 'blockdev-open-tray' by passing
7
Message-id: 20161129113245.32724-4-pbonzini@redhat.com
17
flag 'force' inside. Thus is seems reasonable to add the same
8
Signed-off-by: Jeff Cody <jcody@redhat.com>
18
capability for 'blockdev-change-medium' too.
19
20
Signed-off-by: Denis V. Lunev <den@openvz.org>
21
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@openvz.org>
22
Acked-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
23
CC: Kevin Wolf <kwolf@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>
9
---
30
---
10
block/sheepdog.c | 99 ++++++++++++++++++++++----------------------------------
31
qapi/block.json | 6 ++++++
11
1 file changed, 39 insertions(+), 60 deletions(-)
32
block/qapi-sysemu.c | 3 ++-
33
monitor/hmp-cmds.c | 4 +++-
34
hmp-commands.hx | 11 +++++++----
35
ui/cocoa.m | 1 +
36
5 files changed, 19 insertions(+), 6 deletions(-)
12
37
13
diff --git a/block/sheepdog.c b/block/sheepdog.c
38
diff --git a/qapi/block.json b/qapi/block.json
14
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
15
--- a/block/sheepdog.c
40
--- a/qapi/block.json
16
+++ b/block/sheepdog.c
41
+++ b/qapi/block.json
17
@@ -XXX,XX +XXX,XX @@ static inline size_t count_data_objs(const struct SheepdogInode *inode)
42
@@ -XXX,XX +XXX,XX @@
18
} while (0)
43
# @read-only-mode: change the read-only mode of the device; defaults
19
44
# to 'retain'
20
typedef struct SheepdogAIOCB SheepdogAIOCB;
45
#
21
+typedef struct BDRVSheepdogState BDRVSheepdogState;
46
+# @force: if false (the default), an eject request through blockdev-open-tray
22
47
+# will be sent to the guest if it has locked the tray (and the tray
23
typedef struct AIOReq {
48
+# will not be opened immediately); if true, the tray will be opened
24
SheepdogAIOCB *aiocb;
49
+# regardless of whether it is locked. (since 7.1)
25
@@ -XXX,XX +XXX,XX @@ enum AIOCBState {
50
+#
26
|| y->max_affect_data_idx < x->min_affect_data_idx))
51
# Features:
27
52
# @deprecated: Member @device is deprecated. Use @id instead.
28
struct SheepdogAIOCB {
53
#
29
- BlockAIOCB common;
54
@@ -XXX,XX +XXX,XX @@
30
+ BDRVSheepdogState *s;
55
'*id': 'str',
31
56
'filename': 'str',
32
QEMUIOVector *qiov;
57
'*format': 'str',
33
58
+ '*force': 'bool',
34
@@ -XXX,XX +XXX,XX @@ struct SheepdogAIOCB {
59
'*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
35
QLIST_ENTRY(SheepdogAIOCB) aiocb_siblings;
60
36
};
61
37
62
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
38
-typedef struct BDRVSheepdogState {
63
index XXXXXXX..XXXXXXX 100644
39
+struct BDRVSheepdogState {
64
--- a/block/qapi-sysemu.c
40
BlockDriverState *bs;
65
+++ b/block/qapi-sysemu.c
41
AioContext *aio_context;
66
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
42
67
bool has_id, const char *id,
43
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVSheepdogState {
68
const char *filename,
44
69
bool has_format, const char *format,
45
CoQueue overlapping_queue;
70
+ bool has_force, bool force,
46
QLIST_HEAD(inflight_aiocb_head, SheepdogAIOCB) inflight_aiocb_head;
71
bool has_read_only,
47
-} BDRVSheepdogState;
72
BlockdevChangeReadOnlyMode read_only,
48
+};
73
Error **errp)
49
74
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
50
typedef struct BDRVSheepdogReopenState {
75
51
int fd;
76
rc = do_open_tray(has_device ? device : NULL,
52
@@ -XXX,XX +XXX,XX @@ static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req)
77
has_id ? id : NULL,
53
acb->nr_pending--;
78
- false, &err);
54
}
79
+ force, &err);
55
80
if (rc && rc != -ENOSYS) {
56
-static const AIOCBInfo sd_aiocb_info = {
81
error_propagate(errp, err);
57
- .aiocb_size = sizeof(SheepdogAIOCB),
82
goto fail;
58
-};
83
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
59
-
84
index XXXXXXX..XXXXXXX 100644
60
-static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
85
--- a/monitor/hmp-cmds.c
61
- int64_t sector_num, int nb_sectors)
86
+++ b/monitor/hmp-cmds.c
62
+static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
87
@@ -XXX,XX +XXX,XX @@ void hmp_change(Monitor *mon, const QDict *qdict)
63
+ QEMUIOVector *qiov, int64_t sector_num, int nb_sectors,
88
const char *target = qdict_get_str(qdict, "target");
64
+ int type)
89
const char *arg = qdict_get_try_str(qdict, "arg");
65
{
90
const char *read_only = qdict_get_try_str(qdict, "read-only-mode");
66
- SheepdogAIOCB *acb;
91
+ bool force = qdict_get_try_bool(qdict, "force", false);
67
uint32_t object_size;
92
BlockdevChangeReadOnlyMode read_only_mode = 0;
68
- BDRVSheepdogState *s = bs->opaque;
93
Error *err = NULL;
69
94
70
object_size = (UINT32_C(1) << s->inode.block_size_shift);
95
@@ -XXX,XX +XXX,XX @@ void hmp_change(Monitor *mon, const QDict *qdict)
71
72
- acb = qemu_aio_get(&sd_aiocb_info, bs, NULL, NULL);
73
+ acb->s = s;
74
75
acb->qiov = qiov;
76
77
@@ -XXX,XX +XXX,XX @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
78
79
acb->min_dirty_data_idx = UINT32_MAX;
80
acb->max_dirty_data_idx = 0;
81
-
82
- return acb;
83
+ acb->aiocb_type = type;
84
}
85
86
/* Return -EIO in case of error, file descriptor on success */
87
@@ -XXX,XX +XXX,XX @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
88
*/
89
static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
90
{
91
- BDRVSheepdogState *s = acb->common.bs->opaque;
92
+ BDRVSheepdogState *s = acb->s;
93
struct iovec iov;
94
AIOReq *aio_req;
95
uint32_t offset, data_len, mn, mx;
96
@@ -XXX,XX +XXX,XX @@ out:
97
* Returns 1 when we need to wait a response, 0 when there is no sent
98
* request and -errno in error cases.
99
*/
100
-static void coroutine_fn sd_co_rw_vector(void *p)
101
+static void coroutine_fn sd_co_rw_vector(SheepdogAIOCB *acb)
102
{
103
- SheepdogAIOCB *acb = p;
104
int ret = 0;
105
unsigned long len, done = 0, total = acb->nb_sectors * BDRV_SECTOR_SIZE;
106
unsigned long idx;
107
uint32_t object_size;
108
uint64_t oid;
109
uint64_t offset;
110
- BDRVSheepdogState *s = acb->common.bs->opaque;
111
+ BDRVSheepdogState *s = acb->s;
112
SheepdogInode *inode = &s->inode;
113
AIOReq *aio_req;
114
115
@@ -XXX,XX +XXX,XX @@ static bool check_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *aiocb)
116
static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
117
int nb_sectors, QEMUIOVector *qiov)
118
{
119
- SheepdogAIOCB *acb;
120
+ SheepdogAIOCB acb;
121
int ret;
122
int64_t offset = (sector_num + nb_sectors) * BDRV_SECTOR_SIZE;
123
BDRVSheepdogState *s = bs->opaque;
124
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
125
}
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);
126
}
103
}
127
104
128
- acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
105
diff --git a/hmp-commands.hx b/hmp-commands.hx
129
- acb->aiocb_type = AIOCB_WRITE_UDATA;
106
index XXXXXXX..XXXXXXX 100644
130
+ sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_WRITE_UDATA);
107
--- a/hmp-commands.hx
131
108
+++ b/hmp-commands.hx
132
retry:
109
@@ -XXX,XX +XXX,XX @@ ERST
133
- if (check_overlapping_aiocb(s, acb)) {
110
134
+ if (check_overlapping_aiocb(s, &acb)) {
111
{
135
qemu_co_queue_wait(&s->overlapping_queue);
112
.name = "change",
136
goto retry;
113
- .args_type = "device:B,target:F,arg:s?,read-only-mode:s?",
137
}
114
- .params = "device filename [format [read-only-mode]]",
138
115
- .help = "change a removable medium, optional format",
139
- sd_co_rw_vector(acb);
116
+ .args_type = "device:B,force:-f,target:F,arg:s?,read-only-mode:s?",
140
- sd_write_done(acb);
117
+ .params = "device [-f] filename [format [read-only-mode]]",
141
+ sd_co_rw_vector(&acb);
118
+ .help = "change a removable medium, optional format, use -f to force the operation",
142
+ sd_write_done(&acb);
119
.cmd = hmp_change,
143
120
},
144
- QLIST_REMOVE(acb, aiocb_siblings);
121
145
+ QLIST_REMOVE(&acb, aiocb_siblings);
122
@@ -XXX,XX +XXX,XX @@ SRST
146
qemu_co_queue_restart_all(&s->overlapping_queue);
123
``change`` *device* *setting*
147
- ret = acb->ret;
124
Change the configuration of a device.
148
- qemu_aio_unref(acb);
125
149
- return ret;
126
- ``change`` *diskdevice* *filename* [*format* [*read-only-mode*]]
150
+ return acb.ret;
127
+ ``change`` *diskdevice* [-f] *filename* [*format* [*read-only-mode*]]
151
}
128
Change the medium for a removable disk device to point to *filename*. eg::
152
129
153
static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
130
(qemu) change ide1-cd0 /path/to/some.iso
154
int nb_sectors, QEMUIOVector *qiov)
131
155
{
132
+ ``-f``
156
- SheepdogAIOCB *acb;
133
+ forces the operation even if the guest has locked the tray.
157
- int ret;
134
+
158
+ SheepdogAIOCB acb;
135
*format* is optional.
159
BDRVSheepdogState *s = bs->opaque;
136
160
137
*read-only-mode* may be used to change the read-only status of the device.
161
- acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
138
diff --git a/ui/cocoa.m b/ui/cocoa.m
162
- acb->aiocb_type = AIOCB_READ_UDATA;
139
index XXXXXXX..XXXXXXX 100644
163
+ sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_READ_UDATA);
140
--- a/ui/cocoa.m
164
141
+++ b/ui/cocoa.m
165
retry:
142
@@ -XXX,XX +XXX,XX @@ - (void)changeDeviceMedia:(id)sender
166
- if (check_overlapping_aiocb(s, acb)) {
143
[file cStringUsingEncoding:
167
+ if (check_overlapping_aiocb(s, &acb)) {
144
NSASCIIStringEncoding],
168
qemu_co_queue_wait(&s->overlapping_queue);
145
true, "raw",
169
goto retry;
146
+ true, false,
170
}
147
false, 0,
171
148
&err);
172
- sd_co_rw_vector(acb);
149
});
173
+ sd_co_rw_vector(&acb);
174
175
- QLIST_REMOVE(acb, aiocb_siblings);
176
+ QLIST_REMOVE(&acb, aiocb_siblings);
177
qemu_co_queue_restart_all(&s->overlapping_queue);
178
- ret = acb->ret;
179
- qemu_aio_unref(acb);
180
- return ret;
181
+ return acb.ret;
182
}
183
184
static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
185
{
186
BDRVSheepdogState *s = bs->opaque;
187
- SheepdogAIOCB *acb;
188
- int ret;
189
+ SheepdogAIOCB acb;
190
AIOReq *aio_req;
191
192
if (s->cache_flags != SD_FLAG_CMD_CACHE) {
193
return 0;
194
}
195
196
- acb = sd_aio_setup(bs, NULL, 0, 0);
197
- acb->aiocb_type = AIOCB_FLUSH_CACHE;
198
+ sd_aio_setup(&acb, s, NULL, 0, 0, AIOCB_FLUSH_CACHE);
199
200
- acb->nr_pending++;
201
- aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
202
+ acb.nr_pending++;
203
+ aio_req = alloc_aio_req(s, &acb, vid_to_vdi_oid(s->inode.vdi_id),
204
0, 0, 0, false, 0, 0);
205
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
206
- add_aio_request(s, aio_req, NULL, 0, acb->aiocb_type);
207
+ add_aio_request(s, aio_req, NULL, 0, acb.aiocb_type);
208
209
- if (--acb->nr_pending) {
210
+ if (--acb.nr_pending) {
211
qemu_coroutine_yield();
212
}
213
- ret = acb->ret;
214
- qemu_aio_unref(acb);
215
- return ret;
216
+ return acb.ret;
217
}
218
219
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
220
@@ -XXX,XX +XXX,XX @@ static int sd_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
221
static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
222
int count)
223
{
224
- SheepdogAIOCB *acb;
225
+ SheepdogAIOCB acb;
226
BDRVSheepdogState *s = bs->opaque;
227
- int ret;
228
QEMUIOVector discard_iov;
229
struct iovec iov;
230
uint32_t zero = 0;
231
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
232
if (!QEMU_IS_ALIGNED(offset | count, BDRV_SECTOR_SIZE)) {
233
return -ENOTSUP;
234
}
235
- acb = sd_aio_setup(bs, &discard_iov, offset >> BDRV_SECTOR_BITS,
236
- count >> BDRV_SECTOR_BITS);
237
- acb->aiocb_type = AIOCB_DISCARD_OBJ;
238
+ sd_aio_setup(&acb, s, &discard_iov, offset >> BDRV_SECTOR_BITS,
239
+ count >> BDRV_SECTOR_BITS, AIOCB_DISCARD_OBJ);
240
241
retry:
242
- if (check_overlapping_aiocb(s, acb)) {
243
+ if (check_overlapping_aiocb(s, &acb)) {
244
qemu_co_queue_wait(&s->overlapping_queue);
245
goto retry;
246
}
247
248
- sd_co_rw_vector(acb);
249
+ sd_co_rw_vector(&acb);
250
251
- QLIST_REMOVE(acb, aiocb_siblings);
252
+ QLIST_REMOVE(&acb, aiocb_siblings);
253
qemu_co_queue_restart_all(&s->overlapping_queue);
254
- ret = acb->ret;
255
- qemu_aio_unref(acb);
256
- return ret;
257
+ return acb.ret;
258
}
259
260
static coroutine_fn int64_t
261
--
150
--
262
2.9.3
151
2.35.1
263
152
264
153
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
This makes these callsites a little simpler, but the real motivation is
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>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Message-Id: <20220418211504.943969-2-jsnow@redhat.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
tests/qemu-iotests/242 | 6 +++---
14
tests/qemu-iotests/255 | 4 +---
15
tests/qemu-iotests/303 | 4 ++--
16
3 files changed, 6 insertions(+), 8 deletions(-)
17
18
diff --git a/tests/qemu-iotests/242 b/tests/qemu-iotests/242
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/242
21
+++ b/tests/qemu-iotests/242
22
@@ -XXX,XX +XXX,XX @@
23
import iotests
24
import json
25
import struct
26
-from iotests import qemu_img_create, qemu_io, qemu_img_info, \
27
- file_path, img_info_log, log, filter_qemu_io
28
+from iotests import qemu_img_create, qemu_io_log, qemu_img_info, \
29
+ file_path, img_info_log, log
30
31
iotests.script_initialize(supported_fmts=['qcow2'],
32
supported_protocols=['file'],
33
@@ -XXX,XX +XXX,XX @@ def add_bitmap(bitmap_number, persistent, disabled):
34
35
def write_to_disk(offset, size):
36
write = 'write {} {}'.format(offset, size)
37
- log(qemu_io('-c', write, disk), filters=[filter_qemu_io])
38
+ qemu_io_log('-c', write, disk)
39
40
41
def toggle_flag(offset):
42
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
43
index XXXXXXX..XXXXXXX 100755
44
--- a/tests/qemu-iotests/255
45
+++ b/tests/qemu-iotests/255
46
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('src.qcow2') as src_path, \
47
iotests.qemu_img_create('-f', iotests.imgfmt, src_path, size_str)
48
iotests.qemu_img_create('-f', iotests.imgfmt, dst_path, size_str)
49
50
- iotests.log(iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write 0 1M',
51
- src_path),
52
- filters=[iotests.filter_test_dir, iotests.filter_qemu_io])
53
+ iotests.qemu_io_log('-f', iotests.imgfmt, '-c', 'write 0 1M', src_path),
54
55
vm.add_object('throttle-group,x-bps-read=4096,id=throttle0')
56
57
diff --git a/tests/qemu-iotests/303 b/tests/qemu-iotests/303
58
index XXXXXXX..XXXXXXX 100755
59
--- a/tests/qemu-iotests/303
60
+++ b/tests/qemu-iotests/303
61
@@ -XXX,XX +XXX,XX @@
62
63
import iotests
64
import subprocess
65
-from iotests import qemu_img_create, qemu_io, file_path, log, filter_qemu_io, \
66
+from iotests import qemu_img_create, qemu_io_log, file_path, log, \
67
verify_qcow2_zstd_compression
68
69
iotests.script_initialize(supported_fmts=['qcow2'],
70
@@ -XXX,XX +XXX,XX @@ def create_bitmap(bitmap_number, disabled):
71
72
def write_to_disk(offset, size):
73
write = f'write {offset} {size}'
74
- log(qemu_io('-c', write, disk), filters=[filter_qemu_io])
75
+ qemu_io_log('-c', write, disk)
76
77
78
def add_bitmap(num, begin, end, disabled):
79
--
80
2.35.1
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
The 'read' commands to qemu-io were malformed, and this invocation only
4
worked by coincidence because the error messages were identical. Oops.
5
6
There's no point in checking the patterning of the reference image, so
7
just check the empty image by itself instead.
8
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>
14
Reviewed-by: Eric Blake <eblake@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
---
19
tests/qemu-iotests/163 | 5 +----
20
1 file changed, 1 insertion(+), 4 deletions(-)
21
22
diff --git a/tests/qemu-iotests/163 b/tests/qemu-iotests/163
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/163
25
+++ b/tests/qemu-iotests/163
26
@@ -XXX,XX +XXX,XX @@ class ShrinkBaseClass(iotests.QMPTestCase):
27
qemu_img('resize', '-f', iotests.imgfmt, '--shrink', test_img,
28
self.shrink_size)
29
30
- self.assertEqual(
31
- qemu_io('-c', 'read -P 0x00 %s'%self.shrink_size, test_img),
32
- qemu_io('-c', 'read -P 0x00 %s'%self.shrink_size, check_img),
33
- "Verifying image content")
34
+ qemu_io('-c', f"read -P 0x00 0 {self.shrink_size}", test_img)
35
36
self.image_verify()
37
38
--
39
2.35.1
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
A forthcoming commit updates qemu_io() to raise an exception on non-zero
4
return by default, and changes its return type.
5
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>
16
---
17
tests/qemu-iotests/040 | 33 ++++++++++++++++-----------------
18
tests/qemu-iotests/056 | 2 +-
19
2 files changed, 17 insertions(+), 18 deletions(-)
20
21
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
22
index XXXXXXX..XXXXXXX 100755
23
--- a/tests/qemu-iotests/040
24
+++ b/tests/qemu-iotests/040
25
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
26
27
def test_commit(self):
28
self.run_commit_test(mid_img, backing_img)
29
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
30
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
31
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
32
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
33
34
def test_commit_node(self):
35
self.run_commit_test("mid", "base", node_names=True)
36
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
37
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
38
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
39
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
40
41
@iotests.skip_if_unsupported(['throttle'])
42
def test_commit_with_filter_and_quit(self):
43
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
44
45
def test_top_is_active(self):
46
self.run_commit_test(test_img, backing_img, need_ready=True)
47
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
48
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
49
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
50
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
51
52
def test_top_is_default_active(self):
53
self.run_default_commit_test()
54
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
55
- self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
56
+ qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
57
+ qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
58
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):
112
--
113
2.35.1
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
qemu-io fails on read/write beyond end-of-file on raw images, so skip
4
these invocations when running the zero-length image tests.
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>
11
---
12
tests/qemu-iotests/040 | 14 ++++++++++++--
13
1 file changed, 12 insertions(+), 2 deletions(-)
14
15
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/040
18
+++ b/tests/qemu-iotests/040
19
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
20
qemu_img('create', '-f', iotests.imgfmt,
21
'-o', 'backing_file=%s' % mid_img,
22
'-F', iotests.imgfmt, test_img)
23
- qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img)
24
- qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img)
25
+ if self.image_len:
26
+ qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img)
27
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288',
28
+ mid_img)
29
self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=mid,backing.backing.node-name=base", interface="none")
30
self.vm.add_device('virtio-scsi')
31
self.vm.add_device("scsi-hd,id=scsi0,drive=drive0")
32
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
33
34
def test_commit(self):
35
self.run_commit_test(mid_img, backing_img)
36
+ if not self.image_len:
37
+ return
38
qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
39
qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
40
41
def test_commit_node(self):
42
self.run_commit_test("mid", "base", node_names=True)
43
+ if not self.image_len:
44
+ return
45
qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
46
qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
47
48
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
49
50
def test_top_is_active(self):
51
self.run_commit_test(test_img, backing_img, need_ready=True)
52
+ if not self.image_len:
53
+ return
54
qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
55
qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
56
57
def test_top_is_default_active(self):
58
self.run_default_commit_test()
59
+ if not self.image_len:
60
+ return
61
qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img)
62
qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img)
63
64
--
65
2.35.1
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
Wrap the code that was copied repeatedly in the two functions,
3
Without this change, asserting that qemu_io always returns 0 causes this
4
sd_aio_setup and sd_aio_complete.
4
test to fail in a way we happened not to be catching previously:
5
5
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
qemu.utils.VerboseProcessError: Command
7
Message-id: 20161129113245.32724-6-pbonzini@redhat.com
7
'('/home/jsnow/src/qemu/bin/git/tests/qemu-iotests/../../qemu-io',
8
Signed-off-by: Jeff Cody <jcody@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>
38
Reviewed-by: Eric Blake <eblake@redhat.com>
39
Message-Id: <20220418211504.943969-6-jsnow@redhat.com>
9
---
40
---
10
block/sheepdog.c | 66 ++++++++++++++++++++++++++------------------------------
41
tests/qemu-iotests/040 | 6 ++++--
11
1 file changed, 30 insertions(+), 36 deletions(-)
42
1 file changed, 4 insertions(+), 2 deletions(-)
12
43
13
diff --git a/block/sheepdog.c b/block/sheepdog.c
44
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
14
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100755
15
--- a/block/sheepdog.c
46
--- a/tests/qemu-iotests/040
16
+++ b/block/sheepdog.c
47
+++ b/tests/qemu-iotests/040
17
@@ -XXX,XX +XXX,XX @@ static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
48
@@ -XXX,XX +XXX,XX @@ class TestCommitWithFilters(iotests.QMPTestCase):
18
return aio_req;
49
job_id='commit',
19
}
50
device='top-filter',
20
51
top_node='cow-2',
21
+static void wait_for_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *acb)
52
- base_node='cow-1')
22
+{
53
+ base_node='cow-1',
23
+ SheepdogAIOCB *cb;
54
+ backing_file=self.img1)
24
+
55
self.assert_qmp(result, 'return', {})
25
+retry:
56
self.wait_until_completed(drive='commit')
26
+ QLIST_FOREACH(cb, &s->inflight_aiocb_head, aiocb_siblings) {
57
27
+ if (AIOCBOverlapping(acb, cb)) {
58
@@ -XXX,XX +XXX,XX @@ class TestCommitWithFilters(iotests.QMPTestCase):
28
+ qemu_co_queue_wait(&s->overlapping_queue);
59
job_id='commit',
29
+ goto retry;
60
device='top-filter',
30
+ }
61
top_node='cow-1',
31
+ }
62
- base_node='cow-0')
32
+}
63
+ base_node='cow-0',
33
+
64
+ backing_file=self.img0)
34
static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
65
self.assert_qmp(result, 'return', {})
35
QEMUIOVector *qiov, int64_t sector_num, int nb_sectors,
66
self.wait_until_completed(drive='commit')
36
int type)
37
@@ -XXX,XX +XXX,XX @@ static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
38
acb->min_dirty_data_idx = UINT32_MAX;
39
acb->max_dirty_data_idx = 0;
40
acb->aiocb_type = type;
41
+
42
+ if (type == AIOCB_FLUSH_CACHE) {
43
+ return;
44
+ }
45
+
46
+ wait_for_overlapping_aiocb(s, acb);
47
+ QLIST_INSERT_HEAD(&s->inflight_aiocb_head, acb, aiocb_siblings);
48
}
49
50
/* Return -EIO in case of error, file descriptor on success */
51
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_co_rw_vector(SheepdogAIOCB *acb)
52
}
53
}
54
55
-static bool check_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *aiocb)
56
+static void sd_aio_complete(SheepdogAIOCB *acb)
57
{
58
- SheepdogAIOCB *cb;
59
-
60
- QLIST_FOREACH(cb, &s->inflight_aiocb_head, aiocb_siblings) {
61
- if (AIOCBOverlapping(aiocb, cb)) {
62
- return true;
63
- }
64
+ if (acb->aiocb_type == AIOCB_FLUSH_CACHE) {
65
+ return;
66
}
67
68
- QLIST_INSERT_HEAD(&s->inflight_aiocb_head, aiocb, aiocb_siblings);
69
- return false;
70
+ QLIST_REMOVE(acb, aiocb_siblings);
71
+ qemu_co_queue_restart_all(&acb->s->overlapping_queue);
72
}
73
74
static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
75
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
76
}
77
78
sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_WRITE_UDATA);
79
-
80
-retry:
81
- if (check_overlapping_aiocb(s, &acb)) {
82
- qemu_co_queue_wait(&s->overlapping_queue);
83
- goto retry;
84
- }
85
-
86
sd_co_rw_vector(&acb);
87
sd_write_done(&acb);
88
+ sd_aio_complete(&acb);
89
90
- QLIST_REMOVE(&acb, aiocb_siblings);
91
- qemu_co_queue_restart_all(&s->overlapping_queue);
92
return acb.ret;
93
}
94
95
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
96
BDRVSheepdogState *s = bs->opaque;
97
98
sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_READ_UDATA);
99
-
100
-retry:
101
- if (check_overlapping_aiocb(s, &acb)) {
102
- qemu_co_queue_wait(&s->overlapping_queue);
103
- goto retry;
104
- }
105
-
106
sd_co_rw_vector(&acb);
107
+ sd_aio_complete(&acb);
108
109
- QLIST_REMOVE(&acb, aiocb_siblings);
110
- qemu_co_queue_restart_all(&s->overlapping_queue);
111
return acb.ret;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
115
if (--acb.nr_pending) {
116
qemu_coroutine_yield();
117
}
118
+
119
+ sd_aio_complete(&acb);
120
return acb.ret;
121
}
122
123
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
124
}
125
sd_aio_setup(&acb, s, &discard_iov, offset >> BDRV_SECTOR_BITS,
126
count >> BDRV_SECTOR_BITS, AIOCB_DISCARD_OBJ);
127
-
128
-retry:
129
- if (check_overlapping_aiocb(s, &acb)) {
130
- qemu_co_queue_wait(&s->overlapping_queue);
131
- goto retry;
132
- }
133
-
134
sd_co_rw_vector(&acb);
135
+ sd_aio_complete(&acb);
136
137
- QLIST_REMOVE(&acb, aiocb_siblings);
138
- qemu_co_queue_restart_all(&s->overlapping_queue);
139
return acb.ret;
140
}
141
67
142
--
68
--
143
2.9.3
69
2.35.1
144
70
145
71
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
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>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20220418211504.943969-7-jsnow@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
tests/qemu-iotests/iotests.py | 32 +++++++++++++++++++++-----------
13
1 file changed, 21 insertions(+), 11 deletions(-)
14
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ def qemu_img_create_prepare_args(args: List[str]) -> List[str]:
20
21
return result
22
23
-def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
24
- ) -> 'subprocess.CompletedProcess[str]':
25
- """
26
- Run qemu_img and return the status code and console output.
27
28
- This function always prepends QEMU_IMG_OPTIONS and may further alter
29
- the args for 'create' commands.
30
+def qemu_tool(*args: str, check: bool = True, combine_stdio: bool = True
31
+ ) -> 'subprocess.CompletedProcess[str]':
32
+ """
33
+ Run a qemu tool and return its status code and console output.
34
35
- :param args: command-line arguments to qemu-img.
36
+ :param args: full command line to run.
37
:param check: Enforce a return code of zero.
38
:param combine_stdio: set to False to keep stdout/stderr separated.
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.
69
+
70
+ This function always prepends QEMU_IMG_OPTIONS and may further alter
71
+ the args for 'create' commands.
72
+
73
+ See `qemu_tool()` for greater detail.
74
+ """
75
+ full_args = qemu_img_args + qemu_img_create_prepare_args(list(args))
76
+ return qemu_tool(*full_args, check=check, combine_stdio=combine_stdio)
77
+
78
+
79
def ordered_qmp(qmsg, conv_keys=True):
80
# Dictionaries are not ordered prior to 3.6, therefore:
81
if isinstance(qmsg, list):
82
--
83
2.35.1
diff view generated by jsdifflib
New patch
1
1
From: John Snow <jsnow@redhat.com>
2
3
Rework qemu_io() to be analogous to qemu_img(); a function that requires
4
a return code of zero by default unless disabled explicitly.
5
6
Tests that use qemu_io():
7
030 040 041 044 055 056 093 124 129 132 136 148 149 151 152 163 165 205
8
209 219 236 245 248 254 255 257 260 264 280 298 300 302 304
9
image-fleecing migrate-bitmaps-postcopy-test migrate-bitmaps-test
10
migrate-during-backup migration-permissions
11
12
Test that use qemu_io_log():
13
242 245 255 274 303 307 nbd-reconnect-on-open
14
15
Copy-pastables for testing/verification:
16
17
./check -qcow2 030 040 041 044 055 056 124 129 132 151 152 163 165 209 \
18
219 236 242 245 248 254 255 257 260 264 274 \
19
280 298 300 302 303 304 307 image-fleecing \
20
migrate-bitmaps-postcopy-test migrate-bitmaps-test \
21
migrate-during-backup nbd-reconnect-on-open
22
./check -raw 093 136 148 migration-permissions
23
./check -nbd 205
24
25
# ./configure configure --disable-gnutls --enable-gcrypt
26
# this ALSO requires passwordless sudo.
27
./check -luks 149
28
29
# Just the tests that were edited in this commit:
30
./check -qcow2 030 040 242 245
31
./check -raw migration-permissions
32
./check -nbd 205
33
./check -luks 149
34
35
Signed-off-by: John Snow <jsnow@redhat.com>
36
Message-Id: <20220418211504.943969-8-jsnow@redhat.com>
37
Reviewed-by: Eric Blake <eblake@redhat.com>
38
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
39
---
40
tests/qemu-iotests/030 | 85 +++++++++++--------
41
tests/qemu-iotests/149 | 6 +-
42
tests/qemu-iotests/205 | 4 +-
43
tests/qemu-iotests/245 | 17 ++--
44
tests/qemu-iotests/iotests.py | 19 +++--
45
.../qemu-iotests/tests/migration-permissions | 4 +-
46
6 files changed, 81 insertions(+), 54 deletions(-)
47
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
307
index XXXXXXX..XXXXXXX 100644
308
--- a/tests/qemu-iotests/iotests.py
309
+++ b/tests/qemu-iotests/iotests.py
310
@@ -XXX,XX +XXX,XX @@ def qemu_io_wrap_args(args: Sequence[str]) -> List[str]:
311
def qemu_io_popen(*args):
312
return qemu_tool_popen(qemu_io_wrap_args(args))
313
314
-def qemu_io(*args):
315
- '''Run qemu-io and return the stdout data'''
316
- return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))[0]
317
+def qemu_io(*args: str, check: bool = True, combine_stdio: bool = True
318
+ ) -> 'subprocess.CompletedProcess[str]':
319
+ """
320
+ Run QEMU_IO_PROG and return the status code and console output.
321
+
322
+ This function always prepends either QEMU_IO_OPTIONS or
323
+ QEMU_IO_OPTIONS_NO_FMT.
324
+ """
325
+ return qemu_tool(*qemu_io_wrap_args(args),
326
+ check=check, combine_stdio=combine_stdio)
327
328
def qemu_io_pipe_and_status(*args):
329
return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))
330
331
-def qemu_io_log(*args):
332
- result = qemu_io(*args)
333
- log(result, filters=[filter_testfiles, filter_qemu_io])
334
+def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
335
+ result = qemu_io(*args, check=False)
336
+ log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
337
return result
338
339
def qemu_io_silent(*args):
340
diff --git a/tests/qemu-iotests/tests/migration-permissions b/tests/qemu-iotests/tests/migration-permissions
341
index XXXXXXX..XXXXXXX 100755
342
--- a/tests/qemu-iotests/tests/migration-permissions
343
+++ b/tests/qemu-iotests/tests/migration-permissions
344
@@ -XXX,XX +XXX,XX @@ class TestMigrationPermissions(iotests.QMPTestCase):
345
def test_post_migration_permissions(self):
346
# Try to access the image R/W, which should fail because virtio-blk
347
# has not been configured with share-rw=on
348
- log = qemu_io('-f', imgfmt, '-c', 'quit', test_img)
349
+ log = qemu_io('-f', imgfmt, '-c', 'quit', test_img, check=False).stdout
350
if not log.strip():
351
print('ERROR (pre-migration): qemu-io should not be able to '
352
'access this image, but it reported no error')
353
@@ -XXX,XX +XXX,XX @@ class TestMigrationPermissions(iotests.QMPTestCase):
354
355
# Try the same qemu-io access again, verifying that the WRITE
356
# permission remains unshared
357
- log = qemu_io('-f', imgfmt, '-c', 'quit', test_img)
358
+ log = qemu_io('-f', imgfmt, '-c', 'quit', test_img, check=False).stdout
359
if not log.strip():
360
print('ERROR (post-migration): qemu-io should not be able to '
361
'access this image, but it reported no error')
362
--
363
2.35.1
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
Modify this test to use assertRaises for its negative testing of
4
qemu_io. If the exception raised does not match the one we tell it to
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>
20
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Tested-by: Eric Blake <eblake@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>
25
---
26
.../qemu-iotests/tests/migration-permissions | 28 +++++++++----------
27
1 file changed, 14 insertions(+), 14 deletions(-)
28
29
diff --git a/tests/qemu-iotests/tests/migration-permissions b/tests/qemu-iotests/tests/migration-permissions
30
index XXXXXXX..XXXXXXX 100755
31
--- a/tests/qemu-iotests/tests/migration-permissions
32
+++ b/tests/qemu-iotests/tests/migration-permissions
33
@@ -XXX,XX +XXX,XX @@
34
#
35
36
import os
37
+from subprocess import CalledProcessError
38
+
39
import iotests
40
from iotests import imgfmt, qemu_img_create, qemu_io
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__':
82
--
83
2.35.1
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
This test expects failure ... but only sometimes. When? Why?
4
5
It's for reads of a region not defined by a bitmap. Adjust the test to
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>
13
---
14
tests/qemu-iotests/tests/image-fleecing | 28 +++++++++++++++++--------
15
1 file changed, 19 insertions(+), 9 deletions(-)
16
17
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/tests/image-fleecing
20
+++ b/tests/qemu-iotests/tests/image-fleecing
21
@@ -XXX,XX +XXX,XX @@
22
#
23
# Creator/Owner: John Snow <jsnow@redhat.com>
24
25
+from subprocess import CalledProcessError
26
+
27
import iotests
28
-from iotests import log, qemu_img, qemu_io, qemu_io_silent, \
29
- qemu_io_pipe_and_status
30
+from iotests import log, qemu_img, qemu_io, qemu_io_silent
31
32
iotests.script_initialize(
33
supported_fmts=['qcow2'],
34
@@ -XXX,XX +XXX,XX @@ def do_test(vm, use_cbw, use_snapshot_access_filter, base_img_path,
35
for p in patterns + zeroes:
36
cmd = 'read -P%s %s %s' % p
37
log(cmd)
38
- out, ret = qemu_io_pipe_and_status('-r', '-f', 'raw', '-c', cmd,
39
- nbd_uri)
40
- if ret != 0:
41
- print(out)
42
+
43
+ try:
44
+ qemu_io('-r', '-f', 'raw', '-c', cmd, nbd_uri)
45
+ except CalledProcessError as exc:
46
+ if bitmap and p in zeroes:
47
+ log(exc.stdout)
48
+ else:
49
+ raise
50
51
log('')
52
log('--- Testing COW ---')
53
@@ -XXX,XX +XXX,XX @@ def do_test(vm, use_cbw, use_snapshot_access_filter, base_img_path,
54
args += [target_img_path]
55
else:
56
args += ['-f', 'raw', nbd_uri]
57
- out, ret = qemu_io_pipe_and_status(*args)
58
- if ret != 0:
59
- print(out)
60
+
61
+ try:
62
+ qemu_io(*args)
63
+ except CalledProcessError as exc:
64
+ if bitmap and p in zeroes:
65
+ log(exc.stdout)
66
+ else:
67
+ raise
68
69
log('')
70
log('--- Cleanup ---')
71
--
72
2.35.1
diff view generated by jsdifflib
New patch
1
From: John Snow <jsnow@redhat.com>
1
2
3
I know we just added it, sorry. This is done in favor of qemu_io() which
4
*also* returns the console output and status, but with more robust error
5
handling on failure.
6
7
Signed-off-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Message-Id: <20220418211504.943969-11-jsnow@redhat.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
tests/qemu-iotests/iotests.py | 3 ---
14
1 file changed, 3 deletions(-)
15
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ def qemu_io(*args: str, check: bool = True, combine_stdio: bool = True
21
return qemu_tool(*qemu_io_wrap_args(args),
22
check=check, combine_stdio=combine_stdio)
23
24
-def qemu_io_pipe_and_status(*args):
25
- return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))
26
-
27
def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
28
result = qemu_io(*args, check=False)
29
log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
30
--
31
2.35.1
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
Add to the list in add_aio_request and, indirectly, resend_aioreq. Inline
3
Like qemu-img, qemu-io returning 0 should be the norm and not the
4
free_aio_req in the caller, it does not simply undo alloc_aio_req's job.
4
exception. Remove all calls to qemu_io_silent that just assert the
5
return code is zero (That's every last call, as it turns out), and
6
replace them with a normal qemu_io() call.
5
7
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
qemu_io_silent_check() appeared to have been unused already.
7
Message-id: 20161129113245.32724-5-pbonzini@redhat.com
9
8
Signed-off-by: Jeff Cody <jcody@redhat.com>
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>
9
---
15
---
10
block/sheepdog.c | 23 ++++++-----------------
16
tests/qemu-iotests/216 | 12 +++++-----
11
1 file changed, 6 insertions(+), 17 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(-)
12
27
13
diff --git a/block/sheepdog.c b/block/sheepdog.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
14
index XXXXXXX..XXXXXXX 100644
223
index XXXXXXX..XXXXXXX 100644
15
--- a/block/sheepdog.c
224
--- a/tests/qemu-iotests/iotests.py
16
+++ b/block/sheepdog.c
225
+++ b/tests/qemu-iotests/iotests.py
17
@@ -XXX,XX +XXX,XX @@ static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
226
@@ -XXX,XX +XXX,XX @@ def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
18
return aio_req;
227
log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
19
}
228
return result
20
229
21
-static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req)
230
-def qemu_io_silent(*args):
22
-{
231
- '''Run qemu-io and return the exit code, suppressing stdout'''
23
- SheepdogAIOCB *acb = aio_req->aiocb;
232
- args = qemu_io_wrap_args(args)
233
- result = subprocess.run(args, stdout=subprocess.DEVNULL, check=False)
234
- if result.returncode < 0:
235
- sys.stderr.write('qemu-io received signal %i: %s\n' %
236
- (-result.returncode, ' '.join(args)))
237
- return result.returncode
24
-
238
-
25
- QLIST_REMOVE(aio_req, aio_siblings);
239
-def qemu_io_silent_check(*args):
26
- g_free(aio_req);
240
- '''Run qemu-io and return the true if subprocess returned 0'''
241
- args = qemu_io_wrap_args(args)
242
- result = subprocess.run(args, stdout=subprocess.DEVNULL,
243
- stderr=subprocess.STDOUT, check=False)
244
- return result.returncode == 0
27
-
245
-
28
- acb->nr_pending--;
246
class QemuIoInteractive:
29
-}
247
def __init__(self, *args):
30
-
248
self.args = qemu_io_wrap_args(args)
31
static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
249
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
32
QEMUIOVector *qiov, int64_t sector_num, int nb_sectors,
250
index XXXXXXX..XXXXXXX 100755
33
int type)
251
--- a/tests/qemu-iotests/tests/image-fleecing
34
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
252
+++ b/tests/qemu-iotests/tests/image-fleecing
35
while (!QLIST_EMPTY(&s->failed_aio_head)) {
253
@@ -XXX,XX +XXX,XX @@
36
aio_req = QLIST_FIRST(&s->failed_aio_head);
254
from subprocess import CalledProcessError
37
QLIST_REMOVE(aio_req, aio_siblings);
255
38
- QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
256
import iotests
39
resend_aioreq(s, aio_req);
257
-from iotests import log, qemu_img, qemu_io, qemu_io_silent
40
}
258
+from iotests import log, qemu_img, qemu_io
41
}
259
42
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
260
iotests.script_initialize(
43
*/
261
supported_fmts=['qcow2'],
44
s->co_recv = NULL;
262
@@ -XXX,XX +XXX,XX @@ def do_test(vm, use_cbw, use_snapshot_access_filter, base_img_path,
45
263
for p in overwrite + remainder:
46
+ QLIST_REMOVE(aio_req, aio_siblings);
264
cmd = 'read -P%s %s %s' % p
47
switch (rsp.result) {
265
log(cmd)
48
case SD_RES_SUCCESS:
266
- assert qemu_io_silent(base_img_path, '-c', cmd) == 0
49
break;
267
+ qemu_io(base_img_path, '-c', cmd)
50
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
268
51
break;
269
log('')
52
}
270
log('Done')
53
271
diff --git a/tests/qemu-iotests/tests/mirror-ready-cancel-error b/tests/qemu-iotests/tests/mirror-ready-cancel-error
54
- free_aio_req(s, aio_req);
272
index XXXXXXX..XXXXXXX 100755
55
- if (!acb->nr_pending) {
273
--- a/tests/qemu-iotests/tests/mirror-ready-cancel-error
56
+ g_free(aio_req);
274
+++ b/tests/qemu-iotests/tests/mirror-ready-cancel-error
57
+
275
@@ -XXX,XX +XXX,XX @@ class TestMirrorReadyCancelError(iotests.QMPTestCase):
58
+ if (!--acb->nr_pending) {
276
# Ensure that mirror will copy something before READY so the
59
/*
277
# target format layer will forward the pre-READY flush to its
60
* We've finished all requests which belong to the AIOCB, so
278
# file child
61
* we can switch back to sd_co_readv/writev now.
279
- assert iotests.qemu_io_silent('-c', 'write -P 1 0 64k', source) == 0
62
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
280
+ iotests.qemu_io('-c', 'write -P 1 0 64k', source)
63
uint64_t old_oid = aio_req->base_oid;
281
64
bool create = aio_req->create;
282
self.vm = iotests.VM()
65
283
self.vm.launch()
66
+ QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
284
diff --git a/tests/qemu-iotests/tests/stream-error-on-reset b/tests/qemu-iotests/tests/stream-error-on-reset
67
+
285
index XXXXXXX..XXXXXXX 100755
68
if (!nr_copies) {
286
--- a/tests/qemu-iotests/tests/stream-error-on-reset
69
error_report("bug");
287
+++ b/tests/qemu-iotests/tests/stream-error-on-reset
70
}
288
@@ -XXX,XX +XXX,XX @@
71
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
289
72
iov.iov_len = sizeof(s->inode);
290
import os
73
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
291
import iotests
74
data_len, offset, 0, false, 0, offset);
292
-from iotests import imgfmt, qemu_img_create, qemu_io_silent, QMPTestCase
75
- QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
293
+from iotests import imgfmt, qemu_img_create, qemu_io, QMPTestCase
76
add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
294
77
if (--acb->nr_pending) {
295
78
qemu_coroutine_yield();
296
image_size = 1 * 1024 * 1024
79
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_co_rw_vector(SheepdogAIOCB *acb)
297
@@ -XXX,XX +XXX,XX @@ class TestStreamErrorOnReset(QMPTestCase):
80
old_oid,
298
- top image is attached to a virtio-scsi device
81
acb->aiocb_type == AIOCB_DISCARD_OBJ ?
299
"""
82
0 : done);
300
qemu_img_create('-f', imgfmt, base, str(image_size))
83
- QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
301
- assert qemu_io_silent('-c', f'write 0 {data_size}', base) == 0
84
-
302
+ qemu_io('-c', f'write 0 {data_size}', base)
85
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
303
qemu_img_create('-f', imgfmt, top, str(image_size))
86
acb->aiocb_type);
304
87
done:
305
self.vm = iotests.VM()
88
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
89
acb.nr_pending++;
90
aio_req = alloc_aio_req(s, &acb, vid_to_vdi_oid(s->inode.vdi_id),
91
0, 0, 0, false, 0, 0);
92
- QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
93
add_aio_request(s, aio_req, NULL, 0, acb.aiocb_type);
94
95
if (--acb.nr_pending) {
96
--
306
--
97
2.9.3
307
2.35.1
98
99
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
Delimit co_recv's lifetime clearly in aio_read_response.
3
Just like qemu_img_log(), upgrade qemu_io_log() to enforce a return code
4
of zero by default.
4
5
5
Do a simple qemu_coroutine_enter in aio_read_response, letting
6
Tests that use qemu_io_log(): 242 245 255 274 303 307 nbd-reconnect-on-open
6
sd_co_writev call sd_write_done.
7
7
8
Handle nr_pending in the same way in sd_co_rw_vector,
8
Signed-off-by: John Snow <jsnow@redhat.com>
9
sd_write_done and sd_co_flush_to_disk.
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220418211504.943969-13-jsnow@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
tests/qemu-iotests/iotests.py | 5 +++--
15
tests/qemu-iotests/tests/nbd-reconnect-on-open | 2 +-
16
2 files changed, 4 insertions(+), 3 deletions(-)
10
17
11
Remove sd_co_rw_vector's return value; just leave with no
18
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
pending requests.
13
14
[Jeff: added missing 'return' back, spotted by Paolo after
15
series was applied.]
16
17
Signed-off-by: Jeff Cody <jcody@redhat.com>
18
---
19
block/sheepdog.c | 115 ++++++++++++++++++++-----------------------------------
20
1 file changed, 42 insertions(+), 73 deletions(-)
21
22
diff --git a/block/sheepdog.c b/block/sheepdog.c
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/block/sheepdog.c
20
--- a/tests/qemu-iotests/iotests.py
25
+++ b/block/sheepdog.c
21
+++ b/tests/qemu-iotests/iotests.py
26
@@ -XXX,XX +XXX,XX @@ struct SheepdogAIOCB {
22
@@ -XXX,XX +XXX,XX @@ def qemu_io(*args: str, check: bool = True, combine_stdio: bool = True
27
enum AIOCBState aiocb_type;
23
return qemu_tool(*qemu_io_wrap_args(args),
28
24
check=check, combine_stdio=combine_stdio)
29
Coroutine *coroutine;
25
30
- void (*aio_done_func)(SheepdogAIOCB *);
26
-def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
31
-
27
- result = qemu_io(*args, check=False)
32
int nr_pending;
28
+def qemu_io_log(*args: str, check: bool = True
33
29
+ ) -> 'subprocess.CompletedProcess[str]':
34
uint32_t min_affect_data_idx;
30
+ result = qemu_io(*args, check=check)
35
@@ -XXX,XX +XXX,XX @@ static const char * sd_strerror(int err)
31
log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
36
*
32
return result
37
* 1. In sd_co_rw_vector, we send the I/O requests to the server and
33
38
* link the requests to the inflight_list in the
34
diff --git a/tests/qemu-iotests/tests/nbd-reconnect-on-open b/tests/qemu-iotests/tests/nbd-reconnect-on-open
39
- * BDRVSheepdogState. The function exits without waiting for
35
index XXXXXXX..XXXXXXX 100755
40
+ * BDRVSheepdogState. The function yields while waiting for
36
--- a/tests/qemu-iotests/tests/nbd-reconnect-on-open
41
* receiving the response.
37
+++ b/tests/qemu-iotests/tests/nbd-reconnect-on-open
42
*
38
@@ -XXX,XX +XXX,XX @@ def check_fail_to_connect(open_timeout):
43
* 2. We receive the response in aio_read_response, the fd handler to
39
log(f'Check fail to connect with {open_timeout} seconds of timeout')
44
- * the sheepdog connection. If metadata update is needed, we send
40
45
- * the write request to the vdi object in sd_write_done, the write
41
start_t = time.time()
46
- * completion function. We switch back to sd_co_readv/writev after
42
- qemu_io_log(*create_args(open_timeout))
47
- * all the requests belonging to the AIOCB are finished.
43
+ qemu_io_log(*create_args(open_timeout), check=False)
48
+ * the sheepdog connection. We switch back to sd_co_readv/sd_writev
44
delta_t = time.time() - start_t
49
+ * after all the requests belonging to the AIOCB are finished. If
45
50
+ * needed, sd_co_writev will send another requests for the vdi object.
46
max_delta = open_timeout + 0.2
51
*/
52
53
static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
54
@@ -XXX,XX +XXX,XX @@ static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req)
55
acb->nr_pending--;
56
}
57
58
-static void coroutine_fn sd_finish_aiocb(SheepdogAIOCB *acb)
59
-{
60
- qemu_coroutine_enter(acb->coroutine);
61
- qemu_aio_unref(acb);
62
-}
63
-
64
static const AIOCBInfo sd_aiocb_info = {
65
.aiocb_size = sizeof(SheepdogAIOCB),
66
};
67
@@ -XXX,XX +XXX,XX @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
68
acb->sector_num = sector_num;
69
acb->nb_sectors = nb_sectors;
70
71
- acb->aio_done_func = NULL;
72
acb->coroutine = qemu_coroutine_self();
73
acb->ret = 0;
74
acb->nr_pending = 0;
75
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
76
77
switch (acb->aiocb_type) {
78
case AIOCB_WRITE_UDATA:
79
- /* this coroutine context is no longer suitable for co_recv
80
- * because we may send data to update vdi objects */
81
- s->co_recv = NULL;
82
if (!is_data_obj(aio_req->oid)) {
83
break;
84
}
85
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
86
}
87
}
88
89
+ /* No more data for this aio_req (reload_inode below uses its own file
90
+ * descriptor handler which doesn't use co_recv).
91
+ */
92
+ s->co_recv = NULL;
93
+
94
switch (rsp.result) {
95
case SD_RES_SUCCESS:
96
break;
97
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
98
aio_req->oid = vid_to_vdi_oid(s->inode.vdi_id);
99
}
100
resend_aioreq(s, aio_req);
101
- goto out;
102
+ return;
103
default:
104
acb->ret = -EIO;
105
error_report("%s", sd_strerror(rsp.result));
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
107
* We've finished all requests which belong to the AIOCB, so
108
* we can switch back to sd_co_readv/writev now.
109
*/
110
- acb->aio_done_func(acb);
111
+ qemu_coroutine_enter(acb->coroutine);
112
}
113
-out:
114
- s->co_recv = NULL;
115
+
116
return;
117
+
118
err:
119
- s->co_recv = NULL;
120
reconnect_to_sdog(opaque);
121
}
122
123
@@ -XXX,XX +XXX,XX @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
124
/*
125
* This function is called after writing data objects. If we need to
126
* update metadata, this sends a write request to the vdi object.
127
- * Otherwise, this switches back to sd_co_readv/writev.
128
*/
129
static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
130
{
131
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
132
mx = acb->max_dirty_data_idx;
133
if (mn <= mx) {
134
/* we need to update the vdi object. */
135
+ ++acb->nr_pending;
136
offset = sizeof(s->inode) - sizeof(s->inode.data_vdi_id) +
137
mn * sizeof(s->inode.data_vdi_id[0]);
138
data_len = (mx - mn + 1) * sizeof(s->inode.data_vdi_id[0]);
139
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
140
data_len, offset, 0, false, 0, offset);
141
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
142
add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
143
-
144
- acb->aio_done_func = sd_finish_aiocb;
145
- acb->aiocb_type = AIOCB_WRITE_UDATA;
146
- return;
147
+ if (--acb->nr_pending) {
148
+ qemu_coroutine_yield();
149
+ }
150
}
151
-
152
- sd_finish_aiocb(acb);
153
}
154
155
/* Delete current working VDI on the snapshot chain */
156
@@ -XXX,XX +XXX,XX @@ out:
157
* Returns 1 when we need to wait a response, 0 when there is no sent
158
* request and -errno in error cases.
159
*/
160
-static int coroutine_fn sd_co_rw_vector(void *p)
161
+static void coroutine_fn sd_co_rw_vector(void *p)
162
{
163
SheepdogAIOCB *acb = p;
164
int ret = 0;
165
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_rw_vector(void *p)
166
ret = sd_create_branch(s);
167
if (ret) {
168
acb->ret = -EIO;
169
- goto out;
170
+ return;
171
}
172
}
173
174
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_rw_vector(void *p)
175
idx++;
176
done += len;
177
}
178
-out:
179
- if (!--acb->nr_pending) {
180
- return acb->ret;
181
+ if (--acb->nr_pending) {
182
+ qemu_coroutine_yield();
183
}
184
- return 1;
185
}
186
187
static bool check_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *aiocb)
188
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
189
}
190
191
acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
192
- acb->aio_done_func = sd_write_done;
193
acb->aiocb_type = AIOCB_WRITE_UDATA;
194
195
retry:
196
@@ -XXX,XX +XXX,XX @@ retry:
197
goto retry;
198
}
199
200
- ret = sd_co_rw_vector(acb);
201
- if (ret <= 0) {
202
- QLIST_REMOVE(acb, aiocb_siblings);
203
- qemu_co_queue_restart_all(&s->overlapping_queue);
204
- qemu_aio_unref(acb);
205
- return ret;
206
- }
207
-
208
- qemu_coroutine_yield();
209
+ sd_co_rw_vector(acb);
210
+ sd_write_done(acb);
211
212
QLIST_REMOVE(acb, aiocb_siblings);
213
qemu_co_queue_restart_all(&s->overlapping_queue);
214
-
215
- return acb->ret;
216
+ ret = acb->ret;
217
+ qemu_aio_unref(acb);
218
+ return ret;
219
}
220
221
static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
222
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
223
224
acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
225
acb->aiocb_type = AIOCB_READ_UDATA;
226
- acb->aio_done_func = sd_finish_aiocb;
227
228
retry:
229
if (check_overlapping_aiocb(s, acb)) {
230
@@ -XXX,XX +XXX,XX @@ retry:
231
goto retry;
232
}
233
234
- ret = sd_co_rw_vector(acb);
235
- if (ret <= 0) {
236
- QLIST_REMOVE(acb, aiocb_siblings);
237
- qemu_co_queue_restart_all(&s->overlapping_queue);
238
- qemu_aio_unref(acb);
239
- return ret;
240
- }
241
-
242
- qemu_coroutine_yield();
243
+ sd_co_rw_vector(acb);
244
245
QLIST_REMOVE(acb, aiocb_siblings);
246
qemu_co_queue_restart_all(&s->overlapping_queue);
247
- return acb->ret;
248
+ ret = acb->ret;
249
+ qemu_aio_unref(acb);
250
+ return ret;
251
}
252
253
static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
254
{
255
BDRVSheepdogState *s = bs->opaque;
256
SheepdogAIOCB *acb;
257
+ int ret;
258
AIOReq *aio_req;
259
260
if (s->cache_flags != SD_FLAG_CMD_CACHE) {
261
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
262
263
acb = sd_aio_setup(bs, NULL, 0, 0);
264
acb->aiocb_type = AIOCB_FLUSH_CACHE;
265
- acb->aio_done_func = sd_finish_aiocb;
266
267
+ acb->nr_pending++;
268
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
269
0, 0, 0, false, 0, 0);
270
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
271
add_aio_request(s, aio_req, NULL, 0, acb->aiocb_type);
272
273
- qemu_coroutine_yield();
274
- return acb->ret;
275
+ if (--acb->nr_pending) {
276
+ qemu_coroutine_yield();
277
+ }
278
+ ret = acb->ret;
279
+ qemu_aio_unref(acb);
280
+ return ret;
281
}
282
283
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
284
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
285
acb = sd_aio_setup(bs, &discard_iov, offset >> BDRV_SECTOR_BITS,
286
count >> BDRV_SECTOR_BITS);
287
acb->aiocb_type = AIOCB_DISCARD_OBJ;
288
- acb->aio_done_func = sd_finish_aiocb;
289
290
retry:
291
if (check_overlapping_aiocb(s, acb)) {
292
@@ -XXX,XX +XXX,XX @@ retry:
293
goto retry;
294
}
295
296
- ret = sd_co_rw_vector(acb);
297
- if (ret <= 0) {
298
- QLIST_REMOVE(acb, aiocb_siblings);
299
- qemu_co_queue_restart_all(&s->overlapping_queue);
300
- qemu_aio_unref(acb);
301
- return ret;
302
- }
303
-
304
- qemu_coroutine_yield();
305
+ sd_co_rw_vector(acb);
306
307
QLIST_REMOVE(acb, aiocb_siblings);
308
qemu_co_queue_restart_all(&s->overlapping_queue);
309
-
310
- return acb->ret;
311
+ ret = acb->ret;
312
+ qemu_aio_unref(acb);
313
+ return ret;
314
}
315
316
static coroutine_fn int64_t
317
--
47
--
318
2.9.3
48
2.35.1
319
320
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
FUSE exports' allow-other option defaults to "auto", which means that it
2
will try passing allow_other as a mount option, and fall back to not
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.
2
9
3
SheepdogAIOCB is internal to sheepdog.c, hence it is never canceled.
10
We do not need allow_other here, though, so we can just pass
11
allow-other=off to fix that.
4
12
5
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
13
Reported-by: Markus Armbruster <armbru@redhat.com>
6
Message-id: 20161129113245.32724-2-pbonzini@redhat.com
14
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
15
Message-Id: <20220421142435.569600-1-hreitz@redhat.com>
16
Tested-by: Markus Armbruster <armbru@redhat.com>
17
Tested-by: Eric Blake <eblake@redhat.com>
8
---
18
---
9
block/sheepdog.c | 52 ----------------------------------------------------
19
tests/qemu-iotests/108 | 2 +-
10
1 file changed, 52 deletions(-)
20
1 file changed, 1 insertion(+), 1 deletion(-)
11
21
12
diff --git a/block/sheepdog.c b/block/sheepdog.c
22
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100755
14
--- a/block/sheepdog.c
24
--- a/tests/qemu-iotests/108
15
+++ b/block/sheepdog.c
25
+++ b/tests/qemu-iotests/108
16
@@ -XXX,XX +XXX,XX @@ struct SheepdogAIOCB {
26
@@ -XXX,XX +XXX,XX @@ else
17
Coroutine *coroutine;
27
18
void (*aio_done_func)(SheepdogAIOCB *);
28
$QSD \
19
29
--blockdev file,node-name=export-node,filename="$TEST_IMG" \
20
- bool cancelable;
30
- --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=off \
21
int nr_pending;
31
+ --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=off,allow-other=off \
22
32
--pidfile "$TEST_DIR/qsd.pid" \
23
uint32_t min_affect_data_idx;
33
--daemonize
24
@@ -XXX,XX +XXX,XX @@ static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req)
34
fi
25
{
26
SheepdogAIOCB *acb = aio_req->aiocb;
27
28
- acb->cancelable = false;
29
QLIST_REMOVE(aio_req, aio_siblings);
30
g_free(aio_req);
31
32
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_finish_aiocb(SheepdogAIOCB *acb)
33
qemu_aio_unref(acb);
34
}
35
36
-/*
37
- * Check whether the specified acb can be canceled
38
- *
39
- * We can cancel aio when any request belonging to the acb is:
40
- * - Not processed by the sheepdog server.
41
- * - Not linked to the inflight queue.
42
- */
43
-static bool sd_acb_cancelable(const SheepdogAIOCB *acb)
44
-{
45
- BDRVSheepdogState *s = acb->common.bs->opaque;
46
- AIOReq *aioreq;
47
-
48
- if (!acb->cancelable) {
49
- return false;
50
- }
51
-
52
- QLIST_FOREACH(aioreq, &s->inflight_aio_head, aio_siblings) {
53
- if (aioreq->aiocb == acb) {
54
- return false;
55
- }
56
- }
57
-
58
- return true;
59
-}
60
-
61
-static void sd_aio_cancel(BlockAIOCB *blockacb)
62
-{
63
- SheepdogAIOCB *acb = (SheepdogAIOCB *)blockacb;
64
- BDRVSheepdogState *s = acb->common.bs->opaque;
65
- AIOReq *aioreq, *next;
66
-
67
- if (sd_acb_cancelable(acb)) {
68
- /* Remove outstanding requests from failed queue. */
69
- QLIST_FOREACH_SAFE(aioreq, &s->failed_aio_head, aio_siblings,
70
- next) {
71
- if (aioreq->aiocb == acb) {
72
- free_aio_req(s, aioreq);
73
- }
74
- }
75
-
76
- assert(acb->nr_pending == 0);
77
- if (acb->common.cb) {
78
- acb->common.cb(acb->common.opaque, -ECANCELED);
79
- }
80
- sd_finish_aiocb(acb);
81
- }
82
-}
83
-
84
static const AIOCBInfo sd_aiocb_info = {
85
.aiocb_size = sizeof(SheepdogAIOCB),
86
- .cancel_async = sd_aio_cancel,
87
};
88
89
static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
90
@@ -XXX,XX +XXX,XX @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
91
acb->nb_sectors = nb_sectors;
92
93
acb->aio_done_func = NULL;
94
- acb->cancelable = true;
95
acb->coroutine = qemu_coroutine_self();
96
acb->ret = 0;
97
acb->nr_pending = 0;
98
--
35
--
99
2.9.3
36
2.35.1
100
101
diff view generated by jsdifflib