1
The following changes since commit f17783e706ab9c7b3a2b69cf48e4f0ba40664f54:
1
The following changes since commit 31ee895047bdcf7387e3570cbd2a473c6f744b08:
2
2
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20191220' into staging (2020-01-03 18:50:33 +0000)
3
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging (2021-01-25 15:56:13 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-01-06
7
https://github.com/XanClic/qemu.git tags/pull-block-2021-01-26
8
8
9
for you to fetch changes up to 503ca1262bab2c11c533a4816d1ff4297d4f58a6:
9
for you to fetch changes up to bb24cdc5efee580e81f71c5ff0fd980f2cc179d0:
10
10
11
backup-top: Begin drain earlier (2020-01-06 14:26:23 +0100)
11
iotests/178: Pass value to invalid option (2021-01-26 14:36:37 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Block patches:
15
- Minor fixes and tests from the freeze period (too minor to be included
15
- Make backup block jobs use asynchronous requests with the block-copy
16
in 4.2)
16
module
17
- Allow many bash iotests to test qcow2's external data file feature
17
- Use COR filter node for stream block jobs
18
- Add compress filter driver
18
- Make coroutine-sigaltstack’s qemu_coroutine_new() function thread-safe
19
- Fix Python iotests after 6f6e1698a6
19
- Report error string when file locking fails with an unexpected errno
20
- Fix for the backup job
20
- iotest fixes, additions, and some refactoring
21
21
22
----------------------------------------------------------------
22
----------------------------------------------------------------
23
Andrey Shinkevich (3):
23
Alberto Garcia (1):
24
block: introduce compress filter driver
24
iotests: Add test for the regression fixed in c8bf9a9169
25
qcow2: Allow writing compressed data of multiple clusters
26
tests/qemu-iotests: add case to write compressed data of multiple
27
clusters
28
25
29
Max Reitz (28):
26
Andrey Shinkevich (10):
30
block: Add bdrv_qapi_perm_to_blk_perm()
27
copy-on-read: support preadv/pwritev_part functions
31
block: Use bdrv_qapi_perm_to_blk_perm()
28
block: add API function to insert a node
32
blkdebug: Allow taking/unsharing permissions
29
copy-on-read: add filter drop function
33
iotests: Add @error to wait_until_completed
30
qapi: add filter-node-name to block-stream
34
iotests: Add test for failing mirror complete
31
qapi: copy-on-read filter: add 'bottom' option
35
iotests: s/qocw2/qcow2/
32
iotests: add #310 to test bottom node in COR driver
36
iotests/qcow2.py: Add dump-header-exts
33
block: include supported_read_flags into BDS structure
37
iotests/qcow2.py: Split feature fields into bits
34
copy-on-read: skip non-guest reads if no copy needed
38
iotests: Add _filter_json_filename
35
stream: rework backing-file changing
39
iotests: Filter refcount_order in 036
36
block: apply COR-filter to block-stream jobs
40
iotests: Replace IMGOPTS by _unsupported_imgopts
41
iotests: Drop compat=1.1 in 050
42
iotests: Let _make_test_img parse its parameters
43
iotests: Add -o and --no-opts to _make_test_img
44
iotests: Inject space into -ocompat=0.10 in 051
45
iotests: Replace IMGOPTS= by -o
46
iotests: Replace IMGOPTS='' by --no-opts
47
iotests: Drop IMGOPTS use in 267
48
iotests: Avoid qemu-img create
49
iotests: Use _rm_test_img for deleting test images
50
iotests: Avoid cp/mv of test images
51
iotests: Make 091 work with data_file
52
iotests: Make 110 work with data_file
53
iotests: Make 137 work with data_file
54
iotests: Make 198 work with data_file
55
iotests: Disable data_file where it cannot be used
56
iotests: Allow check -o data_file
57
backup-top: Begin drain earlier
58
37
59
PanNengyuan (1):
38
David Edmondson (1):
60
throttle-groups: fix memory leak in throttle_group_set_limit:
39
block: report errno when flock fcntl fails
61
40
62
Philippe Mathieu-Daudé (1):
41
Max Reitz (14):
63
tests/qemu-iotests: Update tests to recent desugarized -accel option
42
iotests.py: Assume a couple of variables as given
43
iotests/297: Rewrite in Python and extend reach
44
iotests: Move try_remove to iotests.py
45
iotests/129: Remove test images in tearDown()
46
iotests/129: Do not check @busy
47
iotests/129: Use throttle node
48
iotests/129: Actually test a commit job
49
iotests/129: Limit mirror job's buffer size
50
iotests/129: Clean up pylint and mypy complaints
51
iotests/300: Clean up pylint and mypy complaints
52
coroutine-sigaltstack: Add SIGUSR2 mutex
53
iotests/129: Limit backup's max-chunk/max-workers
54
iotests/118: Drop 'change' test
55
iotests/178: Pass value to invalid option
64
56
65
Vladimir Sementsov-Ogievskiy (1):
57
Vladimir Sementsov-Ogievskiy (27):
66
qcow2-bitmaps: fix qcow2_can_store_new_dirty_bitmap
58
iotests: fix _check_o_direct
59
qapi: block-stream: add "bottom" argument
60
iotests: 30: prepare to COR filter insertion by stream job
61
block/stream: add s->target_bs
62
qapi: backup: add perf.use-copy-range parameter
63
block/block-copy: More explicit call_state
64
block/block-copy: implement block_copy_async
65
block/block-copy: add max_chunk and max_workers parameters
66
block/block-copy: add list of all call-states
67
block/block-copy: add ratelimit to block-copy
68
block/block-copy: add block_copy_cancel
69
blockjob: add set_speed to BlockJobDriver
70
job: call job_enter from job_pause
71
qapi: backup: add max-chunk and max-workers to x-perf struct
72
iotests: 56: prepare for backup over block-copy
73
iotests: 185: prepare for backup over block-copy
74
iotests: 219: prepare for backup over block-copy
75
iotests: 257: prepare for backup over block-copy
76
block/block-copy: make progress_bytes_callback optional
77
block/backup: drop extra gotos from backup_run()
78
backup: move to block-copy
79
qapi: backup: disable copy_range by default
80
block/block-copy: drop unused block_copy_set_progress_callback()
81
block/block-copy: drop unused argument of block_copy()
82
simplebench/bench_block_job: use correct shebang line with python3
83
simplebench: bench_block_job: add cmd_options argument
84
simplebench: add bench-backup.py
67
85
68
block.c | 47 +++++----
86
qapi/block-core.json | 66 +++++-
69
block/Makefile.objs | 1 +
87
block/backup-top.h | 1 +
70
block/backup-top.c | 4 +-
88
block/copy-on-read.h | 32 +++
71
block/blkdebug.c | 93 ++++++++++++++++-
89
include/block/block-copy.h | 61 ++++-
72
block/filter-compress.c | 168 +++++++++++++++++++++++++++++++
90
include/block/block.h | 10 +-
73
block/qcow2-bitmap.c | 41 ++++----
91
include/block/block_int.h | 15 +-
74
block/qcow2.c | 102 ++++++++++++++-----
92
include/block/blockjob_int.h | 2 +
75
block/throttle-groups.c | 4 +-
93
block.c | 25 ++
76
include/block/block.h | 1 +
94
block/backup-top.c | 6 +-
77
qapi/block-core.json | 24 ++++-
95
block/backup.c | 233 ++++++++++++-------
78
tests/qemu-iotests/007 | 5 +-
96
block/block-copy.c | 227 +++++++++++++++---
79
tests/qemu-iotests/014 | 2 +
97
block/copy-on-read.c | 184 ++++++++++++++-
80
tests/qemu-iotests/015 | 5 +-
98
block/file-posix.c | 38 ++-
81
tests/qemu-iotests/019 | 6 +-
99
block/io.c | 10 +-
82
tests/qemu-iotests/020 | 6 +-
100
block/monitor/block-hmp-cmds.c | 7 +-
83
tests/qemu-iotests/024 | 10 +-
101
block/replication.c | 2 +
84
tests/qemu-iotests/026 | 5 +-
102
block/stream.c | 185 +++++++++------
85
tests/qemu-iotests/028 | 2 +-
103
blockdev.c | 83 +++++--
86
tests/qemu-iotests/029 | 7 +-
104
blockjob.c | 6 +
87
tests/qemu-iotests/031 | 9 +-
105
job.c | 3 +
88
tests/qemu-iotests/031.out | 36 +++----
106
util/coroutine-sigaltstack.c | 9 +
89
tests/qemu-iotests/036 | 15 +--
107
scripts/simplebench/bench-backup.py | 167 ++++++++++++++
90
tests/qemu-iotests/036.out | 66 ++----------
108
scripts/simplebench/bench-example.py | 2 +-
91
tests/qemu-iotests/039 | 27 ++---
109
scripts/simplebench/bench_block_job.py | 13 +-
92
tests/qemu-iotests/039.out | 22 ++--
110
tests/qemu-iotests/030 | 12 +-
93
tests/qemu-iotests/041 | 44 ++++++++
111
tests/qemu-iotests/056 | 9 +-
94
tests/qemu-iotests/041.out | 4 +-
112
tests/qemu-iotests/109.out | 24 ++
95
tests/qemu-iotests/043 | 4 +-
113
tests/qemu-iotests/118 | 20 +-
96
tests/qemu-iotests/046 | 2 +
114
tests/qemu-iotests/118.out | 4 +-
97
tests/qemu-iotests/048 | 4 +-
115
tests/qemu-iotests/124 | 8 +-
98
tests/qemu-iotests/050 | 8 +-
116
tests/qemu-iotests/129 | 79 ++++---
99
tests/qemu-iotests/051 | 7 +-
117
tests/qemu-iotests/141.out | 2 +-
100
tests/qemu-iotests/053 | 4 +-
118
tests/qemu-iotests/178 | 2 +-
101
tests/qemu-iotests/058 | 7 +-
119
tests/qemu-iotests/178.out.qcow2 | 2 +-
102
tests/qemu-iotests/059 | 20 ++--
120
tests/qemu-iotests/178.out.raw | 2 +-
103
tests/qemu-iotests/060 | 14 +--
121
tests/qemu-iotests/185 | 3 +-
104
tests/qemu-iotests/060.out | 20 ++--
122
tests/qemu-iotests/185.out | 3 +-
105
tests/qemu-iotests/061 | 63 ++++++------
123
tests/qemu-iotests/219 | 13 +-
106
tests/qemu-iotests/061.out | 72 ++++++-------
124
tests/qemu-iotests/245 | 20 +-
107
tests/qemu-iotests/062 | 5 +-
125
tests/qemu-iotests/257 | 1 +
108
tests/qemu-iotests/063 | 18 ++--
126
tests/qemu-iotests/257.out | 306 ++++++++++++-------------
109
tests/qemu-iotests/063.out | 3 +-
127
tests/qemu-iotests/297 | 112 +++++++--
110
tests/qemu-iotests/066 | 7 +-
128
tests/qemu-iotests/297.out | 5 +-
111
tests/qemu-iotests/067 | 6 +-
129
tests/qemu-iotests/300 | 19 +-
112
tests/qemu-iotests/068 | 6 +-
130
tests/qemu-iotests/310 | 117 ++++++++++
113
tests/qemu-iotests/069 | 2 +-
131
tests/qemu-iotests/310.out | 15 ++
114
tests/qemu-iotests/071 | 7 +-
132
tests/qemu-iotests/313 | 104 +++++++++
115
tests/qemu-iotests/073 | 4 +
133
tests/qemu-iotests/313.out | 29 +++
116
tests/qemu-iotests/074 | 4 +-
134
tests/qemu-iotests/common.rc | 7 +-
117
tests/qemu-iotests/079 | 3 +-
135
tests/qemu-iotests/group | 2 +
118
tests/qemu-iotests/080 | 7 +-
136
tests/qemu-iotests/iotests.py | 37 +--
119
tests/qemu-iotests/081 | 6 +-
137
51 files changed, 1797 insertions(+), 547 deletions(-)
120
tests/qemu-iotests/085 | 18 ++--
138
create mode 100644 block/copy-on-read.h
121
tests/qemu-iotests/085.out | 8 +-
139
create mode 100755 scripts/simplebench/bench-backup.py
122
tests/qemu-iotests/088 | 2 +-
140
create mode 100755 tests/qemu-iotests/310
123
tests/qemu-iotests/090 | 2 +
141
create mode 100644 tests/qemu-iotests/310.out
124
tests/qemu-iotests/091 | 2 +-
142
create mode 100755 tests/qemu-iotests/313
125
tests/qemu-iotests/091.out | 2 -
143
create mode 100644 tests/qemu-iotests/313.out
126
tests/qemu-iotests/092 | 2 +-
127
tests/qemu-iotests/094 | 4 +-
128
tests/qemu-iotests/095 | 5 +-
129
tests/qemu-iotests/098 | 6 +-
130
tests/qemu-iotests/099 | 10 +-
131
tests/qemu-iotests/103 | 5 +-
132
tests/qemu-iotests/106 | 2 +-
133
tests/qemu-iotests/108 | 10 +-
134
tests/qemu-iotests/109 | 4 +-
135
tests/qemu-iotests/110 | 11 +-
136
tests/qemu-iotests/110.out | 4 +-
137
tests/qemu-iotests/111 | 3 +-
138
tests/qemu-iotests/112 | 37 +++----
139
tests/qemu-iotests/114 | 2 +
140
tests/qemu-iotests/115 | 3 +-
141
tests/qemu-iotests/121 | 9 +-
142
tests/qemu-iotests/122 | 6 +-
143
tests/qemu-iotests/123 | 4 +-
144
tests/qemu-iotests/125 | 2 +-
145
tests/qemu-iotests/137 | 17 +++-
146
tests/qemu-iotests/137.out | 6 +-
147
tests/qemu-iotests/138 | 8 +-
148
tests/qemu-iotests/141 | 4 +-
149
tests/qemu-iotests/142 | 2 +-
150
tests/qemu-iotests/144 | 4 +-
151
tests/qemu-iotests/153 | 12 +--
152
tests/qemu-iotests/156 | 10 +-
153
tests/qemu-iotests/159 | 2 +-
154
tests/qemu-iotests/160 | 3 +-
155
tests/qemu-iotests/161 | 4 +-
156
tests/qemu-iotests/170 | 2 +-
157
tests/qemu-iotests/172 | 6 +-
158
tests/qemu-iotests/173 | 3 +-
159
tests/qemu-iotests/174 | 2 +-
160
tests/qemu-iotests/175 | 2 +-
161
tests/qemu-iotests/176 | 7 +-
162
tests/qemu-iotests/178 | 6 +-
163
tests/qemu-iotests/182 | 2 +-
164
tests/qemu-iotests/183 | 2 +-
165
tests/qemu-iotests/185 | 4 +-
166
tests/qemu-iotests/187 | 6 +-
167
tests/qemu-iotests/190 | 4 +-
168
tests/qemu-iotests/191 | 11 +-
169
tests/qemu-iotests/195 | 2 +-
170
tests/qemu-iotests/197 | 6 +-
171
tests/qemu-iotests/198 | 6 +-
172
tests/qemu-iotests/198.out | 4 +-
173
tests/qemu-iotests/200 | 7 +-
174
tests/qemu-iotests/201 | 6 +-
175
tests/qemu-iotests/214 | 46 ++++++++-
176
tests/qemu-iotests/214.out | 14 +++
177
tests/qemu-iotests/215 | 6 +-
178
tests/qemu-iotests/217 | 3 +-
179
tests/qemu-iotests/220 | 5 +-
180
tests/qemu-iotests/225 | 2 +-
181
tests/qemu-iotests/229 | 3 +-
182
tests/qemu-iotests/232 | 4 +-
183
tests/qemu-iotests/235 | 2 +-
184
tests/qemu-iotests/243 | 10 +-
185
tests/qemu-iotests/244 | 15 +--
186
tests/qemu-iotests/247 | 4 +-
187
tests/qemu-iotests/249 | 4 +-
188
tests/qemu-iotests/250 | 5 +-
189
tests/qemu-iotests/252 | 2 +-
190
tests/qemu-iotests/261 | 5 +-
191
tests/qemu-iotests/265 | 2 +-
192
tests/qemu-iotests/267 | 17 ++--
193
tests/qemu-iotests/273 | 3 +
194
tests/qemu-iotests/check | 6 +-
195
tests/qemu-iotests/common.filter | 47 ++++++++-
196
tests/qemu-iotests/common.rc | 63 ++++++++++--
197
tests/qemu-iotests/iotests.py | 18 ++--
198
tests/qemu-iotests/qcow2.py | 23 ++++-
199
131 files changed, 1139 insertions(+), 552 deletions(-)
200
create mode 100644 block/filter-compress.c
201
144
202
--
145
--
203
2.24.1
146
2.29.2
204
147
205
148
diff view generated by jsdifflib
1
Blindly overriding IMGOPTS is suboptimal as this discards user-specified
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
options. Whatever options the test needs should simply be appended.
3
2
4
Some tests do this (with IMGOPTS=$(_optstr_add "$IMGOPTS" "...")), but
3
Unfortunately commit "iotests: handle tmpfs" breaks running iotests
5
that is cumbersome. It’s simpler to just give _make_test_img an -o
4
with -nbd -nocache, as _check_o_direct tries to create
6
parameter with which tests can add options.
5
$TEST_IMG.test_o_direct, but in case of nbd TEST_IMG is something like
6
nbd+unix:///... , and test fails with message
7
7
8
Some tests actually must override the user-specified options, though,
8
qemu-img: nbd+unix:///?socket[...]test_o_direct: Protocol driver
9
for example when creating an image in a different format than the test
9
'nbd' does not support image creation, and opening the image
10
$IMGFMT. For such cases, --no-opts allows clearing the current option
10
failed: Failed to connect to '/tmp/tmp.[...]/nbd/test_o_direct': No
11
list.
11
such file or directory
12
12
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Use TEST_DIR instead.
14
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
14
15
Message-id: 20191107163708.833192-10-mreitz@redhat.com
15
Fixes: cfdca2b9f9d4ca26bb2b2dfe8de3149092e39170
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Message-Id: <20201218182012.47607-1-vsementsov@virtuozzo.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
19
---
18
tests/qemu-iotests/common.rc | 13 +++++++++++++
20
tests/qemu-iotests/common.rc | 7 ++++---
19
1 file changed, 13 insertions(+)
21
1 file changed, 4 insertions(+), 3 deletions(-)
20
22
21
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
23
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
22
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
23
--- a/tests/qemu-iotests/common.rc
25
--- a/tests/qemu-iotests/common.rc
24
+++ b/tests/qemu-iotests/common.rc
26
+++ b/tests/qemu-iotests/common.rc
25
@@ -XXX,XX +XXX,XX @@ _make_test_img()
27
@@ -XXX,XX +XXX,XX @@ _supported_cache_modes()
26
local use_backing=0
28
# Check whether the filesystem supports O_DIRECT
27
local backing_file=""
29
_check_o_direct()
28
local object_options=""
30
{
29
+ local opts_param=false
31
- $QEMU_IMG create -f raw "$TEST_IMG".test_o_direct 1M > /dev/null
30
local misc_params=()
32
- out=$($QEMU_IO -f raw -t none -c quit "$TEST_IMG".test_o_direct 2>&1)
31
33
- rm -f "$TEST_IMG".test_o_direct
32
if [ -n "$TEST_IMG_FILE" ]; then
34
+ testfile="$TEST_DIR"/_check_o_direct
33
@@ -XXX,XX +XXX,XX @@ _make_test_img()
35
+ $QEMU_IMG create -f raw "$testfile" 1M > /dev/null
34
if [ "$use_backing" = "1" -a -z "$backing_file" ]; then
36
+ out=$($QEMU_IO -f raw -t none -c quit "$testfile" 2>&1)
35
backing_file=$param
37
+ rm -f "$testfile"
36
continue
38
37
+ elif $opts_param; then
39
[[ "$out" != *"O_DIRECT"* ]]
38
+ optstr=$(_optstr_add "$optstr" "$param")
40
}
39
+ opts_param=false
40
+ continue
41
fi
42
43
case "$param" in
44
@@ -XXX,XX +XXX,XX @@ _make_test_img()
45
use_backing=1
46
;;
47
48
+ -o)
49
+ opts_param=true
50
+ ;;
51
+
52
+ --no-opts)
53
+ optstr=""
54
+ ;;
55
+
56
*)
57
misc_params=("${misc_params[@]}" "$param")
58
;;
59
--
41
--
60
2.24.1
42
2.29.2
61
43
62
44
diff view generated by jsdifflib
New patch
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
2
3
Add support for the recently introduced functions
4
bdrv_co_preadv_part()
5
and
6
bdrv_co_pwritev_part()
7
to the COR-filter driver.
8
9
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20201216061703.70908-2-vsementsov@virtuozzo.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/copy-on-read.c | 28 ++++++++++++++++------------
15
1 file changed, 16 insertions(+), 12 deletions(-)
16
17
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/copy-on-read.c
20
+++ b/block/copy-on-read.c
21
@@ -XXX,XX +XXX,XX @@ static int64_t cor_getlength(BlockDriverState *bs)
22
}
23
24
25
-static int coroutine_fn cor_co_preadv(BlockDriverState *bs,
26
- uint64_t offset, uint64_t bytes,
27
- QEMUIOVector *qiov, int flags)
28
+static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
29
+ uint64_t offset, uint64_t bytes,
30
+ QEMUIOVector *qiov,
31
+ size_t qiov_offset,
32
+ int flags)
33
{
34
- return bdrv_co_preadv(bs->file, offset, bytes, qiov,
35
- flags | BDRV_REQ_COPY_ON_READ);
36
+ return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
37
+ flags | BDRV_REQ_COPY_ON_READ);
38
}
39
40
41
-static int coroutine_fn cor_co_pwritev(BlockDriverState *bs,
42
- uint64_t offset, uint64_t bytes,
43
- QEMUIOVector *qiov, int flags)
44
+static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
45
+ uint64_t offset,
46
+ uint64_t bytes,
47
+ QEMUIOVector *qiov,
48
+ size_t qiov_offset, int flags)
49
{
50
-
51
- return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
52
+ return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
53
+ flags);
54
}
55
56
57
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_copy_on_read = {
58
59
.bdrv_getlength = cor_getlength,
60
61
- .bdrv_co_preadv = cor_co_preadv,
62
- .bdrv_co_pwritev = cor_co_pwritev,
63
+ .bdrv_co_preadv_part = cor_co_preadv_part,
64
+ .bdrv_co_pwritev_part = cor_co_pwritev_part,
65
.bdrv_co_pwrite_zeroes = cor_co_pwrite_zeroes,
66
.bdrv_co_pdiscard = cor_co_pdiscard,
67
.bdrv_co_pwritev_compressed = cor_co_pwritev_compressed,
68
--
69
2.29.2
70
71
diff view generated by jsdifflib
1
We need some way to correlate QAPI BlockPermission values with
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
2
BLK_PERM_* flags. We could:
3
2
4
(1) have the same order in the QAPI definition as the the BLK_PERM_*
3
Provide API for insertion a node to backing chain.
5
flags are in LSb-first order. However, then there is no guarantee
6
that they actually match (e.g. when someone modifies the QAPI schema
7
without thinking of the BLK_PERM_* definitions).
8
We could add static assertions, but these would break what’s good
9
about this solution, namely its simplicity.
10
4
11
(2) define the BLK_PERM_* flags based on the BlockPermission values.
5
Suggested-by: Max Reitz <mreitz@redhat.com>
12
But this way whenever someone were to modify the QAPI order
6
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
13
(perfectly sensible in theory), the BLK_PERM_* values would change.
14
Because these values are used for file locking, this might break
15
file locking between different qemu versions.
16
17
Therefore, go the slightly more cumbersome way: Add a function to
18
translate from the QAPI constants to the BLK_PERM_* flags.
19
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Message-id: 20191108123455.39445-2-mreitz@redhat.com
22
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20201216061703.70908-3-vsementsov@virtuozzo.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
---
11
---
25
block.c | 18 ++++++++++++++++++
12
include/block/block.h | 2 ++
26
include/block/block.h | 1 +
13
block.c | 25 +++++++++++++++++++++++++
27
2 files changed, 19 insertions(+)
14
2 files changed, 27 insertions(+)
28
15
16
diff --git a/include/block/block.h b/include/block/block.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
19
+++ b/include/block/block.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
21
Error **errp);
22
void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
23
Error **errp);
24
+BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
25
+ int flags, Error **errp);
26
27
int bdrv_parse_aio(const char *mode, int *flags);
28
int bdrv_parse_cache_mode(const char *mode, int *flags, bool *writethrough);
29
diff --git a/block.c b/block.c
29
diff --git a/block.c b/block.c
30
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
31
--- a/block.c
32
+++ b/block.c
32
+++ b/block.c
33
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
33
@@ -XXX,XX +XXX,XX @@ static void bdrv_delete(BlockDriverState *bs)
34
*nshared = shared;
34
g_free(bs);
35
}
35
}
36
36
37
+uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
37
+BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
38
+ int flags, Error **errp)
38
+{
39
+{
39
+ static const uint64_t permissions[] = {
40
+ BlockDriverState *new_node_bs;
40
+ [BLOCK_PERMISSION_CONSISTENT_READ] = BLK_PERM_CONSISTENT_READ,
41
+ Error *local_err = NULL;
41
+ [BLOCK_PERMISSION_WRITE] = BLK_PERM_WRITE,
42
+ [BLOCK_PERMISSION_WRITE_UNCHANGED] = BLK_PERM_WRITE_UNCHANGED,
43
+ [BLOCK_PERMISSION_RESIZE] = BLK_PERM_RESIZE,
44
+ [BLOCK_PERMISSION_GRAPH_MOD] = BLK_PERM_GRAPH_MOD,
45
+ };
46
+
42
+
47
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(permissions) != BLOCK_PERMISSION__MAX);
43
+ new_node_bs = bdrv_open(NULL, NULL, node_options, flags, errp);
48
+ QEMU_BUILD_BUG_ON(1UL << ARRAY_SIZE(permissions) != BLK_PERM_ALL + 1);
44
+ if (new_node_bs == NULL) {
45
+ error_prepend(errp, "Could not create node: ");
46
+ return NULL;
47
+ }
49
+
48
+
50
+ assert(qapi_perm < BLOCK_PERMISSION__MAX);
49
+ bdrv_drained_begin(bs);
50
+ bdrv_replace_node(bs, new_node_bs, &local_err);
51
+ bdrv_drained_end(bs);
51
+
52
+
52
+ return permissions[qapi_perm];
53
+ if (local_err) {
54
+ bdrv_unref(new_node_bs);
55
+ error_propagate(errp, local_err);
56
+ return NULL;
57
+ }
58
+
59
+ return new_node_bs;
53
+}
60
+}
54
+
61
+
55
static void bdrv_replace_child_noperm(BdrvChild *child,
62
/*
56
BlockDriverState *new_bs)
63
* Run consistency checks on an image
57
{
64
*
58
diff --git a/include/block/block.h b/include/block/block.h
59
index XXXXXXX..XXXXXXX 100644
60
--- a/include/block/block.h
61
+++ b/include/block/block.h
62
@@ -XXX,XX +XXX,XX @@ enum {
63
};
64
65
char *bdrv_perm_names(uint64_t perm);
66
+uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm);
67
68
/* disk I/O throttling */
69
void bdrv_init(void);
70
--
65
--
71
2.24.1
66
2.29.2
72
67
73
68
diff view generated by jsdifflib
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
2
2
3
Allow writing all the data compressed through the filter driver.
3
Provide API for the COR-filter removal. Also, drop the filter child
4
The written data will be aligned by the cluster size.
4
permissions for an inactive state when the filter node is being
5
Based on the QEMU current implementation, that data can be written to
5
removed.
6
unallocated clusters only. May be used for a backup job.
6
To insert the filter, the block generic layer function
7
bdrv_insert_node() can be used.
8
The new function bdrv_cor_filter_drop() may be considered as an
9
intermediate solution before the QEMU permission update system has
10
overhauled. Then we are able to implement the API function
11
bdrv_remove_node() on the block generic layer.
7
12
8
Suggested-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
13
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-id: 1575288906-551879-2-git-send-email-andrey.shinkevich@virtuozzo.com
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
[mreitz: Replace NULL bdrv_get_format_name() by "(no format)"]
16
Message-Id: <20201216061703.70908-4-vsementsov@virtuozzo.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
18
---
15
block/Makefile.objs | 1 +
19
block/copy-on-read.h | 32 +++++++++++++++++++++++++
16
block/filter-compress.c | 168 ++++++++++++++++++++++++++++++++++++++++
20
block/copy-on-read.c | 56 ++++++++++++++++++++++++++++++++++++++++++++
17
qapi/block-core.json | 10 ++-
21
2 files changed, 88 insertions(+)
18
3 files changed, 175 insertions(+), 4 deletions(-)
22
create mode 100644 block/copy-on-read.h
19
create mode 100644 block/filter-compress.c
20
23
21
diff --git a/block/Makefile.objs b/block/Makefile.objs
24
diff --git a/block/copy-on-read.h b/block/copy-on-read.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/Makefile.objs
24
+++ b/block/Makefile.objs
25
@@ -XXX,XX +XXX,XX @@ block-obj-y += crypto.o
26
27
block-obj-y += aio_task.o
28
block-obj-y += backup-top.o
29
+block-obj-y += filter-compress.o
30
31
common-obj-y += stream.o
32
33
diff --git a/block/filter-compress.c b/block/filter-compress.c
34
new file mode 100644
25
new file mode 100644
35
index XXXXXXX..XXXXXXX
26
index XXXXXXX..XXXXXXX
36
--- /dev/null
27
--- /dev/null
37
+++ b/block/filter-compress.c
28
+++ b/block/copy-on-read.h
38
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@
39
+/*
30
+/*
40
+ * Compress filter block driver
31
+ * Copy-on-read filter block driver
41
+ *
32
+ *
42
+ * Copyright (c) 2019 Virtuozzo International GmbH
33
+ * The filter driver performs Copy-On-Read (COR) operations
34
+ *
35
+ * Copyright (c) 2018-2020 Virtuozzo International GmbH.
43
+ *
36
+ *
44
+ * Author:
37
+ * Author:
45
+ * Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
38
+ * Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
46
+ * (based on block/copy-on-read.c by Max Reitz)
47
+ *
39
+ *
48
+ * This program is free software; you can redistribute it and/or
40
+ * This program is free software; you can redistribute it and/or modify
49
+ * modify it under the terms of the GNU General Public License as
41
+ * it under the terms of the GNU General Public License as published by
50
+ * published by the Free Software Foundation; either version 2 or
42
+ * the Free Software Foundation; either version 2 of the License, or
51
+ * (at your option) any later version of the License.
43
+ * (at your option) any later version.
52
+ *
44
+ *
53
+ * This program is distributed in the hope that it will be useful,
45
+ * This program is distributed in the hope that it will be useful,
54
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
46
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
55
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56
+ * GNU General Public License for more details.
48
+ * GNU General Public License for more details.
57
+ *
49
+ *
58
+ * You should have received a copy of the GNU General Public License
50
+ * You should have received a copy of the GNU General Public License
59
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
51
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
60
+ */
52
+ */
61
+
53
+
62
+#include "qemu/osdep.h"
54
+#ifndef BLOCK_COPY_ON_READ
55
+#define BLOCK_COPY_ON_READ
56
+
63
+#include "block/block_int.h"
57
+#include "block/block_int.h"
64
+#include "qemu/module.h"
58
+
59
+void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs);
60
+
61
+#endif /* BLOCK_COPY_ON_READ */
62
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block/copy-on-read.c
65
+++ b/block/copy-on-read.c
66
@@ -XXX,XX +XXX,XX @@
67
#include "qemu/osdep.h"
68
#include "block/block_int.h"
69
#include "qemu/module.h"
65
+#include "qapi/error.h"
70
+#include "qapi/error.h"
71
+#include "block/copy-on-read.h"
66
+
72
+
67
+
73
+
68
+static int compress_open(BlockDriverState *bs, QDict *options, int flags,
74
+typedef struct BDRVStateCOR {
69
+ Error **errp)
75
+ bool active;
70
+{
76
+} BDRVStateCOR;
71
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
77
72
+ errp);
78
73
+ if (!bs->file) {
79
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
74
+ return -EINVAL;
80
Error **errp)
81
{
82
+ BDRVStateCOR *state = bs->opaque;
83
+
84
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
85
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
86
false, errp);
87
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
88
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
89
bs->file->bs->supported_zero_flags);
90
91
+ state->active = true;
92
+
93
+ /*
94
+ * We don't need to call bdrv_child_refresh_perms() now as the permissions
95
+ * will be updated later when the filter node gets its parent.
96
+ */
97
+
98
return 0;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
102
uint64_t perm, uint64_t shared,
103
uint64_t *nperm, uint64_t *nshared)
104
{
105
+ BDRVStateCOR *s = bs->opaque;
106
+
107
+ if (!s->active) {
108
+ /*
109
+ * While the filter is being removed
110
+ */
111
+ *nperm = 0;
112
+ *nshared = BLK_PERM_ALL;
113
+ return;
75
+ }
114
+ }
76
+
115
+
77
+ if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) {
116
*nperm = perm & PERM_PASSTHROUGH;
78
+ error_setg(errp,
117
*nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
79
+ "Compression is not supported for underlying format: %s",
118
80
+ bdrv_get_format_name(bs->file->bs) ?: "(no format)");
119
@@ -XXX,XX +XXX,XX @@ static void cor_lock_medium(BlockDriverState *bs, bool locked)
120
121
static BlockDriver bdrv_copy_on_read = {
122
.format_name = "copy-on-read",
123
+ .instance_size = sizeof(BDRVStateCOR),
124
125
.bdrv_open = cor_open,
126
.bdrv_child_perm = cor_child_perm,
127
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_copy_on_read = {
128
.is_filter = true,
129
};
130
81
+
131
+
82
+ return -ENOTSUP;
132
+void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs)
133
+{
134
+ BdrvChild *child;
135
+ BlockDriverState *bs;
136
+ BDRVStateCOR *s = cor_filter_bs->opaque;
137
+
138
+ child = bdrv_filter_child(cor_filter_bs);
139
+ if (!child) {
140
+ return;
83
+ }
141
+ }
142
+ bs = child->bs;
84
+
143
+
85
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
144
+ /* Retain the BDS until we complete the graph change. */
86
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
145
+ bdrv_ref(bs);
146
+ /* Hold a guest back from writing while permissions are being reset. */
147
+ bdrv_drained_begin(bs);
148
+ /* Drop permissions before the graph change. */
149
+ s->active = false;
150
+ bdrv_child_refresh_perms(cor_filter_bs, child, &error_abort);
151
+ bdrv_replace_node(cor_filter_bs, bs, &error_abort);
87
+
152
+
88
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
153
+ bdrv_drained_end(bs);
89
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
154
+ bdrv_unref(bs);
90
+ bs->file->bs->supported_zero_flags);
155
+ bdrv_unref(cor_filter_bs);
91
+
92
+ return 0;
93
+}
156
+}
94
+
157
+
95
+
158
+
96
+static int64_t compress_getlength(BlockDriverState *bs)
159
static void bdrv_copy_on_read_init(void)
97
+{
160
{
98
+ return bdrv_getlength(bs->file->bs);
161
bdrv_register(&bdrv_copy_on_read);
99
+}
100
+
101
+
102
+static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs,
103
+ uint64_t offset, uint64_t bytes,
104
+ QEMUIOVector *qiov,
105
+ size_t qiov_offset,
106
+ int flags)
107
+{
108
+ return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
109
+ flags);
110
+}
111
+
112
+
113
+static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
114
+ uint64_t offset,
115
+ uint64_t bytes,
116
+ QEMUIOVector *qiov,
117
+ size_t qiov_offset, int flags)
118
+{
119
+ return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
120
+ flags | BDRV_REQ_WRITE_COMPRESSED);
121
+}
122
+
123
+
124
+static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
125
+ int64_t offset, int bytes,
126
+ BdrvRequestFlags flags)
127
+{
128
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
129
+}
130
+
131
+
132
+static int coroutine_fn compress_co_pdiscard(BlockDriverState *bs,
133
+ int64_t offset, int bytes)
134
+{
135
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
136
+}
137
+
138
+
139
+static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
140
+{
141
+ BlockDriverInfo bdi;
142
+ int ret;
143
+
144
+ if (!bs->file) {
145
+ return;
146
+ }
147
+
148
+ ret = bdrv_get_info(bs->file->bs, &bdi);
149
+ if (ret < 0 || bdi.cluster_size == 0) {
150
+ return;
151
+ }
152
+
153
+ bs->bl.request_alignment = bdi.cluster_size;
154
+}
155
+
156
+
157
+static void compress_eject(BlockDriverState *bs, bool eject_flag)
158
+{
159
+ bdrv_eject(bs->file->bs, eject_flag);
160
+}
161
+
162
+
163
+static void compress_lock_medium(BlockDriverState *bs, bool locked)
164
+{
165
+ bdrv_lock_medium(bs->file->bs, locked);
166
+}
167
+
168
+
169
+static bool compress_recurse_is_first_non_filter(BlockDriverState *bs,
170
+ BlockDriverState *candidate)
171
+{
172
+ return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
173
+}
174
+
175
+
176
+static BlockDriver bdrv_compress = {
177
+ .format_name = "compress",
178
+
179
+ .bdrv_open = compress_open,
180
+ .bdrv_child_perm = bdrv_filter_default_perms,
181
+
182
+ .bdrv_getlength = compress_getlength,
183
+
184
+ .bdrv_co_preadv_part = compress_co_preadv_part,
185
+ .bdrv_co_pwritev_part = compress_co_pwritev_part,
186
+ .bdrv_co_pwrite_zeroes = compress_co_pwrite_zeroes,
187
+ .bdrv_co_pdiscard = compress_co_pdiscard,
188
+ .bdrv_refresh_limits = compress_refresh_limits,
189
+
190
+ .bdrv_eject = compress_eject,
191
+ .bdrv_lock_medium = compress_lock_medium,
192
+
193
+ .bdrv_co_block_status = bdrv_co_block_status_from_file,
194
+
195
+ .bdrv_recurse_is_first_non_filter = compress_recurse_is_first_non_filter,
196
+
197
+ .has_variable_length = true,
198
+ .is_filter = true,
199
+};
200
+
201
+static void bdrv_compress_init(void)
202
+{
203
+ bdrv_register(&bdrv_compress);
204
+}
205
+
206
+block_init(bdrv_compress_init);
207
diff --git a/qapi/block-core.json b/qapi/block-core.json
208
index XXXXXXX..XXXXXXX 100644
209
--- a/qapi/block-core.json
210
+++ b/qapi/block-core.json
211
@@ -XXX,XX +XXX,XX @@
212
# @copy-on-read: Since 3.0
213
# @blklogwrites: Since 3.0
214
# @blkreplay: Since 4.2
215
+# @compress: Since 5.0
216
#
217
# Since: 2.9
218
##
219
{ 'enum': 'BlockdevDriver',
220
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
221
- 'cloop', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
222
- 'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
223
- 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
224
- 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
225
+ 'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
226
+ 'gluster', 'host_cdrom', 'host_device', 'http', 'https', 'iscsi',
227
+ 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
228
+ 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
229
{ 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
230
'sheepdog',
231
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
232
@@ -XXX,XX +XXX,XX @@
233
'blkreplay': 'BlockdevOptionsBlkreplay',
234
'bochs': 'BlockdevOptionsGenericFormat',
235
'cloop': 'BlockdevOptionsGenericFormat',
236
+ 'compress': 'BlockdevOptionsGenericFormat',
237
'copy-on-read':'BlockdevOptionsGenericFormat',
238
'dmg': 'BlockdevOptionsGenericFormat',
239
'file': 'BlockdevOptionsFile',
240
--
162
--
241
2.24.1
163
2.29.2
242
164
243
165
diff view generated by jsdifflib
New patch
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
2
3
Provide the possibility to pass the 'filter-node-name' parameter to the
4
block-stream job as it is done for the commit block job.
5
6
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
[vsementsov: comment indentation, s/Since: 5.2/Since: 6.0/]
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20201216061703.70908-5-vsementsov@virtuozzo.com>
11
[mreitz: s/commit/stream/]
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
qapi/block-core.json | 6 ++++++
15
include/block/block_int.h | 7 ++++++-
16
block/monitor/block-hmp-cmds.c | 4 ++--
17
block/stream.c | 4 +++-
18
blockdev.c | 4 +++-
19
5 files changed, 20 insertions(+), 5 deletions(-)
20
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
22
index XXXXXXX..XXXXXXX 100644
23
--- a/qapi/block-core.json
24
+++ b/qapi/block-core.json
25
@@ -XXX,XX +XXX,XX @@
26
# 'stop' and 'enospc' can only be used if the block device
27
# supports io-status (see BlockInfo). Since 1.3.
28
#
29
+# @filter-node-name: the node name that should be assigned to the
30
+# filter driver that the stream job inserts into the graph
31
+# above @device. If this option is not given, a node name is
32
+# autogenerated. (Since: 6.0)
33
+#
34
# @auto-finalize: When false, this job will wait in a PENDING state after it has
35
# finished its work, waiting for @block-job-finalize before
36
# making any block graph changes.
37
@@ -XXX,XX +XXX,XX @@
38
'data': { '*job-id': 'str', 'device': 'str', '*base': 'str',
39
'*base-node': 'str', '*backing-file': 'str', '*speed': 'int',
40
'*on-error': 'BlockdevOnError',
41
+ '*filter-node-name': 'str',
42
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
43
44
##
45
diff --git a/include/block/block_int.h b/include/block/block_int.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/block/block_int.h
48
+++ b/include/block/block_int.h
49
@@ -XXX,XX +XXX,XX @@ int is_windows_drive(const char *filename);
50
* See @BlockJobCreateFlags
51
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
52
* @on_error: The action to take upon error.
53
+ * @filter_node_name: The node name that should be assigned to the filter
54
+ * driver that the stream job inserts into the graph above
55
+ * @bs. NULL means that a node name should be autogenerated.
56
* @errp: Error object.
57
*
58
* Start a streaming operation on @bs. Clusters that are unallocated
59
@@ -XXX,XX +XXX,XX @@ int is_windows_drive(const char *filename);
60
void stream_start(const char *job_id, BlockDriverState *bs,
61
BlockDriverState *base, const char *backing_file_str,
62
int creation_flags, int64_t speed,
63
- BlockdevOnError on_error, Error **errp);
64
+ BlockdevOnError on_error,
65
+ const char *filter_node_name,
66
+ Error **errp);
67
68
/**
69
* commit_start:
70
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/monitor/block-hmp-cmds.c
73
+++ b/block/monitor/block-hmp-cmds.c
74
@@ -XXX,XX +XXX,XX @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
75
76
qmp_block_stream(true, device, device, base != NULL, base, false, NULL,
77
false, NULL, qdict_haskey(qdict, "speed"), speed, true,
78
- BLOCKDEV_ON_ERROR_REPORT, false, false, false, false,
79
- &error);
80
+ BLOCKDEV_ON_ERROR_REPORT, false, NULL, false, false, false,
81
+ false, &error);
82
83
hmp_handle_error(mon, error);
84
}
85
diff --git a/block/stream.c b/block/stream.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/block/stream.c
88
+++ b/block/stream.c
89
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver stream_job_driver = {
90
void stream_start(const char *job_id, BlockDriverState *bs,
91
BlockDriverState *base, const char *backing_file_str,
92
int creation_flags, int64_t speed,
93
- BlockdevOnError on_error, Error **errp)
94
+ BlockdevOnError on_error,
95
+ const char *filter_node_name,
96
+ Error **errp)
97
{
98
StreamBlockJob *s;
99
BlockDriverState *iter;
100
diff --git a/blockdev.c b/blockdev.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/blockdev.c
103
+++ b/blockdev.c
104
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
105
bool has_backing_file, const char *backing_file,
106
bool has_speed, int64_t speed,
107
bool has_on_error, BlockdevOnError on_error,
108
+ bool has_filter_node_name, const char *filter_node_name,
109
bool has_auto_finalize, bool auto_finalize,
110
bool has_auto_dismiss, bool auto_dismiss,
111
Error **errp)
112
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
113
}
114
115
stream_start(has_job_id ? job_id : NULL, bs, base_bs, base_name,
116
- job_flags, has_speed ? speed : 0, on_error, &local_err);
117
+ job_flags, has_speed ? speed : 0, on_error,
118
+ filter_node_name, &local_err);
119
if (local_err) {
120
error_propagate(errp, local_err);
121
goto out;
122
--
123
2.29.2
124
125
diff view generated by jsdifflib
New patch
1
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
2
3
Add an option to limit copy-on-read operations to specified sub-chain
4
of backing-chain, to make copy-on-read filter useful for block-stream
5
job.
6
7
Suggested-by: Max Reitz <mreitz@redhat.com>
8
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
[vsementsov: change subject, modified to freeze the chain,
12
do some fixes]
13
Message-Id: <20201216061703.70908-6-vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
qapi/block-core.json | 20 ++++++++-
17
block/copy-on-read.c | 98 +++++++++++++++++++++++++++++++++++++++++++-
18
2 files changed, 115 insertions(+), 3 deletions(-)
19
20
diff --git a/qapi/block-core.json b/qapi/block-core.json
21
index XXXXXXX..XXXXXXX 100644
22
--- a/qapi/block-core.json
23
+++ b/qapi/block-core.json
24
@@ -XXX,XX +XXX,XX @@
25
'data': { 'throttle-group': 'str',
26
'file' : 'BlockdevRef'
27
} }
28
+
29
+##
30
+# @BlockdevOptionsCor:
31
+#
32
+# Driver specific block device options for the copy-on-read driver.
33
+#
34
+# @bottom: The name of a non-filter node (allocation-bearing layer) that
35
+# limits the COR operations in the backing chain (inclusive), so
36
+# that no data below this node will be copied by this filter.
37
+# If option is absent, the limit is not applied, so that data
38
+# from all backing layers may be copied.
39
+#
40
+# Since: 6.0
41
+##
42
+{ 'struct': 'BlockdevOptionsCor',
43
+ 'base': 'BlockdevOptionsGenericFormat',
44
+ 'data': { '*bottom': 'str' } }
45
+
46
##
47
# @BlockdevOptions:
48
#
49
@@ -XXX,XX +XXX,XX @@
50
'bochs': 'BlockdevOptionsGenericFormat',
51
'cloop': 'BlockdevOptionsGenericFormat',
52
'compress': 'BlockdevOptionsGenericFormat',
53
- 'copy-on-read':'BlockdevOptionsGenericFormat',
54
+ 'copy-on-read':'BlockdevOptionsCor',
55
'dmg': 'BlockdevOptionsGenericFormat',
56
'file': 'BlockdevOptionsFile',
57
'ftp': 'BlockdevOptionsCurlFtp',
58
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/block/copy-on-read.c
61
+++ b/block/copy-on-read.c
62
@@ -XXX,XX +XXX,XX @@
63
#include "block/block_int.h"
64
#include "qemu/module.h"
65
#include "qapi/error.h"
66
+#include "qapi/qmp/qdict.h"
67
#include "block/copy-on-read.h"
68
69
70
typedef struct BDRVStateCOR {
71
bool active;
72
+ BlockDriverState *bottom_bs;
73
+ bool chain_frozen;
74
} BDRVStateCOR;
75
76
77
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
78
Error **errp)
79
{
80
+ BlockDriverState *bottom_bs = NULL;
81
BDRVStateCOR *state = bs->opaque;
82
+ /* Find a bottom node name, if any */
83
+ const char *bottom_node = qdict_get_try_str(options, "bottom");
84
85
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
86
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
87
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
88
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
89
bs->file->bs->supported_zero_flags);
90
91
+ if (bottom_node) {
92
+ bottom_bs = bdrv_find_node(bottom_node);
93
+ if (!bottom_bs) {
94
+ error_setg(errp, "Bottom node '%s' not found", bottom_node);
95
+ qdict_del(options, "bottom");
96
+ return -EINVAL;
97
+ }
98
+ qdict_del(options, "bottom");
99
+
100
+ if (!bottom_bs->drv) {
101
+ error_setg(errp, "Bottom node '%s' not opened", bottom_node);
102
+ return -EINVAL;
103
+ }
104
+
105
+ if (bottom_bs->drv->is_filter) {
106
+ error_setg(errp, "Bottom node '%s' is a filter", bottom_node);
107
+ return -EINVAL;
108
+ }
109
+
110
+ if (bdrv_freeze_backing_chain(bs, bottom_bs, errp) < 0) {
111
+ return -EINVAL;
112
+ }
113
+ state->chain_frozen = true;
114
+
115
+ /*
116
+ * We do freeze the chain, so it shouldn't be removed. Still, storing a
117
+ * pointer worth bdrv_ref().
118
+ */
119
+ bdrv_ref(bottom_bs);
120
+ }
121
state->active = true;
122
+ state->bottom_bs = bottom_bs;
123
124
/*
125
* We don't need to call bdrv_child_refresh_perms() now as the permissions
126
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
127
size_t qiov_offset,
128
int flags)
129
{
130
- return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
131
- flags | BDRV_REQ_COPY_ON_READ);
132
+ int64_t n;
133
+ int local_flags;
134
+ int ret;
135
+ BDRVStateCOR *state = bs->opaque;
136
+
137
+ if (!state->bottom_bs) {
138
+ return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
139
+ flags | BDRV_REQ_COPY_ON_READ);
140
+ }
141
+
142
+ while (bytes) {
143
+ local_flags = flags;
144
+
145
+ /* In case of failure, try to copy-on-read anyway */
146
+ ret = bdrv_is_allocated(bs->file->bs, offset, bytes, &n);
147
+ if (ret <= 0) {
148
+ ret = bdrv_is_allocated_above(bdrv_backing_chain_next(bs->file->bs),
149
+ state->bottom_bs, true, offset,
150
+ n, &n);
151
+ if (ret > 0 || ret < 0) {
152
+ local_flags |= BDRV_REQ_COPY_ON_READ;
153
+ }
154
+ /* Finish earlier if the end of a backing file has been reached */
155
+ if (n == 0) {
156
+ break;
157
+ }
158
+ }
159
+
160
+ ret = bdrv_co_preadv_part(bs->file, offset, n, qiov, qiov_offset,
161
+ local_flags);
162
+ if (ret < 0) {
163
+ return ret;
164
+ }
165
+
166
+ offset += n;
167
+ qiov_offset += n;
168
+ bytes -= n;
169
+ }
170
+
171
+ return 0;
172
}
173
174
175
@@ -XXX,XX +XXX,XX @@ static void cor_lock_medium(BlockDriverState *bs, bool locked)
176
}
177
178
179
+static void cor_close(BlockDriverState *bs)
180
+{
181
+ BDRVStateCOR *s = bs->opaque;
182
+
183
+ if (s->chain_frozen) {
184
+ s->chain_frozen = false;
185
+ bdrv_unfreeze_backing_chain(bs, s->bottom_bs);
186
+ }
187
+
188
+ bdrv_unref(s->bottom_bs);
189
+}
190
+
191
+
192
static BlockDriver bdrv_copy_on_read = {
193
.format_name = "copy-on-read",
194
.instance_size = sizeof(BDRVStateCOR),
195
196
.bdrv_open = cor_open,
197
+ .bdrv_close = cor_close,
198
.bdrv_child_perm = cor_child_perm,
199
200
.bdrv_getlength = cor_getlength,
201
@@ -XXX,XX +XXX,XX @@ void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs)
202
bdrv_drained_begin(bs);
203
/* Drop permissions before the graph change. */
204
s->active = false;
205
+ /* unfreeze, as otherwise bdrv_replace_node() will fail */
206
+ if (s->chain_frozen) {
207
+ s->chain_frozen = false;
208
+ bdrv_unfreeze_backing_chain(cor_filter_bs, s->bottom_bs);
209
+ }
210
bdrv_child_refresh_perms(cor_filter_bs, child, &error_abort);
211
bdrv_replace_node(cor_filter_bs, bs, &error_abort);
212
213
--
214
2.29.2
215
216
diff view generated by jsdifflib
New patch
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
2
3
The test case #310 is similar to #216 by Max Reitz. The difference is
4
that the test #310 involves a bottom node to the COR filter driver.
5
6
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
[vsementsov: detach backing to test reads from top, limit to qcow2]
9
Message-Id: <20201216061703.70908-7-vsementsov@virtuozzo.com>
10
[mreitz: Add "# group:" line]
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/310 | 117 +++++++++++++++++++++++++++++++++++++
14
tests/qemu-iotests/310.out | 15 +++++
15
tests/qemu-iotests/group | 1 +
16
3 files changed, 133 insertions(+)
17
create mode 100755 tests/qemu-iotests/310
18
create mode 100644 tests/qemu-iotests/310.out
19
20
diff --git a/tests/qemu-iotests/310 b/tests/qemu-iotests/310
21
new file mode 100755
22
index XXXXXXX..XXXXXXX
23
--- /dev/null
24
+++ b/tests/qemu-iotests/310
25
@@ -XXX,XX +XXX,XX @@
26
+#!/usr/bin/env python3
27
+# group: rw quick
28
+#
29
+# Copy-on-read tests using a COR filter with a bottom node
30
+#
31
+# Copyright (C) 2018 Red Hat, Inc.
32
+# Copyright (c) 2020 Virtuozzo International GmbH
33
+#
34
+# This program is free software; you can redistribute it and/or modify
35
+# it under the terms of the GNU General Public License as published by
36
+# the Free Software Foundation; either version 2 of the License, or
37
+# (at your option) any later version.
38
+#
39
+# This program is distributed in the hope that it will be useful,
40
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
41
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42
+# GNU General Public License for more details.
43
+#
44
+# You should have received a copy of the GNU General Public License
45
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
46
+#
47
+
48
+import iotests
49
+from iotests import log, qemu_img, qemu_io_silent
50
+
51
+# Need backing file support
52
+iotests.script_initialize(supported_fmts=['qcow2'],
53
+ supported_platforms=['linux'])
54
+
55
+log('')
56
+log('=== Copy-on-read across nodes ===')
57
+log('')
58
+
59
+# This test is similar to the 216 one by Max Reitz <mreitz@redhat.com>
60
+# The difference is that this test case involves a bottom node to the
61
+# COR filter driver.
62
+
63
+with iotests.FilePath('base.img') as base_img_path, \
64
+ iotests.FilePath('mid.img') as mid_img_path, \
65
+ iotests.FilePath('top.img') as top_img_path, \
66
+ iotests.VM() as vm:
67
+
68
+ log('--- Setting up images ---')
69
+ log('')
70
+
71
+ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
72
+ assert qemu_io_silent(base_img_path, '-c', 'write -P 1 0M 1M') == 0
73
+ assert qemu_io_silent(base_img_path, '-c', 'write -P 1 3M 1M') == 0
74
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
75
+ '-F', iotests.imgfmt, mid_img_path) == 0
76
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 3 2M 1M') == 0
77
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 3 4M 1M') == 0
78
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
79
+ '-F', iotests.imgfmt, top_img_path) == 0
80
+ assert qemu_io_silent(top_img_path, '-c', 'write -P 2 1M 1M') == 0
81
+
82
+# 0 1 2 3 4
83
+# top 2
84
+# mid 3 3
85
+# base 1 1
86
+
87
+ log('Done')
88
+
89
+ log('')
90
+ log('--- Doing COR ---')
91
+ log('')
92
+
93
+ vm.launch()
94
+
95
+ log(vm.qmp('blockdev-add',
96
+ node_name='node0',
97
+ driver='copy-on-read',
98
+ bottom='node2',
99
+ file={
100
+ 'driver': iotests.imgfmt,
101
+ 'file': {
102
+ 'driver': 'file',
103
+ 'filename': top_img_path
104
+ },
105
+ 'backing': {
106
+ 'node-name': 'node2',
107
+ 'driver': iotests.imgfmt,
108
+ 'file': {
109
+ 'driver': 'file',
110
+ 'filename': mid_img_path
111
+ },
112
+ 'backing': {
113
+ 'driver': iotests.imgfmt,
114
+ 'file': {
115
+ 'driver': 'file',
116
+ 'filename': base_img_path
117
+ }
118
+ },
119
+ }
120
+ }))
121
+
122
+ # Trigger COR
123
+ log(vm.qmp('human-monitor-command',
124
+ command_line='qemu-io node0 "read 0 5M"'))
125
+
126
+ vm.shutdown()
127
+
128
+ log('')
129
+ log('--- Checking COR result ---')
130
+ log('')
131
+
132
+ # Detach backing to check that we can read the data from the top level now
133
+ assert qemu_img('rebase', '-u', '-b', '', '-f', iotests.imgfmt,
134
+ top_img_path) == 0
135
+
136
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 0 0 1M') == 0
137
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 2 1M 1M') == 0
138
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 3 2M 1M') == 0
139
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 0 3M 1M') == 0
140
+ assert qemu_io_silent(top_img_path, '-c', 'read -P 3 4M 1M') == 0
141
+
142
+ log('Done')
143
diff --git a/tests/qemu-iotests/310.out b/tests/qemu-iotests/310.out
144
new file mode 100644
145
index XXXXXXX..XXXXXXX
146
--- /dev/null
147
+++ b/tests/qemu-iotests/310.out
148
@@ -XXX,XX +XXX,XX @@
149
+
150
+=== Copy-on-read across nodes ===
151
+
152
+--- Setting up images ---
153
+
154
+Done
155
+
156
+--- Doing COR ---
157
+
158
+{"return": {}}
159
+{"return": ""}
160
+
161
+--- Checking COR result ---
162
+
163
+Done
164
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
165
index XXXXXXX..XXXXXXX 100644
166
--- a/tests/qemu-iotests/group
167
+++ b/tests/qemu-iotests/group
168
@@ -XXX,XX +XXX,XX @@
169
307 rw quick export
170
308 rw
171
309 rw auto quick
172
+310 rw quick
173
312 rw quick
174
--
175
2.29.2
176
177
diff view generated by jsdifflib
New patch
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
2
3
Add the new member supported_read_flags to the BlockDriverState
4
structure. It will control the flags set for copy-on-read operations.
5
Make the block generic layer evaluate supported read flags before they
6
go to a block driver.
7
8
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
[vsementsov: use assert instead of abort]
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20201216061703.70908-8-vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
include/block/block_int.h | 4 ++++
17
block/io.c | 10 ++++++++--
18
2 files changed, 12 insertions(+), 2 deletions(-)
19
20
diff --git a/include/block/block_int.h b/include/block/block_int.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/block/block_int.h
23
+++ b/include/block/block_int.h
24
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
25
/* I/O Limits */
26
BlockLimits bl;
27
28
+ /*
29
+ * Flags honored during pread
30
+ */
31
+ unsigned int supported_read_flags;
32
/* Flags honored during pwrite (so far: BDRV_REQ_FUA,
33
* BDRV_REQ_WRITE_UNCHANGED).
34
* If a driver does not support BDRV_REQ_WRITE_UNCHANGED, those
35
diff --git a/block/io.c b/block/io.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/block/io.c
38
+++ b/block/io.c
39
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
40
if (flags & BDRV_REQ_COPY_ON_READ) {
41
int64_t pnum;
42
43
+ /* The flag BDRV_REQ_COPY_ON_READ has reached its addressee */
44
+ flags &= ~BDRV_REQ_COPY_ON_READ;
45
+
46
ret = bdrv_is_allocated(bs, offset, bytes, &pnum);
47
if (ret < 0) {
48
goto out;
49
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
50
goto out;
51
}
52
53
+ assert(!(flags & ~bs->supported_read_flags));
54
+
55
max_bytes = ROUND_UP(MAX(0, total_bytes - offset), align);
56
if (bytes <= max_bytes && bytes <= max_transfer) {
57
- ret = bdrv_driver_preadv(bs, offset, bytes, qiov, qiov_offset, 0);
58
+ ret = bdrv_driver_preadv(bs, offset, bytes, qiov, qiov_offset, flags);
59
goto out;
60
}
61
62
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
63
64
ret = bdrv_driver_preadv(bs, offset + bytes - bytes_remaining,
65
num, qiov,
66
- qiov_offset + bytes - bytes_remaining, 0);
67
+ qiov_offset + bytes - bytes_remaining,
68
+ flags);
69
max_bytes -= num;
70
} else {
71
num = bytes_remaining;
72
--
73
2.29.2
74
75
diff view generated by jsdifflib
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
2
2
3
Add the case to the iotest #214 that checks possibility of writing
3
If the flag BDRV_REQ_PREFETCH was set, skip idling read/write
4
compressed data of more than one cluster size. The test case involves
4
operations in COR-driver. It can be taken into account for the
5
the compress filter driver showing a sample usage of that.
5
COR-algorithms optimization. That check is being made during the
6
block stream job by the moment.
7
8
Add the BDRV_REQ_PREFETCH flag to the supported_read_flags of the
9
COR-filter.
10
11
block: Modify the comment for the flag BDRV_REQ_PREFETCH as we are
12
going to use it alone and pass it to the COR-filter driver for further
13
processing.
6
14
7
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
15
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 1575288906-551879-4-git-send-email-andrey.shinkevich@virtuozzo.com
18
Message-Id: <20201216061703.70908-9-vsementsov@virtuozzo.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
20
---
13
tests/qemu-iotests/214 | 43 ++++++++++++++++++++++++++++++++++++++
21
include/block/block.h | 8 +++++---
14
tests/qemu-iotests/214.out | 14 +++++++++++++
22
block/copy-on-read.c | 14 ++++++++++----
15
2 files changed, 57 insertions(+)
23
2 files changed, 15 insertions(+), 7 deletions(-)
16
24
17
diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214
25
diff --git a/include/block/block.h b/include/block/block.h
18
index XXXXXXX..XXXXXXX 100755
26
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/214
27
--- a/include/block/block.h
20
+++ b/tests/qemu-iotests/214
28
+++ b/include/block/block.h
21
@@ -XXX,XX +XXX,XX @@ _check_test_img -r all
29
@@ -XXX,XX +XXX,XX @@ typedef enum {
22
$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
30
BDRV_REQ_NO_FALLBACK = 0x100,
23
$QEMU_IO -c "read -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
31
24
32
/*
25
+echo
33
- * BDRV_REQ_PREFETCH may be used only together with BDRV_REQ_COPY_ON_READ
26
+echo "=== Write compressed data of multiple clusters ==="
34
- * on read request and means that caller doesn't really need data to be
27
+echo
35
- * written to qiov parameter which may be NULL.
28
+cluster_size=0x10000
36
+ * BDRV_REQ_PREFETCH makes sense only in the context of copy-on-read
29
+_make_test_img 2M -o cluster_size=$cluster_size
37
+ * (i.e., together with the BDRV_REQ_COPY_ON_READ flag or when a COR
38
+ * filter is involved), in which case it signals that the COR operation
39
+ * need not read the data into memory (qiov) but only ensure they are
40
+ * copied to the top layer (i.e., that COR operation is done).
41
*/
42
BDRV_REQ_PREFETCH = 0x200,
43
44
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/copy-on-read.c
47
+++ b/block/copy-on-read.c
48
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
49
return -EINVAL;
50
}
51
52
+ bs->supported_read_flags = BDRV_REQ_PREFETCH;
30
+
53
+
31
+echo "Write uncompressed data:"
54
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
32
+let data_size="8 * $cluster_size"
55
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
33
+$QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \
56
34
+ 2>&1 | _filter_qemu_io | _filter_testdir
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
35
+sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" |
58
}
36
+ sed -n '/"actual-size":/ s/[^0-9]//gp')
59
}
37
+
60
38
+_make_test_img 2M -o cluster_size=$cluster_size
61
- ret = bdrv_co_preadv_part(bs->file, offset, n, qiov, qiov_offset,
39
+echo "Write compressed data:"
62
- local_flags);
40
+let data_size="3 * $cluster_size + $cluster_size / 2"
63
- if (ret < 0) {
41
+# Set compress on. That will align the written data
64
- return ret;
42
+# by the cluster size and will write them compressed.
65
+ /* Skip if neither read nor write are needed */
43
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
66
+ if ((local_flags & (BDRV_REQ_PREFETCH | BDRV_REQ_COPY_ON_READ)) !=
44
+$QEMU_IO -c "write -P 0xbb 0 $data_size" --image-opts \
67
+ BDRV_REQ_PREFETCH) {
45
+ "driver=compress,file.driver=$IMGFMT,file.file.driver=file,file.file.filename=$TEST_IMG" \
68
+ ret = bdrv_co_preadv_part(bs->file, offset, n, qiov, qiov_offset,
46
+ 2>&1 | _filter_qemu_io | _filter_testdir
69
+ local_flags);
47
+
70
+ if (ret < 0) {
48
+let offset="4 * $cluster_size + $cluster_size / 4"
71
+ return ret;
49
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
72
+ }
50
+$QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\
73
}
51
+ 'driver': 'compress',
74
52
+ 'file': {'driver': '$IMGFMT',
75
offset += n;
53
+ 'file': {'driver': 'file',
54
+ 'filename': '$TEST_IMG'}}}" | \
55
+ _filter_qemu_io | _filter_testdir
56
+
57
+sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
58
+ sed -n '/"actual-size":/ s/[^0-9]//gp')
59
+
60
+if [ $sizeA -le $sizeB ]
61
+then
62
+ echo "Compression ERROR"
63
+fi
64
+
65
+$QEMU_IMG check --output=json "$TEST_IMG" |
66
+ sed -n 's/,$//; /"compressed-clusters":/ s/^ *//p'
67
+
68
# success, all done
69
echo '*** done'
70
rm -f $seq.full
71
diff --git a/tests/qemu-iotests/214.out b/tests/qemu-iotests/214.out
72
index XXXXXXX..XXXXXXX 100644
73
--- a/tests/qemu-iotests/214.out
74
+++ b/tests/qemu-iotests/214.out
75
@@ -XXX,XX +XXX,XX @@ read 4194304/4194304 bytes at offset 0
76
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
77
read 4194304/4194304 bytes at offset 4194304
78
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
79
+
80
+=== Write compressed data of multiple clusters ===
81
+
82
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
83
+Write uncompressed data:
84
+wrote 524288/524288 bytes at offset 0
85
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
86
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
87
+Write compressed data:
88
+wrote 229376/229376 bytes at offset 0
89
+224 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
90
+wrote 229376/229376 bytes at offset 278528
91
+224 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
92
+"compressed-clusters": 8
93
*** done
94
--
76
--
95
2.24.1
77
2.29.2
96
78
97
79
diff view generated by jsdifflib
New patch
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
2
3
Stream in stream_prepare calls bdrv_change_backing_file() to change
4
backing-file in the metadata of bs.
5
6
It may use either backing-file parameter given by user or just take
7
filename of base on job start.
8
9
Backing file format is determined by base on job finish.
10
11
There are some problems with this design, we solve only two by this
12
patch:
13
14
1. Consider scenario with backing-file unset. Current concept of stream
15
supports changing of the base during the job (we don't freeze link to
16
the base). So, we should not save base filename at job start,
17
18
- let's determine name of the base on job finish.
19
20
2. Using direct base to determine filename and format is not very good:
21
base node may be a filter, so its filename may be JSON, and format_name
22
is not good for storing into qcow2 metadata as backing file format.
23
24
- let's use unfiltered_base
25
26
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
27
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
28
[vsementsov: change commit subject, change logic in stream_prepare]
29
Message-Id: <20201216061703.70908-10-vsementsov@virtuozzo.com>
30
Reviewed-by: Max Reitz <mreitz@redhat.com>
31
Signed-off-by: Max Reitz <mreitz@redhat.com>
32
---
33
block/stream.c | 9 +++++----
34
blockdev.c | 8 +-------
35
2 files changed, 6 insertions(+), 11 deletions(-)
36
37
diff --git a/block/stream.c b/block/stream.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/block/stream.c
40
+++ b/block/stream.c
41
@@ -XXX,XX +XXX,XX @@ static int stream_prepare(Job *job)
42
BlockDriverState *bs = blk_bs(bjob->blk);
43
BlockDriverState *unfiltered_bs = bdrv_skip_filters(bs);
44
BlockDriverState *base = bdrv_filter_or_cow_bs(s->above_base);
45
+ BlockDriverState *unfiltered_base = bdrv_skip_filters(base);
46
Error *local_err = NULL;
47
int ret = 0;
48
49
@@ -XXX,XX +XXX,XX @@ static int stream_prepare(Job *job)
50
51
if (bdrv_cow_child(unfiltered_bs)) {
52
const char *base_id = NULL, *base_fmt = NULL;
53
- if (base) {
54
- base_id = s->backing_file_str;
55
- if (base->drv) {
56
- base_fmt = base->drv->format_name;
57
+ if (unfiltered_base) {
58
+ base_id = s->backing_file_str ?: unfiltered_base->filename;
59
+ if (unfiltered_base->drv) {
60
+ base_fmt = unfiltered_base->drv->format_name;
61
}
62
}
63
bdrv_set_backing_hd(unfiltered_bs, base, &local_err);
64
diff --git a/blockdev.c b/blockdev.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/blockdev.c
67
+++ b/blockdev.c
68
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
69
BlockDriverState *base_bs = NULL;
70
AioContext *aio_context;
71
Error *local_err = NULL;
72
- const char *base_name = NULL;
73
int job_flags = JOB_DEFAULT;
74
75
if (!has_on_error) {
76
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
77
goto out;
78
}
79
assert(bdrv_get_aio_context(base_bs) == aio_context);
80
- base_name = base;
81
}
82
83
if (has_base_node) {
84
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
85
}
86
assert(bdrv_get_aio_context(base_bs) == aio_context);
87
bdrv_refresh_filename(base_bs);
88
- base_name = base_bs->filename;
89
}
90
91
/* Check for op blockers in the whole chain between bs and base */
92
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
93
goto out;
94
}
95
96
- /* backing_file string overrides base bs filename */
97
- base_name = has_backing_file ? backing_file : base_name;
98
-
99
if (has_auto_finalize && !auto_finalize) {
100
job_flags |= JOB_MANUAL_FINALIZE;
101
}
102
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
103
job_flags |= JOB_MANUAL_DISMISS;
104
}
105
106
- stream_start(has_job_id ? job_id : NULL, bs, base_bs, base_name,
107
+ stream_start(has_job_id ? job_id : NULL, bs, base_bs, backing_file,
108
job_flags, has_speed ? speed : 0, on_error,
109
filter_node_name, &local_err);
110
if (local_err) {
111
--
112
2.29.2
113
114
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
The code already don't freeze base node and we try to make it prepared
4
for the situation when base node is changed during the operation. In
5
other words, block-stream doesn't own base node.
6
7
Let's introduce a new interface which should replace the current one,
8
which will in better relations with the code. Specifying bottom node
9
instead of base, and requiring it to be non-filter gives us the
10
following benefits:
11
12
- drop difference between above_base and base_overlay, which will be
13
renamed to just bottom, when old interface dropped
14
15
- clean way to work with parallel streams/commits on the same backing
16
chain, which otherwise become a problem when we introduce a filter
17
for stream job
18
19
- cleaner interface. Nobody will surprised the fact that base node may
20
disappear during block-stream, when there is no word about "base" in
21
the interface.
22
23
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
24
Message-Id: <20201216061703.70908-11-vsementsov@virtuozzo.com>
25
Reviewed-by: Max Reitz <mreitz@redhat.com>
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
---
28
qapi/block-core.json | 12 ++++---
29
include/block/block_int.h | 1 +
30
block/monitor/block-hmp-cmds.c | 3 +-
31
block/stream.c | 50 +++++++++++++++++++---------
32
blockdev.c | 59 ++++++++++++++++++++++++++++------
33
5 files changed, 94 insertions(+), 31 deletions(-)
34
35
diff --git a/qapi/block-core.json b/qapi/block-core.json
36
index XXXXXXX..XXXXXXX 100644
37
--- a/qapi/block-core.json
38
+++ b/qapi/block-core.json
39
@@ -XXX,XX +XXX,XX @@
40
# @device: the device or node name of the top image
41
#
42
# @base: the common backing file name.
43
-# It cannot be set if @base-node is also set.
44
+# It cannot be set if @base-node or @bottom is also set.
45
#
46
# @base-node: the node name of the backing file.
47
-# It cannot be set if @base is also set. (Since 2.8)
48
+# It cannot be set if @base or @bottom is also set. (Since 2.8)
49
+#
50
+# @bottom: the last node in the chain that should be streamed into
51
+# top. It cannot be set if @base or @base-node is also set.
52
+# It cannot be filter node. (Since 6.0)
53
#
54
# @backing-file: The backing file string to write into the top
55
# image. This filename is not validated.
56
@@ -XXX,XX +XXX,XX @@
57
##
58
{ 'command': 'block-stream',
59
'data': { '*job-id': 'str', 'device': 'str', '*base': 'str',
60
- '*base-node': 'str', '*backing-file': 'str', '*speed': 'int',
61
- '*on-error': 'BlockdevOnError',
62
+ '*base-node': 'str', '*backing-file': 'str', '*bottom': 'str',
63
+ '*speed': 'int', '*on-error': 'BlockdevOnError',
64
'*filter-node-name': 'str',
65
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
66
67
diff --git a/include/block/block_int.h b/include/block/block_int.h
68
index XXXXXXX..XXXXXXX 100644
69
--- a/include/block/block_int.h
70
+++ b/include/block/block_int.h
71
@@ -XXX,XX +XXX,XX @@ int is_windows_drive(const char *filename);
72
*/
73
void stream_start(const char *job_id, BlockDriverState *bs,
74
BlockDriverState *base, const char *backing_file_str,
75
+ BlockDriverState *bottom,
76
int creation_flags, int64_t speed,
77
BlockdevOnError on_error,
78
const char *filter_node_name,
79
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/block/monitor/block-hmp-cmds.c
82
+++ b/block/monitor/block-hmp-cmds.c
83
@@ -XXX,XX +XXX,XX @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
84
int64_t speed = qdict_get_try_int(qdict, "speed", 0);
85
86
qmp_block_stream(true, device, device, base != NULL, base, false, NULL,
87
- false, NULL, qdict_haskey(qdict, "speed"), speed, true,
88
+ false, NULL, false, NULL,
89
+ qdict_haskey(qdict, "speed"), speed, true,
90
BLOCKDEV_ON_ERROR_REPORT, false, NULL, false, false, false,
91
false, &error);
92
93
diff --git a/block/stream.c b/block/stream.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/block/stream.c
96
+++ b/block/stream.c
97
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver stream_job_driver = {
98
99
void stream_start(const char *job_id, BlockDriverState *bs,
100
BlockDriverState *base, const char *backing_file_str,
101
+ BlockDriverState *bottom,
102
int creation_flags, int64_t speed,
103
BlockdevOnError on_error,
104
const char *filter_node_name,
105
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
106
BlockDriverState *iter;
107
bool bs_read_only;
108
int basic_flags = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
109
- BlockDriverState *base_overlay = bdrv_find_overlay(bs, base);
110
+ BlockDriverState *base_overlay;
111
BlockDriverState *above_base;
112
113
- if (!base_overlay) {
114
- error_setg(errp, "'%s' is not in the backing chain of '%s'",
115
- base->node_name, bs->node_name);
116
- return;
117
- }
118
+ assert(!(base && bottom));
119
+ assert(!(backing_file_str && bottom));
120
+
121
+ if (bottom) {
122
+ /*
123
+ * New simple interface. The code is written in terms of old interface
124
+ * with @base parameter (still, it doesn't freeze link to base, so in
125
+ * this mean old code is correct for new interface). So, for now, just
126
+ * emulate base_overlay and above_base. Still, when old interface
127
+ * finally removed, we should refactor code to use only "bottom", but
128
+ * not "*base*" things.
129
+ */
130
+ assert(!bottom->drv->is_filter);
131
+ base_overlay = above_base = bottom;
132
+ } else {
133
+ base_overlay = bdrv_find_overlay(bs, base);
134
+ if (!base_overlay) {
135
+ error_setg(errp, "'%s' is not in the backing chain of '%s'",
136
+ base->node_name, bs->node_name);
137
+ return;
138
+ }
139
140
- /*
141
- * Find the node directly above @base. @base_overlay is a COW overlay, so
142
- * it must have a bdrv_cow_child(), but it is the immediate overlay of
143
- * @base, so between the two there can only be filters.
144
- */
145
- above_base = base_overlay;
146
- if (bdrv_cow_bs(above_base) != base) {
147
- above_base = bdrv_cow_bs(above_base);
148
- while (bdrv_filter_bs(above_base) != base) {
149
- above_base = bdrv_filter_bs(above_base);
150
+ /*
151
+ * Find the node directly above @base. @base_overlay is a COW overlay,
152
+ * so it must have a bdrv_cow_child(), but it is the immediate overlay
153
+ * of @base, so between the two there can only be filters.
154
+ */
155
+ above_base = base_overlay;
156
+ if (bdrv_cow_bs(above_base) != base) {
157
+ above_base = bdrv_cow_bs(above_base);
158
+ while (bdrv_filter_bs(above_base) != base) {
159
+ above_base = bdrv_filter_bs(above_base);
160
+ }
161
}
162
}
163
164
diff --git a/blockdev.c b/blockdev.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/blockdev.c
167
+++ b/blockdev.c
168
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
169
bool has_base, const char *base,
170
bool has_base_node, const char *base_node,
171
bool has_backing_file, const char *backing_file,
172
+ bool has_bottom, const char *bottom,
173
bool has_speed, int64_t speed,
174
bool has_on_error, BlockdevOnError on_error,
175
bool has_filter_node_name, const char *filter_node_name,
176
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
177
bool has_auto_dismiss, bool auto_dismiss,
178
Error **errp)
179
{
180
- BlockDriverState *bs, *iter;
181
+ BlockDriverState *bs, *iter, *iter_end;
182
BlockDriverState *base_bs = NULL;
183
+ BlockDriverState *bottom_bs = NULL;
184
AioContext *aio_context;
185
Error *local_err = NULL;
186
int job_flags = JOB_DEFAULT;
187
188
+ if (has_base && has_base_node) {
189
+ error_setg(errp, "'base' and 'base-node' cannot be specified "
190
+ "at the same time");
191
+ return;
192
+ }
193
+
194
+ if (has_base && has_bottom) {
195
+ error_setg(errp, "'base' and 'bottom' cannot be specified "
196
+ "at the same time");
197
+ return;
198
+ }
199
+
200
+ if (has_bottom && has_base_node) {
201
+ error_setg(errp, "'bottom' and 'base-node' cannot be specified "
202
+ "at the same time");
203
+ return;
204
+ }
205
+
206
if (!has_on_error) {
207
on_error = BLOCKDEV_ON_ERROR_REPORT;
208
}
209
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
210
aio_context = bdrv_get_aio_context(bs);
211
aio_context_acquire(aio_context);
212
213
- if (has_base && has_base_node) {
214
- error_setg(errp, "'base' and 'base-node' cannot be specified "
215
- "at the same time");
216
- goto out;
217
- }
218
-
219
if (has_base) {
220
base_bs = bdrv_find_backing_image(bs, base);
221
if (base_bs == NULL) {
222
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
223
bdrv_refresh_filename(base_bs);
224
}
225
226
- /* Check for op blockers in the whole chain between bs and base */
227
- for (iter = bs; iter && iter != base_bs;
228
+ if (has_bottom) {
229
+ bottom_bs = bdrv_lookup_bs(NULL, bottom, errp);
230
+ if (!bottom_bs) {
231
+ goto out;
232
+ }
233
+ if (!bottom_bs->drv) {
234
+ error_setg(errp, "Node '%s' is not open", bottom);
235
+ goto out;
236
+ }
237
+ if (bottom_bs->drv->is_filter) {
238
+ error_setg(errp, "Node '%s' is a filter, use a non-filter node "
239
+ "as 'bottom'", bottom);
240
+ goto out;
241
+ }
242
+ if (!bdrv_chain_contains(bs, bottom_bs)) {
243
+ error_setg(errp, "Node '%s' is not in a chain starting from '%s'",
244
+ bottom, device);
245
+ goto out;
246
+ }
247
+ assert(bdrv_get_aio_context(bottom_bs) == aio_context);
248
+ }
249
+
250
+ /*
251
+ * Check for op blockers in the whole chain between bs and base (or bottom)
252
+ */
253
+ iter_end = has_bottom ? bdrv_filter_or_cow_bs(bottom_bs) : base_bs;
254
+ for (iter = bs; iter && iter != iter_end;
255
iter = bdrv_filter_or_cow_bs(iter))
256
{
257
if (bdrv_op_is_blocked(iter, BLOCK_OP_TYPE_STREAM, errp)) {
258
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
259
}
260
261
stream_start(has_job_id ? job_id : NULL, bs, base_bs, backing_file,
262
- job_flags, has_speed ? speed : 0, on_error,
263
+ bottom_bs, job_flags, has_speed ? speed : 0, on_error,
264
filter_node_name, &local_err);
265
if (local_err) {
266
error_propagate(errp, local_err);
267
--
268
2.29.2
269
270
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
2
3
test_stream_parallel run parallel stream jobs, intersecting so that top
4
of one is base of another. It's OK now, but it would be a problem if
5
insert the filter, as one job will want to use another job's filter as
6
above_base node.
7
8
Correct thing to do is move to new interface: "bottom" argument instead
9
of base. This guarantees that jobs don't intersect by their actions.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20201216061703.70908-12-vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
tests/qemu-iotests/030 | 4 +++-
17
1 file changed, 3 insertions(+), 1 deletion(-)
18
19
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
20
index XXXXXXX..XXXXXXX 100755
21
--- a/tests/qemu-iotests/030
22
+++ b/tests/qemu-iotests/030
23
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
24
node_name = 'node%d' % i
25
job_id = 'stream-%s' % node_name
26
pending_jobs.append(job_id)
27
- result = self.vm.qmp('block-stream', device=node_name, job_id=job_id, base=self.imgs[i-2], speed=1024)
28
+ result = self.vm.qmp('block-stream', device=node_name,
29
+ job_id=job_id, bottom=f'node{i-1}',
30
+ speed=1024)
31
self.assert_qmp(result, 'return', {})
32
33
for job in pending_jobs:
34
--
35
2.29.2
36
37
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Commit 6f6e1698a6 desugarized "-machine accel=" to a list
3
Add a direct link to target bs for convenience and to simplify
4
of "-accel" options. Since now "-machine accel" and "-accel"
4
following commit which will insert COR filter above target bs.
5
became incompatible, update the iotests to the new format.
6
5
7
Error reported here:
6
This is a part of original commit written by Andrey.
8
https://gitlab.com/qemu-project/qemu/-/jobs/385801004#L3400
9
7
10
Reported-by: GitLab CI
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Fixes: 6f6e1698a6 (vl: configure accelerators from -accel options)
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-Id: <20201216061703.70908-13-vsementsov@virtuozzo.com>
13
Message-id: 20200106130951.29873-1-philmd@redhat.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
12
---
16
tests/qemu-iotests/235 | 2 +-
13
block/stream.c | 23 ++++++++++-------------
17
tests/qemu-iotests/check | 6 +++---
14
1 file changed, 10 insertions(+), 13 deletions(-)
18
2 files changed, 4 insertions(+), 4 deletions(-)
19
15
20
diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235
16
diff --git a/block/stream.c b/block/stream.c
21
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/235
18
--- a/block/stream.c
23
+++ b/tests/qemu-iotests/235
19
+++ b/block/stream.c
24
@@ -XXX,XX +XXX,XX @@ qemu_img_create('-f', iotests.imgfmt, '-o', 'preallocation=metadata', disk,
20
@@ -XXX,XX +XXX,XX @@ typedef struct StreamBlockJob {
25
str(size))
21
BlockJob common;
26
22
BlockDriverState *base_overlay; /* COW overlay (stream from this) */
27
vm = QEMUMachine(iotests.qemu_prog)
23
BlockDriverState *above_base; /* Node directly above the base */
28
-vm.add_args('-machine', 'accel=kvm:tcg')
24
+ BlockDriverState *target_bs;
29
+vm.add_args('-accel', 'kvm', '-accel', 'tcg')
25
BlockdevOnError on_error;
30
if iotests.qemu_default_machine == 's390-ccw-virtio':
26
char *backing_file_str;
31
vm.add_args('-no-shutdown')
27
bool bs_read_only;
32
vm.add_args('-drive', 'id=src,file=' + disk)
28
@@ -XXX,XX +XXX,XX @@ static void stream_abort(Job *job)
33
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
29
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
34
index XXXXXXX..XXXXXXX 100755
30
35
--- a/tests/qemu-iotests/check
31
if (s->chain_frozen) {
36
+++ b/tests/qemu-iotests/check
32
- BlockJob *bjob = &s->common;
37
@@ -XXX,XX +XXX,XX @@ export QEMU_PROG="$(type -p "$QEMU_PROG")"
33
- bdrv_unfreeze_backing_chain(blk_bs(bjob->blk), s->above_base);
38
34
+ bdrv_unfreeze_backing_chain(s->target_bs, s->above_base);
39
case "$QEMU_PROG" in
35
}
40
*qemu-system-arm|*qemu-system-aarch64)
36
}
41
- export QEMU_OPTIONS="-nodefaults -display none -machine virt,accel=qtest"
37
42
+ export QEMU_OPTIONS="-nodefaults -display none -machine virt -accel qtest"
38
static int stream_prepare(Job *job)
43
;;
39
{
44
*qemu-system-tricore)
40
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
45
- export QEMU_OPTIONS="-nodefaults -display none -machine tricore_testboard,accel=qtest"
41
- BlockJob *bjob = &s->common;
46
+ export QEMU_OPTIONS="-nodefaults -display none -machine tricore_testboard -accel qtest"
42
- BlockDriverState *bs = blk_bs(bjob->blk);
47
;;
43
- BlockDriverState *unfiltered_bs = bdrv_skip_filters(bs);
48
*)
44
+ BlockDriverState *unfiltered_bs = bdrv_skip_filters(s->target_bs);
49
- export QEMU_OPTIONS="-nodefaults -display none -machine accel=qtest"
45
BlockDriverState *base = bdrv_filter_or_cow_bs(s->above_base);
50
+ export QEMU_OPTIONS="-nodefaults -display none -accel qtest"
46
BlockDriverState *unfiltered_base = bdrv_skip_filters(base);
51
;;
47
Error *local_err = NULL;
52
esac
48
int ret = 0;
49
50
- bdrv_unfreeze_backing_chain(bs, s->above_base);
51
+ bdrv_unfreeze_backing_chain(s->target_bs, s->above_base);
52
s->chain_frozen = false;
53
54
if (bdrv_cow_child(unfiltered_bs)) {
55
@@ -XXX,XX +XXX,XX @@ static void stream_clean(Job *job)
56
{
57
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
58
BlockJob *bjob = &s->common;
59
- BlockDriverState *bs = blk_bs(bjob->blk);
60
61
/* Reopen the image back in read-only mode if necessary */
62
if (s->bs_read_only) {
63
/* Give up write permissions before making it read-only */
64
blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
65
- bdrv_reopen_set_read_only(bs, true, NULL);
66
+ bdrv_reopen_set_read_only(s->target_bs, true, NULL);
67
}
68
69
g_free(s->backing_file_str);
70
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
71
{
72
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
73
BlockBackend *blk = s->common.blk;
74
- BlockDriverState *bs = blk_bs(blk);
75
- BlockDriverState *unfiltered_bs = bdrv_skip_filters(bs);
76
+ BlockDriverState *unfiltered_bs = bdrv_skip_filters(s->target_bs);
77
bool enable_cor = !bdrv_cow_child(s->base_overlay);
78
int64_t len;
79
int64_t offset = 0;
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
81
return 0;
82
}
83
84
- len = bdrv_getlength(bs);
85
+ len = bdrv_getlength(s->target_bs);
86
if (len < 0) {
87
return len;
88
}
89
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
90
* account.
91
*/
92
if (enable_cor) {
93
- bdrv_enable_copy_on_read(bs);
94
+ bdrv_enable_copy_on_read(s->target_bs);
95
}
96
97
for ( ; offset < len; offset += n) {
98
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
99
}
100
101
if (enable_cor) {
102
- bdrv_disable_copy_on_read(bs);
103
+ bdrv_disable_copy_on_read(s->target_bs);
104
}
105
106
/* Do not remove the backing file if an error was there but ignored. */
107
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
108
s->base_overlay = base_overlay;
109
s->above_base = above_base;
110
s->backing_file_str = g_strdup(backing_file_str);
111
+ s->target_bs = bs;
112
s->bs_read_only = bs_read_only;
113
s->chain_frozen = true;
53
114
54
--
115
--
55
2.24.1
116
2.29.2
56
117
57
118
diff view generated by jsdifflib
New patch
1
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
2
3
This patch completes the series with the COR-filter applied to
4
block-stream operations.
5
6
Adding the filter makes it possible in future implement discarding
7
copied regions in backing files during the block-stream job, to reduce
8
the disk overuse (we need control on permissions).
9
10
Also, the filter now is smart enough to do copy-on-read with specified
11
base, so we have benefit on guest reads even when doing block-stream of
12
the part of the backing chain.
13
14
Several iotests are slightly modified due to filter insertion.
15
16
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
17
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Message-Id: <20201216061703.70908-14-vsementsov@virtuozzo.com>
19
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
22
block/stream.c | 105 ++++++++++++++++++++++---------------
23
tests/qemu-iotests/030 | 8 +--
24
tests/qemu-iotests/141.out | 2 +-
25
tests/qemu-iotests/245 | 20 ++++---
26
4 files changed, 80 insertions(+), 55 deletions(-)
27
28
diff --git a/block/stream.c b/block/stream.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/stream.c
31
+++ b/block/stream.c
32
@@ -XXX,XX +XXX,XX @@
33
#include "block/blockjob_int.h"
34
#include "qapi/error.h"
35
#include "qapi/qmp/qerror.h"
36
+#include "qapi/qmp/qdict.h"
37
#include "qemu/ratelimit.h"
38
#include "sysemu/block-backend.h"
39
+#include "block/copy-on-read.h"
40
41
enum {
42
/*
43
@@ -XXX,XX +XXX,XX @@ typedef struct StreamBlockJob {
44
BlockJob common;
45
BlockDriverState *base_overlay; /* COW overlay (stream from this) */
46
BlockDriverState *above_base; /* Node directly above the base */
47
+ BlockDriverState *cor_filter_bs;
48
BlockDriverState *target_bs;
49
BlockdevOnError on_error;
50
char *backing_file_str;
51
bool bs_read_only;
52
- bool chain_frozen;
53
} StreamBlockJob;
54
55
static int coroutine_fn stream_populate(BlockBackend *blk,
56
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_populate(BlockBackend *blk,
57
{
58
assert(bytes < SIZE_MAX);
59
60
- return blk_co_preadv(blk, offset, bytes, NULL,
61
- BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH);
62
-}
63
-
64
-static void stream_abort(Job *job)
65
-{
66
- StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
67
-
68
- if (s->chain_frozen) {
69
- bdrv_unfreeze_backing_chain(s->target_bs, s->above_base);
70
- }
71
+ return blk_co_preadv(blk, offset, bytes, NULL, BDRV_REQ_PREFETCH);
72
}
73
74
static int stream_prepare(Job *job)
75
@@ -XXX,XX +XXX,XX @@ static int stream_prepare(Job *job)
76
Error *local_err = NULL;
77
int ret = 0;
78
79
- bdrv_unfreeze_backing_chain(s->target_bs, s->above_base);
80
- s->chain_frozen = false;
81
+ /* We should drop filter at this point, as filter hold the backing chain */
82
+ bdrv_cor_filter_drop(s->cor_filter_bs);
83
+ s->cor_filter_bs = NULL;
84
85
if (bdrv_cow_child(unfiltered_bs)) {
86
const char *base_id = NULL, *base_fmt = NULL;
87
@@ -XXX,XX +XXX,XX @@ static void stream_clean(Job *job)
88
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
89
BlockJob *bjob = &s->common;
90
91
+ if (s->cor_filter_bs) {
92
+ bdrv_cor_filter_drop(s->cor_filter_bs);
93
+ s->cor_filter_bs = NULL;
94
+ }
95
+
96
/* Reopen the image back in read-only mode if necessary */
97
if (s->bs_read_only) {
98
/* Give up write permissions before making it read-only */
99
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
100
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
101
BlockBackend *blk = s->common.blk;
102
BlockDriverState *unfiltered_bs = bdrv_skip_filters(s->target_bs);
103
- bool enable_cor = !bdrv_cow_child(s->base_overlay);
104
int64_t len;
105
int64_t offset = 0;
106
uint64_t delay_ns = 0;
107
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
108
}
109
job_progress_set_remaining(&s->common.job, len);
110
111
- /* Turn on copy-on-read for the whole block device so that guest read
112
- * requests help us make progress. Only do this when copying the entire
113
- * backing chain since the copy-on-read operation does not take base into
114
- * account.
115
- */
116
- if (enable_cor) {
117
- bdrv_enable_copy_on_read(s->target_bs);
118
- }
119
-
120
for ( ; offset < len; offset += n) {
121
bool copy;
122
int ret;
123
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_run(Job *job, Error **errp)
124
}
125
}
126
127
- if (enable_cor) {
128
- bdrv_disable_copy_on_read(s->target_bs);
129
- }
130
-
131
/* Do not remove the backing file if an error was there but ignored. */
132
return error;
133
}
134
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver stream_job_driver = {
135
.free = block_job_free,
136
.run = stream_run,
137
.prepare = stream_prepare,
138
- .abort = stream_abort,
139
.clean = stream_clean,
140
.user_resume = block_job_user_resume,
141
},
142
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
143
bool bs_read_only;
144
int basic_flags = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
145
BlockDriverState *base_overlay;
146
+ BlockDriverState *cor_filter_bs = NULL;
147
BlockDriverState *above_base;
148
+ QDict *opts;
149
150
assert(!(base && bottom));
151
assert(!(backing_file_str && bottom));
152
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
153
}
154
}
155
156
- if (bdrv_freeze_backing_chain(bs, above_base, errp) < 0) {
157
- return;
158
- }
159
-
160
/* Make sure that the image is opened in read-write mode */
161
bs_read_only = bdrv_is_read_only(bs);
162
if (bs_read_only) {
163
- if (bdrv_reopen_set_read_only(bs, false, errp) != 0) {
164
- bs_read_only = false;
165
- goto fail;
166
+ int ret;
167
+ /* Hold the chain during reopen */
168
+ if (bdrv_freeze_backing_chain(bs, above_base, errp) < 0) {
169
+ return;
170
+ }
171
+
172
+ ret = bdrv_reopen_set_read_only(bs, false, errp);
173
+
174
+ /* failure, or cor-filter will hold the chain */
175
+ bdrv_unfreeze_backing_chain(bs, above_base);
176
+
177
+ if (ret < 0) {
178
+ return;
179
}
180
}
181
182
- /* Prevent concurrent jobs trying to modify the graph structure here, we
183
- * already have our own plans. Also don't allow resize as the image size is
184
- * queried only at the job start and then cached. */
185
- s = block_job_create(job_id, &stream_job_driver, NULL, bs,
186
- basic_flags | BLK_PERM_GRAPH_MOD,
187
+ opts = qdict_new();
188
+
189
+ qdict_put_str(opts, "driver", "copy-on-read");
190
+ qdict_put_str(opts, "file", bdrv_get_node_name(bs));
191
+ /* Pass the base_overlay node name as 'bottom' to COR driver */
192
+ qdict_put_str(opts, "bottom", base_overlay->node_name);
193
+ if (filter_node_name) {
194
+ qdict_put_str(opts, "node-name", filter_node_name);
195
+ }
196
+
197
+ cor_filter_bs = bdrv_insert_node(bs, opts, BDRV_O_RDWR, errp);
198
+ if (!cor_filter_bs) {
199
+ goto fail;
200
+ }
201
+
202
+ if (!filter_node_name) {
203
+ cor_filter_bs->implicit = true;
204
+ }
205
+
206
+ s = block_job_create(job_id, &stream_job_driver, NULL, cor_filter_bs,
207
+ BLK_PERM_CONSISTENT_READ,
208
basic_flags | BLK_PERM_WRITE,
209
speed, creation_flags, NULL, NULL, errp);
210
if (!s) {
211
goto fail;
212
}
213
214
+ /*
215
+ * Prevent concurrent jobs trying to modify the graph structure here, we
216
+ * already have our own plans. Also don't allow resize as the image size is
217
+ * queried only at the job start and then cached.
218
+ */
219
+ if (block_job_add_bdrv(&s->common, "active node", bs, 0,
220
+ basic_flags | BLK_PERM_WRITE, &error_abort)) {
221
+ goto fail;
222
+ }
223
+
224
/* Block all intermediate nodes between bs and base, because they will
225
* disappear from the chain after this operation. The streaming job reads
226
* every block only once, assuming that it doesn't change, so forbid writes
227
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
228
s->base_overlay = base_overlay;
229
s->above_base = above_base;
230
s->backing_file_str = g_strdup(backing_file_str);
231
+ s->cor_filter_bs = cor_filter_bs;
232
s->target_bs = bs;
233
s->bs_read_only = bs_read_only;
234
- s->chain_frozen = true;
235
236
s->on_error = on_error;
237
trace_stream_start(bs, base, s);
238
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
239
return;
240
241
fail:
242
+ if (cor_filter_bs) {
243
+ bdrv_cor_filter_drop(cor_filter_bs);
244
+ }
245
if (bs_read_only) {
246
bdrv_reopen_set_read_only(bs, true, NULL);
247
}
248
- bdrv_unfreeze_backing_chain(bs, above_base);
249
}
250
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
251
index XXXXXXX..XXXXXXX 100755
252
--- a/tests/qemu-iotests/030
253
+++ b/tests/qemu-iotests/030
254
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
255
self.assert_no_active_block_jobs()
256
257
# Set a speed limit to make sure that this job blocks the rest
258
- result = self.vm.qmp('block-stream', device='node4', job_id='stream-node4', base=self.imgs[1], speed=1024*1024)
259
+ result = self.vm.qmp('block-stream', device='node4',
260
+ job_id='stream-node4', base=self.imgs[1],
261
+ filter_node_name='stream-filter', speed=1024*1024)
262
self.assert_qmp(result, 'return', {})
263
264
result = self.vm.qmp('block-stream', device='node5', job_id='stream-node5', base=self.imgs[2])
265
self.assert_qmp(result, 'error/desc',
266
- "Node 'node4' is busy: block device is in use by block job: stream")
267
+ "Node 'stream-filter' is busy: block device is in use by block job: stream")
268
269
result = self.vm.qmp('block-stream', device='node3', job_id='stream-node3', base=self.imgs[2])
270
self.assert_qmp(result, 'error/desc',
271
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
272
# block-commit should also fail if it touches nodes used by the stream job
273
result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[4], job_id='commit-node4')
274
self.assert_qmp(result, 'error/desc',
275
- "Node 'node4' is busy: block device is in use by block job: stream")
276
+ "Node 'stream-filter' is busy: block device is in use by block job: stream")
277
278
result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[1], top=self.imgs[3], job_id='commit-node1')
279
self.assert_qmp(result, 'error/desc',
280
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
281
index XXXXXXX..XXXXXXX 100644
282
--- a/tests/qemu-iotests/141.out
283
+++ b/tests/qemu-iotests/141.out
284
@@ -XXX,XX +XXX,XX @@ wrote 1048576/1048576 bytes at offset 0
285
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
286
{'execute': 'blockdev-del',
287
'arguments': {'node-name': 'drv0'}}
288
-{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
289
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}}
290
{'execute': 'block-job-cancel',
291
'arguments': {'device': 'job0'}}
292
{"return": {}}
293
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
294
index XXXXXXX..XXXXXXX 100755
295
--- a/tests/qemu-iotests/245
296
+++ b/tests/qemu-iotests/245
297
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
298
299
# hd1 <- hd0
300
result = self.vm.qmp('block-stream', conv_keys = True, job_id = 'stream0',
301
- device = 'hd1', auto_finalize = False)
302
+ device = 'hd1', filter_node_name='cor',
303
+ auto_finalize = False)
304
self.assert_qmp(result, 'return', {})
305
306
- # We can't reopen with the original options because that would
307
- # make hd1 read-only and block-stream requires it to be read-write
308
- # (Which error message appears depends on whether the stream job is
309
- # already done with copying at this point.)
310
+ # We can't reopen with the original options because there is a filter
311
+ # inserted by stream job above hd1.
312
self.reopen(opts, {},
313
- ["Can't set node 'hd1' to r/o with copy-on-read enabled",
314
- "Cannot make block node read-only, there is a writer on it"])
315
+ "Cannot change the option 'backing.backing.file.node-name'")
316
+
317
+ # We can't reopen hd1 to read-only, as block-stream requires it to be
318
+ # read-write
319
+ self.reopen(opts['backing'], {'read-only': True},
320
+ "Cannot make block node read-only, there is a writer on it")
321
322
# We can't remove hd2 while the stream job is ongoing
323
opts['backing']['backing'] = None
324
- self.reopen(opts, {'backing.read-only': False}, "Cannot change 'backing' link from 'hd1' to 'hd2'")
325
+ self.reopen(opts['backing'], {'read-only': False},
326
+ "Cannot change 'backing' link from 'hd1' to 'hd2'")
327
328
# We can detach hd1 from hd0 because it doesn't affect the stream job
329
opts['backing'] = None
330
--
331
2.29.2
332
333
diff view generated by jsdifflib
1
Callers can use this new parameter to expect failure during the
1
There are a couple of environment variables that we fetch with
2
completion process.
2
os.environ.get() without supplying a default. Clearly they are required
3
and expected to be set by the ./check script (as evidenced by
4
execute_setup_common(), which checks for test_dir and
5
qemu_default_machine to be set, and aborts if they are not).
6
7
Using .get() this way has the disadvantage of returning an Optional[str]
8
type, which mypy will complain about when tests just assume these values
9
to be str.
10
11
Use [] instead, which raises a KeyError for environment variables that
12
are not set. When this exception is raised, catch it and move the abort
13
code from execute_setup_common() there.
14
15
Drop the 'assert iotests.sock_dir is not None' from iotest 300, because
16
that sort of thing is precisely what this patch wants to prevent.
3
17
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-id: 20191108123455.39445-5-mreitz@redhat.com
20
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Message-Id: <20210118105720.14824-2-mreitz@redhat.com>
9
---
22
---
10
tests/qemu-iotests/iotests.py | 18 ++++++++++++------
23
tests/qemu-iotests/300 | 1 -
11
1 file changed, 12 insertions(+), 6 deletions(-)
24
tests/qemu-iotests/iotests.py | 26 +++++++++++++-------------
25
2 files changed, 13 insertions(+), 14 deletions(-)
12
26
27
diff --git a/tests/qemu-iotests/300 b/tests/qemu-iotests/300
28
index XXXXXXX..XXXXXXX 100755
29
--- a/tests/qemu-iotests/300
30
+++ b/tests/qemu-iotests/300
31
@@ -XXX,XX +XXX,XX @@ import qemu
32
33
BlockBitmapMapping = List[Dict[str, Union[str, List[Dict[str, str]]]]]
34
35
-assert iotests.sock_dir is not None
36
mig_sock = os.path.join(iotests.sock_dir, 'mig_sock')
37
38
13
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
39
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/iotests.py
41
--- a/tests/qemu-iotests/iotests.py
16
+++ b/tests/qemu-iotests/iotests.py
42
+++ b/tests/qemu-iotests/iotests.py
17
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
43
@@ -XXX,XX +XXX,XX @@ qemu_opts = os.environ.get('QEMU_OPTIONS', '').strip().split(' ')
18
self.assert_no_active_block_jobs()
44
19
return result
45
imgfmt = os.environ.get('IMGFMT', 'raw')
20
46
imgproto = os.environ.get('IMGPROTO', 'file')
21
- def wait_until_completed(self, drive='drive0', check_offset=True, wait=60.0):
47
-test_dir = os.environ.get('TEST_DIR')
22
+ def wait_until_completed(self, drive='drive0', check_offset=True, wait=60.0,
48
-sock_dir = os.environ.get('SOCK_DIR')
23
+ error=None):
49
output_dir = os.environ.get('OUTPUT_DIR', '.')
24
'''Wait for a block job to finish, returning the event'''
50
-cachemode = os.environ.get('CACHEMODE')
25
while True:
51
-aiomode = os.environ.get('AIOMODE')
26
for event in self.vm.get_qmp_events(wait=wait):
52
-qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE')
27
if event['event'] == 'BLOCK_JOB_COMPLETED':
53
+
28
self.assert_qmp(event, 'data/device', drive)
54
+try:
29
- self.assert_qmp_absent(event, 'data/error')
55
+ test_dir = os.environ['TEST_DIR']
30
- if check_offset:
56
+ sock_dir = os.environ['SOCK_DIR']
31
- self.assert_qmp(event, 'data/offset', event['data']['len'])
57
+ cachemode = os.environ['CACHEMODE']
32
+ if error is None:
58
+ aiomode = os.environ['AIOMODE']
33
+ self.assert_qmp_absent(event, 'data/error')
59
+ qemu_default_machine = os.environ['QEMU_DEFAULT_MACHINE']
34
+ if check_offset:
60
+except KeyError:
35
+ self.assert_qmp(event, 'data/offset',
61
+ # We are using these variables as proxies to indicate that we're
36
+ event['data']['len'])
62
+ # not being run via "check". There may be other things set up by
37
+ else:
63
+ # "check" that individual test cases rely on.
38
+ self.assert_qmp(event, 'data/error', error)
64
+ sys.stderr.write('Please run this test via the "check" script\n')
39
self.assert_no_active_block_jobs()
65
+ sys.exit(os.EX_USAGE)
40
return event
66
41
elif event['event'] == 'JOB_STATUS_CHANGE':
67
socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
42
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
68
43
self.assert_qmp(event, 'data/type', 'mirror')
69
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
44
self.assert_qmp(event, 'data/offset', event['data']['len'])
70
"""
45
71
# Note: Python 3.6 and pylint do not like 'Collection' so use 'Sequence'.
46
- def complete_and_wait(self, drive='drive0', wait_ready=True):
72
47
+ def complete_and_wait(self, drive='drive0', wait_ready=True,
73
- # We are using TEST_DIR and QEMU_DEFAULT_MACHINE as proxies to
48
+ completion_error=None):
74
- # indicate that we're not being run via "check". There may be
49
'''Complete a block job and wait for it to finish'''
75
- # other things set up by "check" that individual test cases rely
50
if wait_ready:
76
- # on.
51
self.wait_ready(drive=drive)
77
- if test_dir is None or qemu_default_machine is None:
52
@@ -XXX,XX +XXX,XX @@ class QMPTestCase(unittest.TestCase):
78
- sys.stderr.write('Please run this test via the "check" script\n')
53
result = self.vm.qmp('block-job-complete', device=drive)
79
- sys.exit(os.EX_USAGE)
54
self.assert_qmp(result, 'return', {})
80
-
55
81
debug = '-d' in sys.argv
56
- event = self.wait_until_completed(drive=drive)
82
if debug:
57
+ event = self.wait_until_completed(drive=drive, error=completion_error)
83
sys.argv.remove('-d')
58
self.assert_qmp(event, 'data/type', 'mirror')
59
60
def pause_wait(self, job_id='job0'):
61
--
84
--
62
2.24.1
85
2.29.2
63
86
64
87
diff view generated by jsdifflib
New patch
1
Instead of checking iotests.py only, check all Python files in the
2
qemu-iotests/ directory. Of course, most of them do not pass, so there
3
is an extensive skip list for now. (The only files that do pass are
4
209, 254, 283, and iotests.py.)
1
5
6
(Alternatively, we could have the opposite, i.e. an explicit list of
7
files that we do want to check, but I think it is better to check files
8
by default.)
9
10
Unless started in debug mode (./check -d), the output has no information
11
on which files are tested, so we will not have a problem e.g. with
12
backports, where some files may be missing when compared to upstream.
13
14
Besides the technical rewrite, some more things are changed:
15
16
- For the pylint invocation, PYTHONPATH is adjusted. This mirrors
17
setting MYPYPATH for mypy.
18
19
- Also, MYPYPATH is now derived from PYTHONPATH, so that we include
20
paths set by the environment. Maybe at some point we want to let the
21
check script add '../../python/' to PYTHONPATH so that iotests.py does
22
not need to do that.
23
24
- Passing --notes=FIXME,XXX to pylint suppresses warnings for TODO
25
comments. TODO is fine, we do not need 297 to complain about such
26
comments.
27
28
- The "Success" line from mypy's output is suppressed, because (A) it
29
does not add useful information, and (B) it would leak information
30
about the files having been tested to the reference output, which we
31
decidedly do not want.
32
33
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
34
Signed-off-by: Max Reitz <mreitz@redhat.com>
35
Message-Id: <20210118105720.14824-3-mreitz@redhat.com>
36
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
37
---
38
tests/qemu-iotests/297 | 112 +++++++++++++++++++++++++++++--------
39
tests/qemu-iotests/297.out | 5 +-
40
2 files changed, 92 insertions(+), 25 deletions(-)
41
42
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
43
index XXXXXXX..XXXXXXX 100755
44
--- a/tests/qemu-iotests/297
45
+++ b/tests/qemu-iotests/297
46
@@ -XXX,XX +XXX,XX @@
47
-#!/usr/bin/env bash
48
+#!/usr/bin/env python3
49
# group: meta
50
#
51
# Copyright (C) 2020 Red Hat, Inc.
52
@@ -XXX,XX +XXX,XX @@
53
# You should have received a copy of the GNU General Public License
54
# along with this program. If not, see <http://www.gnu.org/licenses/>.
55
56
-seq=$(basename $0)
57
-echo "QA output created by $seq"
58
+import os
59
+import re
60
+import shutil
61
+import subprocess
62
+import sys
63
64
-status=1    # failure is the default!
65
+import iotests
66
67
-# get standard environment
68
-. ./common.rc
69
70
-if ! type -p "pylint-3" > /dev/null; then
71
- _notrun "pylint-3 not found"
72
-fi
73
-if ! type -p "mypy" > /dev/null; then
74
- _notrun "mypy not found"
75
-fi
76
+# TODO: Empty this list!
77
+SKIP_FILES = (
78
+ '030', '040', '041', '044', '045', '055', '056', '057', '065', '093',
79
+ '096', '118', '124', '129', '132', '136', '139', '147', '148', '149',
80
+ '151', '152', '155', '163', '165', '169', '194', '196', '199', '202',
81
+ '203', '205', '206', '207', '208', '210', '211', '212', '213', '216',
82
+ '218', '219', '222', '224', '228', '234', '235', '236', '237', '238',
83
+ '240', '242', '245', '246', '248', '255', '256', '257', '258', '260',
84
+ '262', '264', '266', '274', '277', '280', '281', '295', '296', '298',
85
+ '299', '300', '302', '303', '304', '307',
86
+ 'nbd-fault-injector.py', 'qcow2.py', 'qcow2_format.py', 'qed.py'
87
+)
88
89
-pylint-3 --score=n iotests.py
90
91
-MYPYPATH=../../python/ mypy --warn-unused-configs --disallow-subclassing-any \
92
- --disallow-any-generics --disallow-incomplete-defs \
93
- --disallow-untyped-decorators --no-implicit-optional \
94
- --warn-redundant-casts --warn-unused-ignores \
95
- --no-implicit-reexport iotests.py
96
+def is_python_file(filename):
97
+ if not os.path.isfile(filename):
98
+ return False
99
100
-# success, all done
101
-echo "*** done"
102
-rm -f $seq.full
103
-status=0
104
+ if filename.endswith('.py'):
105
+ return True
106
+
107
+ with open(filename) as f:
108
+ try:
109
+ first_line = f.readline()
110
+ return re.match('^#!.*python', first_line) is not None
111
+ except UnicodeDecodeError: # Ignore binary files
112
+ return False
113
+
114
+
115
+def run_linters():
116
+ files = [filename for filename in (set(os.listdir('.')) - set(SKIP_FILES))
117
+ if is_python_file(filename)]
118
+
119
+ iotests.logger.debug('Files to be checked:')
120
+ iotests.logger.debug(', '.join(sorted(files)))
121
+
122
+ print('=== pylint ===')
123
+ sys.stdout.flush()
124
+
125
+ # Todo notes are fine, but fixme's or xxx's should probably just be
126
+ # fixed (in tests, at least)
127
+ env = os.environ.copy()
128
+ qemu_module_path = os.path.join(os.path.dirname(__file__),
129
+ '..', '..', 'python')
130
+ try:
131
+ env['PYTHONPATH'] += os.pathsep + qemu_module_path
132
+ except KeyError:
133
+ env['PYTHONPATH'] = qemu_module_path
134
+ subprocess.run(('pylint-3', '--score=n', '--notes=FIXME,XXX', *files),
135
+ env=env, check=False)
136
+
137
+ print('=== mypy ===')
138
+ sys.stdout.flush()
139
+
140
+ # We have to call mypy separately for each file. Otherwise, it
141
+ # will interpret all given files as belonging together (i.e., they
142
+ # may not both define the same classes, etc.; most notably, they
143
+ # must not both define the __main__ module).
144
+ env['MYPYPATH'] = env['PYTHONPATH']
145
+ for filename in files:
146
+ p = subprocess.run(('mypy',
147
+ '--warn-unused-configs',
148
+ '--disallow-subclassing-any',
149
+ '--disallow-any-generics',
150
+ '--disallow-incomplete-defs',
151
+ '--disallow-untyped-decorators',
152
+ '--no-implicit-optional',
153
+ '--warn-redundant-casts',
154
+ '--warn-unused-ignores',
155
+ '--no-implicit-reexport',
156
+ filename),
157
+ env=env,
158
+ check=False,
159
+ stdout=subprocess.PIPE,
160
+ stderr=subprocess.STDOUT,
161
+ universal_newlines=True)
162
+
163
+ if p.returncode != 0:
164
+ print(p.stdout)
165
+
166
+
167
+for linter in ('pylint-3', 'mypy'):
168
+ if shutil.which(linter) is None:
169
+ iotests.notrun(f'{linter} not found')
170
+
171
+iotests.script_main(run_linters)
172
diff --git a/tests/qemu-iotests/297.out b/tests/qemu-iotests/297.out
173
index XXXXXXX..XXXXXXX 100644
174
--- a/tests/qemu-iotests/297.out
175
+++ b/tests/qemu-iotests/297.out
176
@@ -XXX,XX +XXX,XX @@
177
-QA output created by 297
178
-Success: no issues found in 1 source file
179
-*** done
180
+=== pylint ===
181
+=== mypy ===
182
--
183
2.29.2
184
185
diff view generated by jsdifflib
New patch
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
5
Message-Id: <20210118105720.14824-4-mreitz@redhat.com>
6
---
7
tests/qemu-iotests/124 | 8 +-------
8
tests/qemu-iotests/iotests.py | 11 +++++++----
9
2 files changed, 8 insertions(+), 11 deletions(-)
1
10
11
diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124
12
index XXXXXXX..XXXXXXX 100755
13
--- a/tests/qemu-iotests/124
14
+++ b/tests/qemu-iotests/124
15
@@ -XXX,XX +XXX,XX @@
16
17
import os
18
import iotests
19
+from iotests import try_remove
20
21
22
def io_write_patterns(img, patterns):
23
@@ -XXX,XX +XXX,XX @@ def io_write_patterns(img, patterns):
24
iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img)
25
26
27
-def try_remove(img):
28
- try:
29
- os.remove(img)
30
- except OSError:
31
- pass
32
-
33
-
34
def transaction_action(action, **kwargs):
35
return {
36
'type': action,
37
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
38
index XXXXXXX..XXXXXXX 100644
39
--- a/tests/qemu-iotests/iotests.py
40
+++ b/tests/qemu-iotests/iotests.py
41
@@ -XXX,XX +XXX,XX @@ class FilePath:
42
return False
43
44
45
+def try_remove(img):
46
+ try:
47
+ os.remove(img)
48
+ except OSError:
49
+ pass
50
+
51
def file_path_remover():
52
for path in reversed(file_path_remover.paths):
53
- try:
54
- os.remove(path)
55
- except OSError:
56
- pass
57
+ try_remove(path)
58
59
60
def file_path(*names, base_dir=test_dir):
61
--
62
2.29.2
63
64
diff view generated by jsdifflib
New patch
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
5
Message-Id: <20210118105720.14824-5-mreitz@redhat.com>
6
---
7
tests/qemu-iotests/129 | 2 ++
8
1 file changed, 2 insertions(+)
1
9
10
diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129
11
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/129
13
+++ b/tests/qemu-iotests/129
14
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
15
result = self.vm.qmp("block_set_io_throttle", conv_keys=False,
16
**params)
17
self.vm.shutdown()
18
+ for img in (self.test_img, self.target_img, self.base_img):
19
+ iotests.try_remove(img)
20
21
def do_test_stop(self, cmd, **args):
22
"""Test 'stop' while block job is running on a throttled drive.
23
--
24
2.29.2
25
26
diff view generated by jsdifflib
New patch
1
@busy is false when the job is paused, which happens all the time
2
because that is how jobs yield (e.g. for mirror at least since commit
3
565ac01f8d3).
1
4
5
Back when 129 was added (2015), perhaps there was no better way of
6
checking whether the job was still actually running. Now we have the
7
@status field (as of 58b295ba52c, i.e. 2018), which can give us exactly
8
that information.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
14
Message-Id: <20210118105720.14824-6-mreitz@redhat.com>
15
---
16
tests/qemu-iotests/129 | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
18
19
diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129
20
index XXXXXXX..XXXXXXX 100755
21
--- a/tests/qemu-iotests/129
22
+++ b/tests/qemu-iotests/129
23
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
24
result = self.vm.qmp("stop")
25
self.assert_qmp(result, 'return', {})
26
result = self.vm.qmp("query-block-jobs")
27
- self.assert_qmp(result, 'return[0]/busy', True)
28
+ self.assert_qmp(result, 'return[0]/status', 'running')
29
self.assert_qmp(result, 'return[0]/ready', False)
30
31
def test_drive_mirror(self):
32
--
33
2.29.2
34
35
diff view generated by jsdifflib
New patch
1
Throttling on the BB has not affected block jobs in a while, so it is
2
possible that one of the jobs in 129 finishes before the VM is stopped.
3
We can fix that by running the job from a throttle node.
1
4
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
9
Message-Id: <20210118105720.14824-7-mreitz@redhat.com>
10
---
11
tests/qemu-iotests/129 | 37 +++++++++++++------------------------
12
1 file changed, 13 insertions(+), 24 deletions(-)
13
14
diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/129
17
+++ b/tests/qemu-iotests/129
18
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
19
iotests.qemu_img('create', '-f', iotests.imgfmt, self.test_img,
20
"-b", self.base_img, '-F', iotests.imgfmt)
21
iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 1M 128M', self.test_img)
22
- self.vm = iotests.VM().add_drive(self.test_img)
23
+ self.vm = iotests.VM()
24
+ self.vm.add_object('throttle-group,id=tg0,x-bps-total=1024')
25
+
26
+ source_drive = 'driver=throttle,' \
27
+ 'throttle-group=tg0,' \
28
+ f'file.driver={iotests.imgfmt},' \
29
+ f'file.file.filename={self.test_img}'
30
+
31
+ self.vm.add_drive(None, source_drive)
32
self.vm.launch()
33
34
def tearDown(self):
35
- params = {"device": "drive0",
36
- "bps": 0,
37
- "bps_rd": 0,
38
- "bps_wr": 0,
39
- "iops": 0,
40
- "iops_rd": 0,
41
- "iops_wr": 0,
42
- }
43
- result = self.vm.qmp("block_set_io_throttle", conv_keys=False,
44
- **params)
45
self.vm.shutdown()
46
for img in (self.test_img, self.target_img, self.base_img):
47
iotests.try_remove(img)
48
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
49
def do_test_stop(self, cmd, **args):
50
"""Test 'stop' while block job is running on a throttled drive.
51
The 'stop' command shouldn't drain the job"""
52
- params = {"device": "drive0",
53
- "bps": 1024,
54
- "bps_rd": 0,
55
- "bps_wr": 0,
56
- "iops": 0,
57
- "iops_rd": 0,
58
- "iops_wr": 0,
59
- }
60
- result = self.vm.qmp("block_set_io_throttle", conv_keys=False,
61
- **params)
62
- self.assert_qmp(result, 'return', {})
63
result = self.vm.qmp(cmd, **args)
64
self.assert_qmp(result, 'return', {})
65
+
66
result = self.vm.qmp("stop")
67
self.assert_qmp(result, 'return', {})
68
result = self.vm.qmp("query-block-jobs")
69
+
70
self.assert_qmp(result, 'return[0]/status', 'running')
71
self.assert_qmp(result, 'return[0]/ready', False)
72
73
def test_drive_mirror(self):
74
self.do_test_stop("drive-mirror", device="drive0",
75
- target=self.target_img,
76
+ target=self.target_img, format=iotests.imgfmt,
77
sync="full")
78
79
def test_drive_backup(self):
80
self.do_test_stop("drive-backup", device="drive0",
81
- target=self.target_img,
82
+ target=self.target_img, format=iotests.imgfmt,
83
sync="full")
84
85
def test_block_commit(self):
86
--
87
2.29.2
88
89
diff view generated by jsdifflib
New patch
1
Before this patch, test_block_commit() performs an active commit, which
2
under the hood is a mirror job. If we want to test various different
3
block jobs, we should perhaps run an actual commit job instead.
1
4
5
Doing so requires adding an overlay above the source node before the
6
commit is done (and then specifying the source node as the top node for
7
the commit job).
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
13
Message-Id: <20210118105720.14824-8-mreitz@redhat.com>
14
---
15
tests/qemu-iotests/129 | 27 +++++++++++++++++++++++++--
16
1 file changed, 25 insertions(+), 2 deletions(-)
17
18
diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/129
21
+++ b/tests/qemu-iotests/129
22
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
23
test_img = os.path.join(iotests.test_dir, 'test.img')
24
target_img = os.path.join(iotests.test_dir, 'target.img')
25
base_img = os.path.join(iotests.test_dir, 'base.img')
26
+ overlay_img = os.path.join(iotests.test_dir, 'overlay.img')
27
28
def setUp(self):
29
iotests.qemu_img('create', '-f', iotests.imgfmt, self.base_img, "1G")
30
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
31
self.vm.add_object('throttle-group,id=tg0,x-bps-total=1024')
32
33
source_drive = 'driver=throttle,' \
34
+ 'node-name=source,' \
35
'throttle-group=tg0,' \
36
f'file.driver={iotests.imgfmt},' \
37
f'file.file.filename={self.test_img}'
38
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
39
40
def tearDown(self):
41
self.vm.shutdown()
42
- for img in (self.test_img, self.target_img, self.base_img):
43
+ for img in (self.test_img, self.target_img, self.base_img,
44
+ self.overlay_img):
45
iotests.try_remove(img)
46
47
def do_test_stop(self, cmd, **args):
48
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
49
sync="full")
50
51
def test_block_commit(self):
52
- self.do_test_stop("block-commit", device="drive0")
53
+ # Add overlay above the source node so that we actually use a
54
+ # commit job instead of a mirror job
55
+
56
+ iotests.qemu_img('create', '-f', iotests.imgfmt, self.overlay_img,
57
+ '1G')
58
+
59
+ result = self.vm.qmp('blockdev-add', **{
60
+ 'node-name': 'overlay',
61
+ 'driver': iotests.imgfmt,
62
+ 'file': {
63
+ 'driver': 'file',
64
+ 'filename': self.overlay_img
65
+ }
66
+ })
67
+ self.assert_qmp(result, 'return', {})
68
+
69
+ result = self.vm.qmp('blockdev-snapshot',
70
+ node='source', overlay='overlay')
71
+ self.assert_qmp(result, 'return', {})
72
+
73
+ self.do_test_stop('block-commit', device='drive0', top_node='source')
74
75
if __name__ == '__main__':
76
iotests.main(supported_fmts=["qcow2"],
77
--
78
2.29.2
79
80
diff view generated by jsdifflib
New patch
1
Issuing 'stop' on the VM drains all nodes. If the mirror job has many
2
large requests in flight, this may lead to significant I/O that looks a
3
bit like 'stop' would make the job try to complete (which is what 129
4
should verify not to happen).
1
5
6
We can limit the I/O in flight by limiting the buffer size, so mirror
7
will make very little progress during the 'stop' drain.
8
9
(We do not need to do anything about commit, which has a buffer size of
10
512 kB by default; or backup, which goes cluster by cluster. Once we
11
have asynchronous requests for backup, that will change, but then we can
12
fine-tune the backup job to only perform a single request on a very
13
small chunk, too.)
14
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
19
Message-Id: <20210118105720.14824-9-mreitz@redhat.com>
20
---
21
tests/qemu-iotests/129 | 2 +-
22
1 file changed, 1 insertion(+), 1 deletion(-)
23
24
diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129
25
index XXXXXXX..XXXXXXX 100755
26
--- a/tests/qemu-iotests/129
27
+++ b/tests/qemu-iotests/129
28
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
29
def test_drive_mirror(self):
30
self.do_test_stop("drive-mirror", device="drive0",
31
target=self.target_img, format=iotests.imgfmt,
32
- sync="full")
33
+ sync="full", buf_size=65536)
34
35
def test_drive_backup(self):
36
self.do_test_stop("drive-backup", device="drive0",
37
--
38
2.29.2
39
40
diff view generated by jsdifflib
New patch
1
And consequentially drop it from 297's skip list.
1
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-Id: <20210118105720.14824-10-mreitz@redhat.com>
7
---
8
tests/qemu-iotests/129 | 4 ++--
9
tests/qemu-iotests/297 | 2 +-
10
2 files changed, 3 insertions(+), 3 deletions(-)
11
12
diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/129
15
+++ b/tests/qemu-iotests/129
16
@@ -XXX,XX +XXX,XX @@
17
18
import os
19
import iotests
20
-import time
21
22
class TestStopWithBlockJob(iotests.QMPTestCase):
23
test_img = os.path.join(iotests.test_dir, 'test.img')
24
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
25
iotests.qemu_img('create', '-f', iotests.imgfmt, self.base_img, "1G")
26
iotests.qemu_img('create', '-f', iotests.imgfmt, self.test_img,
27
"-b", self.base_img, '-F', iotests.imgfmt)
28
- iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 1M 128M', self.test_img)
29
+ iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write -P0x5d 1M 128M',
30
+ self.test_img)
31
self.vm = iotests.VM()
32
self.vm.add_object('throttle-group,id=tg0,x-bps-total=1024')
33
34
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
35
index XXXXXXX..XXXXXXX 100755
36
--- a/tests/qemu-iotests/297
37
+++ b/tests/qemu-iotests/297
38
@@ -XXX,XX +XXX,XX @@ import iotests
39
# TODO: Empty this list!
40
SKIP_FILES = (
41
'030', '040', '041', '044', '045', '055', '056', '057', '065', '093',
42
- '096', '118', '124', '129', '132', '136', '139', '147', '148', '149',
43
+ '096', '118', '124', '132', '136', '139', '147', '148', '149',
44
'151', '152', '155', '163', '165', '169', '194', '196', '199', '202',
45
'203', '205', '206', '207', '208', '210', '211', '212', '213', '216',
46
'218', '219', '222', '224', '228', '234', '235', '236', '237', '238',
47
--
48
2.29.2
49
50
diff view generated by jsdifflib
1
We do not care about the json:{} filenames here, so we can just filter
1
And consequentially drop it from 297's skip list.
2
them out and thus make the test work both with and without external data
3
files.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-id: 20191107163708.833192-21-mreitz@redhat.com
5
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Message-Id: <20210118105720.14824-11-mreitz@redhat.com>
9
---
7
---
10
tests/qemu-iotests/198 | 6 ++++--
8
tests/qemu-iotests/297 | 2 +-
11
tests/qemu-iotests/198.out | 4 ++--
9
tests/qemu-iotests/300 | 18 +++++++++++++++---
12
2 files changed, 6 insertions(+), 4 deletions(-)
10
2 files changed, 16 insertions(+), 4 deletions(-)
13
11
14
diff --git a/tests/qemu-iotests/198 b/tests/qemu-iotests/198
12
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
15
index XXXXXXX..XXXXXXX 100755
13
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/198
14
--- a/tests/qemu-iotests/297
17
+++ b/tests/qemu-iotests/198
15
+++ b/tests/qemu-iotests/297
18
@@ -XXX,XX +XXX,XX @@ echo
16
@@ -XXX,XX +XXX,XX @@ SKIP_FILES = (
19
echo "== checking image base =="
17
'218', '219', '222', '224', '228', '234', '235', '236', '237', '238',
20
$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info --format-specific \
18
'240', '242', '245', '246', '248', '255', '256', '257', '258', '260',
21
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
19
'262', '264', '266', '274', '277', '280', '281', '295', '296', '298',
22
- -e '/lazy refcounts:/ D' -e '/corrupt:/ D'
20
- '299', '300', '302', '303', '304', '307',
23
+ -e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
21
+ '299', '302', '303', '304', '307',
24
+ | _filter_json_filename
22
'nbd-fault-injector.py', 'qcow2.py', 'qcow2_format.py', 'qed.py'
25
23
)
26
echo
24
27
echo "== checking image layer =="
25
diff --git a/tests/qemu-iotests/300 b/tests/qemu-iotests/300
28
$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info --format-specific \
26
index XXXXXXX..XXXXXXX 100755
29
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
27
--- a/tests/qemu-iotests/300
30
- -e '/lazy refcounts:/ D' -e '/corrupt:/ D'
28
+++ b/tests/qemu-iotests/300
31
+ -e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
29
@@ -XXX,XX +XXX,XX @@ import os
32
+ | _filter_json_filename
30
import random
33
31
import re
34
32
from typing import Dict, List, Optional, Union
35
# success, all done
33
+
36
diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out
34
import iotests
37
index XXXXXXX..XXXXXXX 100644
35
+
38
--- a/tests/qemu-iotests/198.out
36
+# Import qemu after iotests.py has amended sys.path
39
+++ b/tests/qemu-iotests/198.out
37
+# pylint: disable=wrong-import-order
40
@@ -XXX,XX +XXX,XX @@ read 16777216/16777216 bytes at offset 0
38
import qemu
41
16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
39
42
40
BlockBitmapMapping = List[Dict[str, Union[str, List[Dict[str, str]]]]]
43
== checking image base ==
41
@@ -XXX,XX +XXX,XX @@ class TestDirtyBitmapMigration(iotests.QMPTestCase):
44
-image: json:{"encrypt.key-secret": "sec0", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.base"}}
42
If @msg is None, check that there has not been any error.
45
+image: json:{ /* filtered */ }
43
"""
46
file format: IMGFMT
44
self.vm_b.shutdown()
47
virtual size: 16 MiB (16777216 bytes)
45
+
48
Format specific information:
46
+ log = self.vm_b.get_log()
49
@@ -XXX,XX +XXX,XX @@ Format specific information:
47
+ assert log is not None # Loaded after shutdown
50
master key iters: 1024
48
+
51
49
if msg is None:
52
== checking image layer ==
50
- self.assertNotIn('qemu-system-', self.vm_b.get_log())
53
-image: json:{"encrypt.key-secret": "sec1", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}}
51
+ self.assertNotIn('qemu-system-', log)
54
+image: json:{ /* filtered */ }
52
else:
55
file format: IMGFMT
53
- self.assertIn(msg, self.vm_b.get_log())
56
virtual size: 16 MiB (16777216 bytes)
54
+ self.assertIn(msg, log)
57
backing file: TEST_DIR/t.IMGFMT.base
55
56
@staticmethod
57
def mapping(node_name: str, node_alias: str,
58
@@ -XXX,XX +XXX,XX @@ class TestBlockBitmapMappingErrors(TestDirtyBitmapMigration):
59
60
# Check for the error in the source's log
61
self.vm_a.shutdown()
62
+
63
+ log = self.vm_a.get_log()
64
+ assert log is not None # Loaded after shutdown
65
+
66
self.assertIn(f"Cannot migrate bitmap '{name}' on node "
67
f"'{self.src_node_name}': Name is longer than 255 bytes",
68
- self.vm_a.get_log())
69
+ log)
70
71
# Expect abnormal shutdown of the destination VM because of
72
# the failed migration
58
--
73
--
59
2.24.1
74
2.29.2
60
75
61
76
diff view generated by jsdifflib
1
When using an external data file, there are no refcounts for data
1
Disposition (action) for any given signal is global for the process.
2
clusters. We thus have to adjust the corruption test in this patch to
2
When two threads run coroutine-sigaltstack's qemu_coroutine_new()
3
not be based around a data cluster allocation, but the L2 table
3
concurrently, they may interfere with each other: One of them may revert
4
allocation (L2 tables are still refcounted with external data files).
4
the SIGUSR2 handler to SIG_DFL, between the other thread (a) setting up
5
coroutine_trampoline() as the handler and (b) raising SIGUSR2. That
6
SIGUSR2 will then terminate the QEMU process abnormally.
5
7
6
Furthermore, we should not print qcow2.py's list of incompatible
8
We have to ensure that only one thread at a time can modify the
7
features because it differs depending on whether there is an external
9
process-global SIGUSR2 handler. To do so, wrap the whole section where
8
data file or not.
10
that is done in a mutex.
9
11
10
With those two changes, the test will work both with and without
12
Alternatively, we could for example have the SIGUSR2 handler always be
11
external data files (once that options works with the iotests at all).
13
coroutine_trampoline(), so there would be no need to invoke sigaction()
14
in qemu_coroutine_new(). Laszlo has posted a patch to do so here:
15
16
https://lists.nongnu.org/archive/html/qemu-devel/2021-01/msg05962.html
17
18
However, given that coroutine-sigaltstack is more of a fallback
19
implementation for platforms that do not support ucontext, that change
20
may be a bit too invasive to be comfortable with it. The mutex proposed
21
here may negatively impact performance, but the change is much simpler.
12
22
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
24
Message-Id: <20210125120305.19520-1-mreitz@redhat.com>
15
Message-id: 20191107163708.833192-20-mreitz@redhat.com
25
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
---
27
---
18
tests/qemu-iotests/137 | 15 +++++++++++----
28
util/coroutine-sigaltstack.c | 9 +++++++++
19
tests/qemu-iotests/137.out | 6 ++----
29
1 file changed, 9 insertions(+)
20
2 files changed, 13 insertions(+), 8 deletions(-)
21
30
22
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
31
diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/137
25
+++ b/tests/qemu-iotests/137
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO \
27
"$TEST_IMG" 2>&1 | _filter_qemu_io
28
29
# The dirty bit must not be set
30
-$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
31
+# (Filter the external data file bit)
32
+if $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features \
33
+ | grep -q '\<0\>'
34
+then
35
+ echo 'ERROR: Dirty bit set'
36
+else
37
+ echo 'OK: Dirty bit not set'
38
+fi
39
40
# Similarly we can test whether corruption detection has been enabled:
41
-# Create L1/L2, overwrite first entry in refcount block, allocate something.
42
+# Create L1, overwrite refcounts, force allocation of L2 by writing
43
+# data.
44
# Disabling the checks should fail, so the corruption must be detected.
45
_make_test_img 64M
46
-$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
47
-poke_file "$TEST_IMG" "$((0x20000))" "\x00\x00"
48
+poke_file "$TEST_IMG" "$((0x20000))" "\x00\x00\x00\x00\x00\x00\x00\x00"
49
$QEMU_IO \
50
-c "reopen -o overlap-check=none,lazy-refcounts=42" \
51
-c "write 64k 64k" \
52
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
53
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
54
--- a/tests/qemu-iotests/137.out
33
--- a/util/coroutine-sigaltstack.c
55
+++ b/tests/qemu-iotests/137.out
34
+++ b/util/coroutine-sigaltstack.c
56
@@ -XXX,XX +XXX,XX @@ qemu-io: Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are
35
@@ -XXX,XX +XXX,XX @@ Coroutine *qemu_coroutine_new(void)
57
wrote 512/512 bytes at offset 0
36
sigset_t sigs;
58
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
37
sigset_t osigs;
59
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
38
sigjmp_buf old_env;
60
-incompatible_features []
39
+ static pthread_mutex_t sigusr2_mutex = PTHREAD_MUTEX_INITIALIZER;
61
+OK: Dirty bit not set
40
62
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
41
/* The way to manipulate stack is with the sigaltstack function. We
63
-wrote 65536/65536 bytes at offset 0
42
* prepare a stack, with it delivering a signal to ourselves and then
64
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
43
@@ -XXX,XX +XXX,XX @@ Coroutine *qemu_coroutine_new(void)
65
qemu-io: Parameter 'lazy-refcounts' expects 'on' or 'off'
44
sa.sa_handler = coroutine_trampoline;
66
-qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed
45
sigfillset(&sa.sa_mask);
67
+qcow2: Marking image as corrupt: Preventing invalid allocation of L2 table at offset 0; further corruption events will be suppressed
46
sa.sa_flags = SA_ONSTACK;
68
write failed: Input/output error
47
+
69
*** done
48
+ /*
49
+ * sigaction() is a process-global operation. We must not run
50
+ * this code in multiple threads at once.
51
+ */
52
+ pthread_mutex_lock(&sigusr2_mutex);
53
if (sigaction(SIGUSR2, &sa, &osa) != 0) {
54
abort();
55
}
56
@@ -XXX,XX +XXX,XX @@ Coroutine *qemu_coroutine_new(void)
57
* Restore the old SIGUSR2 signal handler and mask
58
*/
59
sigaction(SIGUSR2, &osa, NULL);
60
+ pthread_mutex_unlock(&sigusr2_mutex);
61
+
62
pthread_sigmask(SIG_SETMASK, &osigs, NULL);
63
64
/*
70
--
65
--
71
2.24.1
66
2.29.2
72
67
73
68
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
Experiments show, that copy_range is not always making things faster.
4
So, to make experimentation simpler, let's add a parameter. Some more
5
perf parameters will be added soon, so here is a new struct.
6
7
For now, add new backup qmp parameter with x- prefix for the following
8
reasons:
9
10
- We are going to add more performance parameters, some will be
11
related to the whole block-copy process, some only to background
12
copying in backup (ignored for copy-before-write operations).
13
- On the other hand, we are going to use block-copy interface in other
14
block jobs, which will need performance options as well.. And it
15
should be the same structure or at least somehow related.
16
17
So, there are too much unclean things about how the interface and now
18
we need the new options mostly for testing. Let's keep them
19
experimental for a while.
20
21
In do_backup_common() new x-perf parameter handled in a way to
22
make further options addition simpler.
23
24
We add use-copy-range with default=true, and we'll change the default
25
in further patch, after moving backup to use block-copy.
26
27
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
28
Reviewed-by: Max Reitz <mreitz@redhat.com>
29
Message-Id: <20210116214705.822267-2-vsementsov@virtuozzo.com>
30
[mreitz: s/5\.2/6.0/]
31
Signed-off-by: Max Reitz <mreitz@redhat.com>
32
---
33
qapi/block-core.json | 17 ++++++++++++++++-
34
block/backup-top.h | 1 +
35
include/block/block-copy.h | 2 +-
36
include/block/block_int.h | 3 +++
37
block/backup-top.c | 4 +++-
38
block/backup.c | 6 +++++-
39
block/block-copy.c | 4 ++--
40
block/replication.c | 2 ++
41
blockdev.c | 8 ++++++++
42
9 files changed, 41 insertions(+), 6 deletions(-)
43
44
diff --git a/qapi/block-core.json b/qapi/block-core.json
45
index XXXXXXX..XXXXXXX 100644
46
--- a/qapi/block-core.json
47
+++ b/qapi/block-core.json
48
@@ -XXX,XX +XXX,XX @@
49
{ 'struct': 'BlockdevSnapshot',
50
'data': { 'node': 'str', 'overlay': 'str' } }
51
52
+##
53
+# @BackupPerf:
54
+#
55
+# Optional parameters for backup. These parameters don't affect
56
+# functionality, but may significantly affect performance.
57
+#
58
+# @use-copy-range: Use copy offloading. Default true.
59
+#
60
+# Since: 6.0
61
+##
62
+{ 'struct': 'BackupPerf',
63
+ 'data': { '*use-copy-range': 'bool' }}
64
+
65
##
66
# @BackupCommon:
67
#
68
@@ -XXX,XX +XXX,XX @@
69
# above node specified by @drive. If this option is not given,
70
# a node name is autogenerated. (Since: 4.2)
71
#
72
+# @x-perf: Performance options. (Since 6.0)
73
+#
74
# Note: @on-source-error and @on-target-error only affect background
75
# I/O. If an error occurs during a guest write request, the device's
76
# rerror/werror actions will be used.
77
@@ -XXX,XX +XXX,XX @@
78
'*on-source-error': 'BlockdevOnError',
79
'*on-target-error': 'BlockdevOnError',
80
'*auto-finalize': 'bool', '*auto-dismiss': 'bool',
81
- '*filter-node-name': 'str' } }
82
+ '*filter-node-name': 'str', '*x-perf': 'BackupPerf' } }
83
84
##
85
# @DriveBackup:
86
diff --git a/block/backup-top.h b/block/backup-top.h
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/backup-top.h
89
+++ b/block/backup-top.h
90
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
91
BlockDriverState *target,
92
const char *filter_node_name,
93
uint64_t cluster_size,
94
+ BackupPerf *perf,
95
BdrvRequestFlags write_flags,
96
BlockCopyState **bcs,
97
Error **errp);
98
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
99
index XXXXXXX..XXXXXXX 100644
100
--- a/include/block/block-copy.h
101
+++ b/include/block/block-copy.h
102
@@ -XXX,XX +XXX,XX @@ typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
103
typedef struct BlockCopyState BlockCopyState;
104
105
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
106
- int64_t cluster_size,
107
+ int64_t cluster_size, bool use_copy_range,
108
BdrvRequestFlags write_flags,
109
Error **errp);
110
111
diff --git a/include/block/block_int.h b/include/block/block_int.h
112
index XXXXXXX..XXXXXXX 100644
113
--- a/include/block/block_int.h
114
+++ b/include/block/block_int.h
115
@@ -XXX,XX +XXX,XX @@ void mirror_start(const char *job_id, BlockDriverState *bs,
116
* @sync_mode: What parts of the disk image should be copied to the destination.
117
* @sync_bitmap: The dirty bitmap if sync_mode is 'bitmap' or 'incremental'
118
* @bitmap_mode: The bitmap synchronization policy to use.
119
+ * @perf: Performance options. All actual fields assumed to be present,
120
+ * all ".has_*" fields are ignored.
121
* @on_source_error: The action to take upon error reading from the source.
122
* @on_target_error: The action to take upon error writing to the target.
123
* @creation_flags: Flags that control the behavior of the Job lifetime.
124
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
125
BitmapSyncMode bitmap_mode,
126
bool compress,
127
const char *filter_node_name,
128
+ BackupPerf *perf,
129
BlockdevOnError on_source_error,
130
BlockdevOnError on_target_error,
131
int creation_flags,
132
diff --git a/block/backup-top.c b/block/backup-top.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/block/backup-top.c
135
+++ b/block/backup-top.c
136
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
137
BlockDriverState *target,
138
const char *filter_node_name,
139
uint64_t cluster_size,
140
+ BackupPerf *perf,
141
BdrvRequestFlags write_flags,
142
BlockCopyState **bcs,
143
Error **errp)
144
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
145
146
state->cluster_size = cluster_size;
147
state->bcs = block_copy_state_new(top->backing, state->target,
148
- cluster_size, write_flags, &local_err);
149
+ cluster_size, perf->use_copy_range,
150
+ write_flags, &local_err);
151
if (local_err) {
152
error_prepend(&local_err, "Cannot create block-copy-state: ");
153
goto fail;
154
diff --git a/block/backup.c b/block/backup.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/block/backup.c
157
+++ b/block/backup.c
158
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
159
uint64_t len;
160
uint64_t bytes_read;
161
int64_t cluster_size;
162
+ BackupPerf perf;
163
164
BlockCopyState *bcs;
165
} BackupBlockJob;
166
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
167
BitmapSyncMode bitmap_mode,
168
bool compress,
169
const char *filter_node_name,
170
+ BackupPerf *perf,
171
BlockdevOnError on_source_error,
172
BlockdevOnError on_target_error,
173
int creation_flags,
174
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
175
(compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
176
177
backup_top = bdrv_backup_top_append(bs, target, filter_node_name,
178
- cluster_size, write_flags, &bcs, errp);
179
+ cluster_size, perf,
180
+ write_flags, &bcs, errp);
181
if (!backup_top) {
182
goto error;
183
}
184
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
185
job->bcs = bcs;
186
job->cluster_size = cluster_size;
187
job->len = len;
188
+ job->perf = *perf;
189
190
block_copy_set_progress_callback(bcs, backup_progress_bytes_callback, job);
191
block_copy_set_progress_meter(bcs, &job->common.job.progress);
192
diff --git a/block/block-copy.c b/block/block-copy.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/block-copy.c
195
+++ b/block/block-copy.c
196
@@ -XXX,XX +XXX,XX @@ static uint32_t block_copy_max_transfer(BdrvChild *source, BdrvChild *target)
197
}
198
199
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
200
- int64_t cluster_size,
201
+ int64_t cluster_size, bool use_copy_range,
202
BdrvRequestFlags write_flags, Error **errp)
203
{
204
BlockCopyState *s;
205
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
206
* We enable copy-range, but keep small copy_size, until first
207
* successful copy_range (look at block_copy_do_copy).
208
*/
209
- s->use_copy_range = true;
210
+ s->use_copy_range = use_copy_range;
211
s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
212
}
213
214
diff --git a/block/replication.c b/block/replication.c
215
index XXXXXXX..XXXXXXX 100644
216
--- a/block/replication.c
217
+++ b/block/replication.c
218
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
219
int64_t active_length, hidden_length, disk_length;
220
AioContext *aio_context;
221
Error *local_err = NULL;
222
+ BackupPerf perf = { .use_copy_range = true };
223
224
aio_context = bdrv_get_aio_context(bs);
225
aio_context_acquire(aio_context);
226
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
227
s->backup_job = backup_job_create(
228
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
229
0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, NULL,
230
+ &perf,
231
BLOCKDEV_ON_ERROR_REPORT,
232
BLOCKDEV_ON_ERROR_REPORT, JOB_INTERNAL,
233
backup_job_completed, bs, NULL, &local_err);
234
diff --git a/blockdev.c b/blockdev.c
235
index XXXXXXX..XXXXXXX 100644
236
--- a/blockdev.c
237
+++ b/blockdev.c
238
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
239
{
240
BlockJob *job = NULL;
241
BdrvDirtyBitmap *bmap = NULL;
242
+ BackupPerf perf = { .use_copy_range = true };
243
int job_flags = JOB_DEFAULT;
244
245
if (!backup->has_speed) {
246
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
247
backup->compress = false;
248
}
249
250
+ if (backup->x_perf) {
251
+ if (backup->x_perf->has_use_copy_range) {
252
+ perf.use_copy_range = backup->x_perf->use_copy_range;
253
+ }
254
+ }
255
+
256
if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) ||
257
(backup->sync == MIRROR_SYNC_MODE_INCREMENTAL)) {
258
/* done before desugaring 'incremental' to print the right message */
259
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
260
backup->sync, bmap, backup->bitmap_mode,
261
backup->compress,
262
backup->filter_node_name,
263
+ &perf,
264
backup->on_source_error,
265
backup->on_target_error,
266
job_flags, NULL, NULL, txn, errp);
267
--
268
2.29.2
269
270
diff view generated by jsdifflib
1
The only difference is that the json:{} filename of the image looks
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
different. We actually do not care about that filename in this test, we
3
are only interested in (1) that there is a json:{} filename, and (2)
4
whether the backing filename can be constructed.
5
2
6
So just filter out the json:{} data, thus making this test pass both
3
Refactor common path to use BlockCopyCallState pointer as parameter, to
7
with and without data_file.
4
prepare it for use in asynchronous block-copy (at least, we'll need to
5
run block-copy in a coroutine, passing the whole parameters as one
6
pointer).
8
7
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20191107163708.833192-19-mreitz@redhat.com
10
Message-Id: <20210116214705.822267-3-vsementsov@virtuozzo.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
12
---
14
tests/qemu-iotests/110 | 7 +++++--
13
block/block-copy.c | 51 ++++++++++++++++++++++++++++++++++------------
15
tests/qemu-iotests/110.out | 4 ++--
14
1 file changed, 38 insertions(+), 13 deletions(-)
16
2 files changed, 7 insertions(+), 4 deletions(-)
17
15
18
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
16
diff --git a/block/block-copy.c b/block/block-copy.c
19
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/110
18
--- a/block/block-copy.c
21
+++ b/tests/qemu-iotests/110
19
+++ b/block/block-copy.c
22
@@ -XXX,XX +XXX,XX @@ echo
20
@@ -XXX,XX +XXX,XX @@
23
# Across blkdebug without a config file, you cannot reconstruct filenames, so
21
static coroutine_fn int block_copy_task_entry(AioTask *task);
24
# qemu is incapable of knowing the directory of the top image from the filename
22
25
# alone. However, using bdrv_dirname(), it should still work.
23
typedef struct BlockCopyCallState {
26
+# (Filter out the json:{} filename so this test works with external data files)
24
+ /* IN parameters */
27
TEST_IMG="json:{
25
+ BlockCopyState *s;
28
'driver': '$IMGFMT',
26
+ int64_t offset;
29
'file': {
27
+ int64_t bytes;
30
@@ -XXX,XX +XXX,XX @@ TEST_IMG="json:{
28
+
31
}
29
+ /* State */
32
]
30
bool failed;
31
+
32
+ /* OUT parameters */
33
bool error_is_read;
34
} BlockCopyCallState;
35
36
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
37
* Returns 1 if dirty clusters found and successfully copied, 0 if no dirty
38
* clusters found and -errno on failure.
39
*/
40
-static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
41
- int64_t offset, int64_t bytes,
42
- bool *error_is_read)
43
+static int coroutine_fn
44
+block_copy_dirty_clusters(BlockCopyCallState *call_state)
45
{
46
+ BlockCopyState *s = call_state->s;
47
+ int64_t offset = call_state->offset;
48
+ int64_t bytes = call_state->bytes;
49
+
50
int ret = 0;
51
bool found_dirty = false;
52
int64_t end = offset + bytes;
53
AioTaskPool *aio = NULL;
54
- BlockCopyCallState call_state = {false, false};
55
56
/*
57
* block_copy() user is responsible for keeping source and target in same
58
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_dirty_clusters(BlockCopyState *s,
59
BlockCopyTask *task;
60
int64_t status_bytes;
61
62
- task = block_copy_task_create(s, &call_state, offset, bytes);
63
+ task = block_copy_task_create(s, call_state, offset, bytes);
64
if (!task) {
65
/* No more dirty bits in the bitmap */
66
trace_block_copy_skip_range(s, offset, bytes);
67
@@ -XXX,XX +XXX,XX @@ out:
68
69
aio_task_pool_free(aio);
33
}
70
}
34
-}" _img_info | _filter_img_info | grep -v 'backing file format'
71
- if (error_is_read && ret < 0) {
35
+}" _img_info | _filter_img_info | grep -v 'backing file format' \
72
- *error_is_read = call_state.error_is_read;
36
+ | _filter_json_filename
73
- }
37
74
38
echo
75
return ret < 0 ? ret : found_dirty;
39
echo '=== Backing name is always relative to the backed image ==='
76
}
40
@@ -XXX,XX +XXX,XX @@ TEST_IMG="json:{
77
41
}
78
/*
42
]
79
- * block_copy
43
}
80
+ * block_copy_common
44
-}" _img_info | _filter_img_info | grep -v 'backing file format'
81
*
45
+}" _img_info | _filter_img_info | grep -v 'backing file format' \
82
* Copy requested region, accordingly to dirty bitmap.
46
+ | _filter_json_filename
83
* Collaborate with parallel block_copy requests: if they succeed it will help
47
84
@@ -XXX,XX +XXX,XX @@ out:
48
85
* it means that some I/O operation failed in context of _this_ block_copy call,
49
# success, all done
86
* not some parallel operation.
50
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
87
*/
51
index XXXXXXX..XXXXXXX 100644
88
-int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
52
--- a/tests/qemu-iotests/110.out
89
- bool *error_is_read)
53
+++ b/tests/qemu-iotests/110.out
90
+static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
54
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
91
{
55
92
int ret;
56
=== Non-reconstructable filename ===
93
57
94
do {
58
-image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
95
- ret = block_copy_dirty_clusters(s, offset, bytes, error_is_read);
59
+image: json:{ /* filtered */ }
96
+ ret = block_copy_dirty_clusters(call_state);
60
file format: IMGFMT
97
61
virtual size: 64 MiB (67108864 bytes)
98
if (ret == 0) {
62
backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
99
- ret = block_copy_wait_one(s, offset, bytes);
63
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.b
100
+ ret = block_copy_wait_one(call_state->s, call_state->offset,
64
101
+ call_state->bytes);
65
=== Nodes without a common directory ===
102
}
66
103
67
-image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}}
104
/*
68
+image: json:{ /* filtered */ }
105
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
69
file format: IMGFMT
106
return ret;
70
virtual size: 64 MiB (67108864 bytes)
107
}
71
backing file: t.IMGFMT.base (cannot determine actual path)
108
109
+int coroutine_fn block_copy(BlockCopyState *s, int64_t start, int64_t bytes,
110
+ bool *error_is_read)
111
+{
112
+ BlockCopyCallState call_state = {
113
+ .s = s,
114
+ .offset = start,
115
+ .bytes = bytes,
116
+ };
117
+
118
+ int ret = block_copy_common(&call_state);
119
+
120
+ if (error_is_read && ret < 0) {
121
+ *error_is_read = call_state.error_is_read;
122
+ }
123
+
124
+ return ret;
125
+}
126
+
127
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s)
128
{
129
return s->copy_bitmap;
72
--
130
--
73
2.24.1
131
2.29.2
74
132
75
133
diff view generated by jsdifflib
1
From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
QEMU currently supports writing compressed data of the size equal to
3
We'll need async block-copy invocation to use in backup directly.
4
one cluster. This patch allows writing QCOW2 compressed data that
5
exceed one cluster. Now, we split buffered data into separate clusters
6
and write them compressed using the block/aio_task API.
7
4
8
Suggested-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 1575288906-551879-3-git-send-email-andrey.shinkevich@virtuozzo.com
7
Message-Id: <20210116214705.822267-4-vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
9
---
16
block/qcow2.c | 102 +++++++++++++++++++++++++++++++++++++-------------
10
include/block/block-copy.h | 29 ++++++++++++++
17
1 file changed, 75 insertions(+), 27 deletions(-)
11
block/block-copy.c | 81 ++++++++++++++++++++++++++++++++++++--
12
2 files changed, 106 insertions(+), 4 deletions(-)
18
13
19
diff --git a/block/qcow2.c b/block/qcow2.c
14
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
16
--- a/include/block/block-copy.h
22
+++ b/block/qcow2.c
17
+++ b/include/block/block-copy.h
23
@@ -XXX,XX +XXX,XX @@ fail:
18
@@ -XXX,XX +XXX,XX @@
19
#include "qemu/co-shared-resource.h"
20
21
typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
22
+typedef void (*BlockCopyAsyncCallbackFunc)(void *opaque);
23
typedef struct BlockCopyState BlockCopyState;
24
+typedef struct BlockCopyCallState BlockCopyCallState;
25
26
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
27
int64_t cluster_size, bool use_copy_range,
28
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
29
int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
30
bool *error_is_read);
31
32
+/*
33
+ * Run block-copy in a coroutine, create corresponding BlockCopyCallState
34
+ * object and return pointer to it. Never returns NULL.
35
+ *
36
+ * Caller is responsible to call block_copy_call_free() to free
37
+ * BlockCopyCallState object.
38
+ */
39
+BlockCopyCallState *block_copy_async(BlockCopyState *s,
40
+ int64_t offset, int64_t bytes,
41
+ BlockCopyAsyncCallbackFunc cb,
42
+ void *cb_opaque);
43
+
44
+/*
45
+ * Free finished BlockCopyCallState. Trying to free running
46
+ * block-copy will crash.
47
+ */
48
+void block_copy_call_free(BlockCopyCallState *call_state);
49
+
50
+/*
51
+ * Note, that block-copy call is marked finished prior to calling
52
+ * the callback.
53
+ */
54
+bool block_copy_call_finished(BlockCopyCallState *call_state);
55
+bool block_copy_call_succeeded(BlockCopyCallState *call_state);
56
+bool block_copy_call_failed(BlockCopyCallState *call_state);
57
+int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read);
58
+
59
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
60
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
61
62
diff --git a/block/block-copy.c b/block/block-copy.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block/block-copy.c
65
+++ b/block/block-copy.c
66
@@ -XXX,XX +XXX,XX @@
67
static coroutine_fn int block_copy_task_entry(AioTask *task);
68
69
typedef struct BlockCopyCallState {
70
- /* IN parameters */
71
+ /* IN parameters. Initialized in block_copy_async() and never changed. */
72
BlockCopyState *s;
73
int64_t offset;
74
int64_t bytes;
75
+ BlockCopyAsyncCallbackFunc cb;
76
+ void *cb_opaque;
77
+
78
+ /* Coroutine where async block-copy is running */
79
+ Coroutine *co;
80
81
/* State */
82
- bool failed;
83
+ int ret;
84
+ bool finished;
85
86
/* OUT parameters */
87
bool error_is_read;
88
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
89
90
ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
91
&error_is_read);
92
- if (ret < 0 && !t->call_state->failed) {
93
- t->call_state->failed = true;
94
+ if (ret < 0 && !t->call_state->ret) {
95
+ t->call_state->ret = ret;
96
t->call_state->error_is_read = error_is_read;
97
} else {
98
progress_work_done(t->s->progress, t->bytes);
99
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
100
*/
101
} while (ret > 0);
102
103
+ call_state->finished = true;
104
+
105
+ if (call_state->cb) {
106
+ call_state->cb(call_state->cb_opaque);
107
+ }
108
+
24
return ret;
109
return ret;
25
}
110
}
26
111
27
-/* XXX: put compressed sectors first, then all the cluster aligned
112
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s, int64_t start, int64_t bytes,
28
- tables to avoid losing bytes in alignment */
29
static coroutine_fn int
30
-qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
31
+qcow2_co_pwritev_compressed_task(BlockDriverState *bs,
32
uint64_t offset, uint64_t bytes,
33
QEMUIOVector *qiov, size_t qiov_offset)
34
{
35
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
36
uint8_t *buf, *out_buf;
37
uint64_t cluster_offset;
38
39
- if (has_data_file(bs)) {
40
- return -ENOTSUP;
41
- }
42
-
43
- if (bytes == 0) {
44
- /* align end of file to a sector boundary to ease reading with
45
- sector based I/Os */
46
- int64_t len = bdrv_getlength(bs->file->bs);
47
- if (len < 0) {
48
- return len;
49
- }
50
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
51
- }
52
-
53
- if (offset_into_cluster(s, offset)) {
54
- return -EINVAL;
55
- }
56
+ assert(bytes == s->cluster_size || (bytes < s->cluster_size &&
57
+ (offset + bytes == bs->total_sectors << BDRV_SECTOR_BITS)));
58
59
buf = qemu_blockalign(bs, s->cluster_size);
60
- if (bytes != s->cluster_size) {
61
- if (bytes > s->cluster_size ||
62
- offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
63
- {
64
- qemu_vfree(buf);
65
- return -EINVAL;
66
- }
67
+ if (bytes < s->cluster_size) {
68
/* Zero-pad last write if image size is not cluster aligned */
69
memset(buf + bytes, 0, s->cluster_size - bytes);
70
}
71
@@ -XXX,XX +XXX,XX @@ fail:
72
return ret;
113
return ret;
73
}
114
}
74
115
75
+static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
116
+static void coroutine_fn block_copy_async_co_entry(void *opaque)
76
+{
117
+{
77
+ Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
118
+ block_copy_common(opaque);
78
+
79
+ assert(!t->cluster_type && !t->l2meta);
80
+
81
+ return qcow2_co_pwritev_compressed_task(t->bs, t->offset, t->bytes, t->qiov,
82
+ t->qiov_offset);
83
+}
119
+}
84
+
120
+
85
+/*
121
+BlockCopyCallState *block_copy_async(BlockCopyState *s,
86
+ * XXX: put compressed sectors first, then all the cluster aligned
122
+ int64_t offset, int64_t bytes,
87
+ * tables to avoid losing bytes in alignment
123
+ BlockCopyAsyncCallbackFunc cb,
88
+ */
124
+ void *cb_opaque)
89
+static coroutine_fn int
90
+qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
91
+ uint64_t offset, uint64_t bytes,
92
+ QEMUIOVector *qiov, size_t qiov_offset)
93
+{
125
+{
94
+ BDRVQcow2State *s = bs->opaque;
126
+ BlockCopyCallState *call_state = g_new(BlockCopyCallState, 1);
95
+ AioTaskPool *aio = NULL;
96
+ int ret = 0;
97
+
127
+
98
+ if (has_data_file(bs)) {
128
+ *call_state = (BlockCopyCallState) {
99
+ return -ENOTSUP;
129
+ .s = s,
130
+ .offset = offset,
131
+ .bytes = bytes,
132
+ .cb = cb,
133
+ .cb_opaque = cb_opaque,
134
+
135
+ .co = qemu_coroutine_create(block_copy_async_co_entry, call_state),
136
+ };
137
+
138
+ qemu_coroutine_enter(call_state->co);
139
+
140
+ return call_state;
141
+}
142
+
143
+void block_copy_call_free(BlockCopyCallState *call_state)
144
+{
145
+ if (!call_state) {
146
+ return;
100
+ }
147
+ }
101
+
148
+
102
+ if (bytes == 0) {
149
+ assert(call_state->finished);
103
+ /*
150
+ g_free(call_state);
104
+ * align end of file to a sector boundary to ease reading with
105
+ * sector based I/Os
106
+ */
107
+ int64_t len = bdrv_getlength(bs->file->bs);
108
+ if (len < 0) {
109
+ return len;
110
+ }
111
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
112
+ }
113
+
114
+ if (offset_into_cluster(s, offset)) {
115
+ return -EINVAL;
116
+ }
117
+
118
+ while (bytes && aio_task_pool_status(aio) == 0) {
119
+ uint64_t chunk_size = MIN(bytes, s->cluster_size);
120
+
121
+ if (!aio && chunk_size != bytes) {
122
+ aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
123
+ }
124
+
125
+ ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_compressed_task_entry,
126
+ 0, 0, offset, chunk_size, qiov, qiov_offset, NULL);
127
+ if (ret < 0) {
128
+ break;
129
+ }
130
+ qiov_offset += chunk_size;
131
+ offset += chunk_size;
132
+ bytes -= chunk_size;
133
+ }
134
+
135
+ if (aio) {
136
+ aio_task_pool_wait_all(aio);
137
+ if (ret == 0) {
138
+ ret = aio_task_pool_status(aio);
139
+ }
140
+ g_free(aio);
141
+ }
142
+
143
+ return ret;
144
+}
151
+}
145
+
152
+
146
static int coroutine_fn
153
+bool block_copy_call_finished(BlockCopyCallState *call_state)
147
qcow2_co_preadv_compressed(BlockDriverState *bs,
154
+{
148
uint64_t file_cluster_offset,
155
+ return call_state->finished;
156
+}
157
+
158
+bool block_copy_call_succeeded(BlockCopyCallState *call_state)
159
+{
160
+ return call_state->finished && call_state->ret == 0;
161
+}
162
+
163
+bool block_copy_call_failed(BlockCopyCallState *call_state)
164
+{
165
+ return call_state->finished && call_state->ret < 0;
166
+}
167
+
168
+int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read)
169
+{
170
+ assert(call_state->finished);
171
+ if (error_is_read) {
172
+ *error_is_read = call_state->error_is_read;
173
+ }
174
+ return call_state->ret;
175
+}
176
+
177
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s)
178
{
179
return s->copy_bitmap;
149
--
180
--
150
2.24.1
181
2.29.2
151
182
152
183
diff view generated by jsdifflib
1
Use _make_test_img whenever possible. This way, we will not ignore
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
user-specified image options.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
They will be used for backup.
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
6
Message-id: 20191107163708.833192-15-mreitz@redhat.com
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20210116214705.822267-5-vsementsov@virtuozzo.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
---
9
tests/qemu-iotests/094 | 2 +-
10
include/block/block-copy.h | 6 ++++++
10
tests/qemu-iotests/111 | 3 +--
11
block/block-copy.c | 11 +++++++++--
11
tests/qemu-iotests/123 | 2 +-
12
2 files changed, 15 insertions(+), 2 deletions(-)
12
tests/qemu-iotests/153 | 2 +-
13
tests/qemu-iotests/200 | 4 ++--
14
5 files changed, 6 insertions(+), 7 deletions(-)
15
13
16
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
14
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
17
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/094
16
--- a/include/block/block-copy.h
19
+++ b/tests/qemu-iotests/094
17
+++ b/include/block/block-copy.h
20
@@ -XXX,XX +XXX,XX @@ _supported_proto nbd
18
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
21
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
19
*
22
20
* Caller is responsible to call block_copy_call_free() to free
23
_make_test_img 64M
21
* BlockCopyCallState object.
24
-$QEMU_IMG create -f $IMGFMT "$TEST_DIR/source.$IMGFMT" 64M | _filter_img_create
22
+ *
25
+TEST_IMG_FILE="$TEST_DIR/source.$IMGFMT" IMGPROTO=file _make_test_img 64M
23
+ * @max_workers means maximum of parallel coroutines to execute sub-requests,
26
24
+ * must be > 0.
27
_launch_qemu -drive if=none,id=src,file="$TEST_DIR/source.$IMGFMT",format=raw \
25
+ *
28
-nodefaults
26
+ * @max_chunk means maximum length for one IO operation. Zero means unlimited.
29
diff --git a/tests/qemu-iotests/111 b/tests/qemu-iotests/111
27
*/
30
index XXXXXXX..XXXXXXX 100755
28
BlockCopyCallState *block_copy_async(BlockCopyState *s,
31
--- a/tests/qemu-iotests/111
29
int64_t offset, int64_t bytes,
32
+++ b/tests/qemu-iotests/111
30
+ int max_workers, int64_t max_chunk,
33
@@ -XXX,XX +XXX,XX @@ _supported_fmt qed qcow qcow2 vmdk
31
BlockCopyAsyncCallbackFunc cb,
34
_supported_proto file
32
void *cb_opaque);
35
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
33
36
34
diff --git a/block/block-copy.c b/block/block-copy.c
37
-$QEMU_IMG create -f $IMGFMT -b "$TEST_IMG.inexistent" "$TEST_IMG" 2>&1 \
35
index XXXXXXX..XXXXXXX 100644
38
- | _filter_testdir | _filter_imgfmt
36
--- a/block/block-copy.c
39
+_make_test_img -b "$TEST_IMG.inexistent"
37
+++ b/block/block-copy.c
40
38
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState {
41
# success, all done
39
BlockCopyState *s;
42
echo '*** done'
40
int64_t offset;
43
diff --git a/tests/qemu-iotests/123 b/tests/qemu-iotests/123
41
int64_t bytes;
44
index XXXXXXX..XXXXXXX 100755
42
+ int max_workers;
45
--- a/tests/qemu-iotests/123
43
+ int64_t max_chunk;
46
+++ b/tests/qemu-iotests/123
44
BlockCopyAsyncCallbackFunc cb;
47
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
45
void *cb_opaque;
48
SRC_IMG="$TEST_DIR/source.$IMGFMT"
46
49
47
@@ -XXX,XX +XXX,XX @@ static BlockCopyTask *block_copy_task_create(BlockCopyState *s,
50
_make_test_img 1M
48
int64_t offset, int64_t bytes)
51
-$QEMU_IMG create -f $IMGFMT "$SRC_IMG" 1M | _filter_img_create
49
{
52
+TEST_IMG_FILE=$SRC_IMG IMGPROTO=file _make_test_img 1M
50
BlockCopyTask *task;
53
51
+ int64_t max_chunk = MIN_NON_ZERO(s->copy_size, call_state->max_chunk);
54
$QEMU_IO -c 'write -P 42 0 1M' "$SRC_IMG" | _filter_qemu_io
52
55
53
if (!bdrv_dirty_bitmap_next_dirty_area(s->copy_bitmap,
56
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
54
offset, offset + bytes,
57
index XXXXXXX..XXXXXXX 100755
55
- s->copy_size, &offset, &bytes))
58
--- a/tests/qemu-iotests/153
56
+ max_chunk, &offset, &bytes))
59
+++ b/tests/qemu-iotests/153
57
{
60
@@ -XXX,XX +XXX,XX @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do
58
return NULL;
61
59
}
62
echo
60
@@ -XXX,XX +XXX,XX @@ block_copy_dirty_clusters(BlockCopyCallState *call_state)
63
echo "== Creating test image =="
61
bytes = end - offset;
64
- $QEMU_IMG create -f $IMGFMT "${TEST_IMG}" -b ${TEST_IMG}.base | _filter_img_create
62
65
+ _make_test_img -b "${TEST_IMG}.base"
63
if (!aio && bytes) {
66
64
- aio = aio_task_pool_new(BLOCK_COPY_MAX_WORKERS);
67
echo
65
+ aio = aio_task_pool_new(call_state->max_workers);
68
echo "== Launching QEMU, opts: '$opts1' =="
66
}
69
diff --git a/tests/qemu-iotests/200 b/tests/qemu-iotests/200
67
70
index XXXXXXX..XXXXXXX 100755
68
ret = block_copy_task_run(aio, task);
71
--- a/tests/qemu-iotests/200
69
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s, int64_t start, int64_t bytes,
72
+++ b/tests/qemu-iotests/200
70
.s = s,
73
@@ -XXX,XX +XXX,XX @@ _supported_proto file
71
.offset = start,
74
BACKING_IMG="${TEST_DIR}/backing.img"
72
.bytes = bytes,
75
TEST_IMG="${TEST_DIR}/test.img"
73
+ .max_workers = BLOCK_COPY_MAX_WORKERS,
76
74
};
77
-${QEMU_IMG} create -f $IMGFMT "${BACKING_IMG}" 512M | _filter_img_create
75
78
-${QEMU_IMG} create -f $IMGFMT -F $IMGFMT "${TEST_IMG}" -b "${BACKING_IMG}" 512M | _filter_img_create
76
int ret = block_copy_common(&call_state);
79
+TEST_IMG="$BACKING_IMG" _make_test_img 512M
77
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn block_copy_async_co_entry(void *opaque)
80
+_make_test_img -F $IMGFMT -b "$BACKING_IMG" 512M
78
81
79
BlockCopyCallState *block_copy_async(BlockCopyState *s,
82
${QEMU_IO} -c "write -P 0xa5 512 300M" "${BACKING_IMG}" | _filter_qemu_io
80
int64_t offset, int64_t bytes,
81
+ int max_workers, int64_t max_chunk,
82
BlockCopyAsyncCallbackFunc cb,
83
void *cb_opaque)
84
{
85
@@ -XXX,XX +XXX,XX @@ BlockCopyCallState *block_copy_async(BlockCopyState *s,
86
.s = s,
87
.offset = offset,
88
.bytes = bytes,
89
+ .max_workers = max_workers,
90
+ .max_chunk = max_chunk,
91
.cb = cb,
92
.cb_opaque = cb_opaque,
83
93
84
--
94
--
85
2.24.1
95
2.29.2
86
96
87
97
diff view generated by jsdifflib
1
This will allow us to add more options than just -b.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
It simplifies debugging.
4
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
5
Message-id: 20191107163708.833192-9-mreitz@redhat.com
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20210116214705.822267-6-vsementsov@virtuozzo.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
9
---
8
tests/qemu-iotests/common.rc | 28 ++++++++++++++++++++--------
10
block/block-copy.c | 11 ++++++++++-
9
1 file changed, 20 insertions(+), 8 deletions(-)
11
1 file changed, 10 insertions(+), 1 deletion(-)
10
12
11
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
13
diff --git a/block/block-copy.c b/block/block-copy.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/common.rc
15
--- a/block/block-copy.c
14
+++ b/tests/qemu-iotests/common.rc
16
+++ b/block/block-copy.c
15
@@ -XXX,XX +XXX,XX @@ _make_test_img()
17
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState {
16
# extra qemu-img options can be added by tests
18
/* Coroutine where async block-copy is running */
17
# at least one argument (the image size) needs to be added
19
Coroutine *co;
18
local extra_img_options=""
20
19
- local image_size=$*
21
+ /* To reference all call states from BlockCopyState */
20
local optstr=""
22
+ QLIST_ENTRY(BlockCopyCallState) list;
21
local img_name=""
22
local use_backing=0
23
local backing_file=""
24
local object_options=""
25
+ local misc_params=()
26
27
if [ -n "$TEST_IMG_FILE" ]; then
28
img_name=$TEST_IMG_FILE
29
@@ -XXX,XX +XXX,XX @@ _make_test_img()
30
optstr=$(_optstr_add "$optstr" "key-secret=keysec0")
31
fi
32
33
- if [ "$1" = "-b" ]; then
34
- use_backing=1
35
- backing_file=$2
36
- image_size=$3
37
- fi
38
+ for param; do
39
+ if [ "$use_backing" = "1" -a -z "$backing_file" ]; then
40
+ backing_file=$param
41
+ continue
42
+ fi
43
+
23
+
44
+ case "$param" in
24
/* State */
45
+ -b)
25
int ret;
46
+ use_backing=1
26
bool finished;
47
+ ;;
27
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
28
bool use_copy_range;
29
int64_t copy_size;
30
uint64_t len;
31
- QLIST_HEAD(, BlockCopyTask) tasks;
32
+ QLIST_HEAD(, BlockCopyTask) tasks; /* All tasks from all block-copy calls */
33
+ QLIST_HEAD(, BlockCopyCallState) calls;
34
35
BdrvRequestFlags write_flags;
36
37
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
38
}
39
40
QLIST_INIT(&s->tasks);
41
+ QLIST_INIT(&s->calls);
42
43
return s;
44
}
45
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
46
{
47
int ret;
48
49
+ QLIST_INSERT_HEAD(&call_state->s->calls, call_state, list);
48
+
50
+
49
+ *)
51
do {
50
+ misc_params=("${misc_params[@]}" "$param")
52
ret = block_copy_dirty_clusters(call_state);
51
+ ;;
53
52
+ esac
54
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
53
+ done
55
call_state->cb(call_state->cb_opaque);
56
}
57
58
+ QLIST_REMOVE(call_state, list);
54
+
59
+
55
if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then
60
return ret;
56
optstr=$(_optstr_add "$optstr" "cluster_size=$CLUSTER_SIZE")
61
}
57
fi
58
@@ -XXX,XX +XXX,XX @@ _make_test_img()
59
# XXX(hch): have global image options?
60
(
61
if [ $use_backing = 1 ]; then
62
- $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1
63
+ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" "${misc_params[@]}" 2>&1
64
else
65
- $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
66
+ $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" "${misc_params[@]}" 2>&1
67
fi
68
) | _filter_img_create
69
62
70
--
63
--
71
2.24.1
64
2.29.2
72
65
73
66
diff view generated by jsdifflib
1
The problem with allowing the data_file option is that you want to use a
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
different data file per image used in the test. Therefore, we need to
3
allow patterns like -o data_file='$TEST_IMG.data_file'.
4
2
5
Then, we need to filter it out from qemu-img map, qemu-img create, and
3
We are going to directly use one async block-copy operation for backup
6
remove the data file in _rm_test_img.
4
job, so we need rate limiter.
7
5
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
We want to maintain current backup behavior: only background copying is
9
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
7
limited and copy-before-write operations only participate in limit
10
Message-id: 20191107163708.833192-23-mreitz@redhat.com
8
calculation. Therefore we need one rate limiter for block-copy state
9
and boolean flag for block-copy call state for actual limitation.
10
11
Note, that we can't just calculate each chunk in limiter after
12
successful copying: it will not save us from starting a lot of async
13
sub-requests which will exceed limit too much. Instead let's use the
14
following scheme on sub-request creation:
15
1. If at the moment limit is not exceeded, create the request and
16
account it immediately.
17
2. If at the moment limit is already exceeded, drop create sub-request
18
and handle limit instead (by sleep).
19
With this approach we'll never exceed the limit more than by one
20
sub-request (which pretty much matches current backup behavior).
21
22
Note also, that if there is in-flight block-copy async call,
23
block_copy_kick() should be used after set-speed to apply new setup
24
faster. For that block_copy_kick() published in this patch.
25
26
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
27
Reviewed-by: Max Reitz <mreitz@redhat.com>
28
Message-Id: <20210116214705.822267-7-vsementsov@virtuozzo.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
29
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
30
---
13
tests/qemu-iotests/common.filter | 23 +++++++++++++++++++++--
31
include/block/block-copy.h | 5 ++++-
14
tests/qemu-iotests/common.rc | 22 +++++++++++++++++++++-
32
block/backup-top.c | 2 +-
15
2 files changed, 42 insertions(+), 3 deletions(-)
33
block/backup.c | 2 +-
34
block/block-copy.c | 46 +++++++++++++++++++++++++++++++++++++-
35
4 files changed, 51 insertions(+), 4 deletions(-)
16
36
17
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
37
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
18
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/common.filter
39
--- a/include/block/block-copy.h
20
+++ b/tests/qemu-iotests/common.filter
40
+++ b/include/block/block-copy.h
21
@@ -XXX,XX +XXX,XX @@ _filter_actual_image_size()
41
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
22
# replace driver-specific options in the "Formatting..." line
42
int64_t offset, int64_t *count);
23
_filter_img_create()
43
24
{
44
int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
25
- $SED -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
45
- bool *error_is_read);
26
+ data_file_filter=()
46
+ bool ignore_ratelimit, bool *error_is_read);
27
+ if data_file=$(_get_data_file "$TEST_IMG"); then
47
28
+ data_file_filter=(-e "s# data_file=$data_file##")
48
/*
29
+ fi
49
* Run block-copy in a coroutine, create corresponding BlockCopyCallState
50
@@ -XXX,XX +XXX,XX @@ bool block_copy_call_succeeded(BlockCopyCallState *call_state);
51
bool block_copy_call_failed(BlockCopyCallState *call_state);
52
int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read);
53
54
+void block_copy_set_speed(BlockCopyState *s, uint64_t speed);
55
+void block_copy_kick(BlockCopyCallState *call_state);
30
+
56
+
31
+ $SED "${data_file_filter[@]}" \
57
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
32
+ -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
58
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
33
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
59
34
-e "s#$TEST_DIR#TEST_DIR#g" \
60
diff --git a/block/backup-top.c b/block/backup-top.c
35
-e "s#$SOCK_DIR#SOCK_DIR#g" \
61
index XXXXXXX..XXXXXXX 100644
36
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
62
--- a/block/backup-top.c
37
# human and json output
63
+++ b/block/backup-top.c
38
_filter_qemu_img_map()
64
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
39
{
65
off = QEMU_ALIGN_DOWN(offset, s->cluster_size);
40
+ # Assuming the data_file value in $IMGOPTS contains a '$TEST_IMG',
66
end = QEMU_ALIGN_UP(offset + bytes, s->cluster_size);
41
+ # create a filter that replaces the data file name by $TEST_IMG.
67
42
+ # Example:
68
- return block_copy(s->bcs, off, end - off, NULL);
43
+ # In $IMGOPTS: 'data_file=$TEST_IMG.data_file'
69
+ return block_copy(s->bcs, off, end - off, true, NULL);
44
+ # Then data_file_pattern == '\(.*\).data_file'
70
}
45
+ # And data_file_filter == -e 's#\(.*\).data_file#\1#
71
46
+ data_file_filter=()
72
static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
47
+ if data_file_pattern=$(_get_data_file '\\(.*\\)'); then
73
diff --git a/block/backup.c b/block/backup.c
48
+ data_file_filter=(-e "s#$data_file_pattern#\\1#")
74
index XXXXXXX..XXXXXXX 100644
49
+ fi
75
--- a/block/backup.c
76
+++ b/block/backup.c
77
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
78
79
trace_backup_do_cow_enter(job, start, offset, bytes);
80
81
- ret = block_copy(job->bcs, start, end - start, error_is_read);
82
+ ret = block_copy(job->bcs, start, end - start, true, error_is_read);
83
84
trace_backup_do_cow_return(job, offset, bytes, ret);
85
86
diff --git a/block/block-copy.c b/block/block-copy.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/block-copy.c
89
+++ b/block/block-copy.c
90
@@ -XXX,XX +XXX,XX @@
91
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
92
#define BLOCK_COPY_MAX_MEM (128 * MiB)
93
#define BLOCK_COPY_MAX_WORKERS 64
94
+#define BLOCK_COPY_SLICE_TIME 100000000ULL /* ns */
95
96
static coroutine_fn int block_copy_task_entry(AioTask *task);
97
98
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState {
99
int64_t bytes;
100
int max_workers;
101
int64_t max_chunk;
102
+ bool ignore_ratelimit;
103
BlockCopyAsyncCallbackFunc cb;
104
void *cb_opaque;
105
106
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState {
107
/* State */
108
int ret;
109
bool finished;
110
+ QemuCoSleepState *sleep_state;
111
112
/* OUT parameters */
113
bool error_is_read;
114
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
115
void *progress_opaque;
116
117
SharedResource *mem;
50
+
118
+
51
$SED -e 's/\([0-9a-fx]* *[0-9a-fx]* *\)[0-9a-fx]* */\1/g' \
119
+ uint64_t speed;
52
-e 's/"offset": [0-9]\+/"offset": OFFSET/g' \
120
+ RateLimit rate_limit;
53
- -e 's/Mapped to *//' | _filter_testdir | _filter_imgfmt
121
} BlockCopyState;
54
+ -e 's/Mapped to *//' \
122
55
+ "${data_file_filter[@]}" \
123
static BlockCopyTask *find_conflicting_task(BlockCopyState *s,
56
+ | _filter_testdir | _filter_imgfmt
124
@@ -XXX,XX +XXX,XX @@ block_copy_dirty_clusters(BlockCopyCallState *call_state)
125
}
126
task->zeroes = ret & BDRV_BLOCK_ZERO;
127
128
+ if (s->speed) {
129
+ if (!call_state->ignore_ratelimit) {
130
+ uint64_t ns = ratelimit_calculate_delay(&s->rate_limit, 0);
131
+ if (ns > 0) {
132
+ block_copy_task_end(task, -EAGAIN);
133
+ g_free(task);
134
+ qemu_co_sleep_ns_wakeable(QEMU_CLOCK_REALTIME, ns,
135
+ &call_state->sleep_state);
136
+ continue;
137
+ }
138
+ }
139
+
140
+ ratelimit_calculate_delay(&s->rate_limit, task->bytes);
141
+ }
142
+
143
trace_block_copy_process(s, task->offset);
144
145
co_get_from_shres(s->mem, task->bytes);
146
@@ -XXX,XX +XXX,XX @@ out:
147
return ret < 0 ? ret : found_dirty;
57
}
148
}
58
149
59
_filter_nbd()
150
+void block_copy_kick(BlockCopyCallState *call_state)
60
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
61
index XXXXXXX..XXXXXXX 100644
62
--- a/tests/qemu-iotests/common.rc
63
+++ b/tests/qemu-iotests/common.rc
64
@@ -XXX,XX +XXX,XX @@ _stop_nbd_server()
65
fi
66
}
67
68
+# Gets the data_file value from IMGOPTS and replaces the '$TEST_IMG'
69
+# pattern by '$1'
70
+# Caution: The replacement is done with sed, so $1 must be escaped
71
+# properly. (The delimiter is '#'.)
72
+_get_data_file()
73
+{
151
+{
74
+ if ! echo "$IMGOPTS" | grep -q 'data_file='; then
152
+ if (call_state->sleep_state) {
75
+ return 1
153
+ qemu_co_sleep_wake(call_state->sleep_state);
76
+ fi
154
+ }
77
+
78
+ echo "$IMGOPTS" | sed -e 's/.*data_file=\([^,]*\).*/\1/' \
79
+ | sed -e "s#\\\$TEST_IMG#$1#"
80
+}
155
+}
81
+
156
+
82
_make_test_img()
157
/*
158
* block_copy_common
159
*
160
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
161
}
162
163
int coroutine_fn block_copy(BlockCopyState *s, int64_t start, int64_t bytes,
164
- bool *error_is_read)
165
+ bool ignore_ratelimit, bool *error_is_read)
83
{
166
{
84
# extra qemu-img options can be added by tests
167
BlockCopyCallState call_state = {
85
@@ -XXX,XX +XXX,XX @@ _make_test_img()
168
.s = s,
86
fi
169
.offset = start,
87
170
.bytes = bytes,
88
if [ -n "$IMGOPTS" ]; then
171
+ .ignore_ratelimit = ignore_ratelimit,
89
- optstr=$(_optstr_add "$optstr" "$IMGOPTS")
172
.max_workers = BLOCK_COPY_MAX_WORKERS,
90
+ imgopts_expanded=$(echo "$IMGOPTS" | sed -e "s#\\\$TEST_IMG#$img_name#")
173
};
91
+ optstr=$(_optstr_add "$optstr" "$imgopts_expanded")
174
92
fi
175
@@ -XXX,XX +XXX,XX @@ void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip)
93
if [ -n "$IMGKEYSECRET" ]; then
176
{
94
object_options="--object secret,id=keysec0,data=$IMGKEYSECRET"
177
s->skip_unallocated = skip;
95
@@ -XXX,XX +XXX,XX @@ _rm_test_img()
96
# Remove all the extents for vmdk
97
"$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
98
| xargs -I {} rm -f "{}"
99
+ elif [ "$IMGFMT" = "qcow2" ]; then
100
+ # Remove external data file
101
+ if data_file=$(_get_data_file "$img"); then
102
+ rm -f "$data_file"
103
+ fi
104
fi
105
rm -f "$img"
106
}
178
}
179
+
180
+void block_copy_set_speed(BlockCopyState *s, uint64_t speed)
181
+{
182
+ s->speed = speed;
183
+ if (speed > 0) {
184
+ ratelimit_set_speed(&s->rate_limit, speed, BLOCK_COPY_SLICE_TIME);
185
+ }
186
+
187
+ /*
188
+ * Note: it's good to kick all call states from here, but it should be done
189
+ * only from a coroutine, to not crash if s->calls list changed while
190
+ * entering one call. So for now, the only user of this function kicks its
191
+ * only one call_state by hand.
192
+ */
193
+}
107
--
194
--
108
2.24.1
195
2.29.2
109
196
110
197
diff view generated by jsdifflib
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
2
3
Message-id: 20191107163708.833192-5-mreitz@redhat.com
3
Add function to cancel running async block-copy call. It will be used
4
in backup.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210116214705.822267-8-vsementsov@virtuozzo.com>
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
10
---
6
tests/qemu-iotests/common.filter | 24 ++++++++++++++++++++++++
11
include/block/block-copy.h | 13 +++++++++++++
7
1 file changed, 24 insertions(+)
12
block/block-copy.c | 24 +++++++++++++++++++-----
13
2 files changed, 32 insertions(+), 5 deletions(-)
8
14
9
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
15
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
10
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
11
--- a/tests/qemu-iotests/common.filter
17
--- a/include/block/block-copy.h
12
+++ b/tests/qemu-iotests/common.filter
18
+++ b/include/block/block-copy.h
13
@@ -XXX,XX +XXX,XX @@ _filter_qmp_empty_return()
19
@@ -XXX,XX +XXX,XX @@ void block_copy_call_free(BlockCopyCallState *call_state);
14
grep -v '{"return": {}}'
20
bool block_copy_call_finished(BlockCopyCallState *call_state);
21
bool block_copy_call_succeeded(BlockCopyCallState *call_state);
22
bool block_copy_call_failed(BlockCopyCallState *call_state);
23
+bool block_copy_call_cancelled(BlockCopyCallState *call_state);
24
int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read);
25
26
void block_copy_set_speed(BlockCopyState *s, uint64_t speed);
27
void block_copy_kick(BlockCopyCallState *call_state);
28
29
+/*
30
+ * Cancel running block-copy call.
31
+ *
32
+ * Cancel leaves block-copy state valid: dirty bits are correct and you may use
33
+ * cancel + <run block_copy with same parameters> to emulate pause/resume.
34
+ *
35
+ * Note also, that the cancel is async: it only marks block-copy call to be
36
+ * cancelled. So, the call may be cancelled (block_copy_call_cancelled() reports
37
+ * true) but not yet finished (block_copy_call_finished() reports false).
38
+ */
39
+void block_copy_call_cancel(BlockCopyCallState *call_state);
40
+
41
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
42
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
43
44
diff --git a/block/block-copy.c b/block/block-copy.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/block-copy.c
47
+++ b/block/block-copy.c
48
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState {
49
int ret;
50
bool finished;
51
QemuCoSleepState *sleep_state;
52
+ bool cancelled;
53
54
/* OUT parameters */
55
bool error_is_read;
56
@@ -XXX,XX +XXX,XX @@ block_copy_dirty_clusters(BlockCopyCallState *call_state)
57
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
58
assert(QEMU_IS_ALIGNED(bytes, s->cluster_size));
59
60
- while (bytes && aio_task_pool_status(aio) == 0) {
61
+ while (bytes && aio_task_pool_status(aio) == 0 && !call_state->cancelled) {
62
BlockCopyTask *task;
63
int64_t status_bytes;
64
65
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
66
do {
67
ret = block_copy_dirty_clusters(call_state);
68
69
- if (ret == 0) {
70
+ if (ret == 0 && !call_state->cancelled) {
71
ret = block_copy_wait_one(call_state->s, call_state->offset,
72
call_state->bytes);
73
}
74
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
75
* 2. We have waited for some intersecting block-copy request
76
* It may have failed and produced new dirty bits.
77
*/
78
- } while (ret > 0);
79
+ } while (ret > 0 && !call_state->cancelled);
80
81
call_state->finished = true;
82
83
@@ -XXX,XX +XXX,XX @@ bool block_copy_call_finished(BlockCopyCallState *call_state)
84
85
bool block_copy_call_succeeded(BlockCopyCallState *call_state)
86
{
87
- return call_state->finished && call_state->ret == 0;
88
+ return call_state->finished && !call_state->cancelled &&
89
+ call_state->ret == 0;
15
}
90
}
16
91
17
+_filter_json_filename()
92
bool block_copy_call_failed(BlockCopyCallState *call_state)
18
+{
93
{
19
+ $PYTHON -c 'import sys
94
- return call_state->finished && call_state->ret < 0;
20
+result, *fnames = sys.stdin.read().split("json:{")
95
+ return call_state->finished && !call_state->cancelled &&
21
+depth = 0
96
+ call_state->ret < 0;
22
+for fname in fnames:
23
+ depth += 1 # For the opening brace in the split separator
24
+ for chr_i, chr in enumerate(fname):
25
+ if chr == "{":
26
+ depth += 1
27
+ elif chr == "}":
28
+ depth -= 1
29
+ if depth == 0:
30
+ break
31
+
32
+ # json:{} filenames may be nested; filter out everything from
33
+ # inside the outermost one
34
+ if depth == 0:
35
+ chr_i += 1 # First character past the filename
36
+ result += "json:{ /* filtered */ }" + fname[chr_i:]
37
+
38
+sys.stdout.write(result)'
39
+}
97
+}
40
+
98
+
41
# make sure this script returns success
99
+bool block_copy_call_cancelled(BlockCopyCallState *call_state)
42
true
100
+{
101
+ return call_state->cancelled;
102
}
103
104
int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read)
105
@@ -XXX,XX +XXX,XX @@ int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_read)
106
return call_state->ret;
107
}
108
109
+void block_copy_call_cancel(BlockCopyCallState *call_state)
110
+{
111
+ call_state->cancelled = true;
112
+ block_copy_kick(call_state);
113
+}
114
+
115
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s)
116
{
117
return s->copy_bitmap;
43
--
118
--
44
2.24.1
119
2.29.2
45
120
46
121
diff view generated by jsdifflib
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
Message-id: 20191107163708.833192-22-mreitz@redhat.com
2
3
[mreitz: Also disable 273]
3
We are going to use async block-copy call in backup, so we'll need to
4
passthrough setting backup speed to block-copy call.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210116214705.822267-9-vsementsov@virtuozzo.com>
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
10
---
6
tests/qemu-iotests/007 | 5 +++--
11
include/block/blockjob_int.h | 2 ++
7
tests/qemu-iotests/014 | 2 ++
12
blockjob.c | 6 ++++++
8
tests/qemu-iotests/015 | 5 +++--
13
2 files changed, 8 insertions(+)
9
tests/qemu-iotests/026 | 5 ++++-
10
tests/qemu-iotests/029 | 5 +++--
11
tests/qemu-iotests/031 | 6 +++---
12
tests/qemu-iotests/036 | 5 +++--
13
tests/qemu-iotests/039 | 3 +++
14
tests/qemu-iotests/046 | 2 ++
15
tests/qemu-iotests/048 | 2 ++
16
tests/qemu-iotests/051 | 5 +++--
17
tests/qemu-iotests/058 | 5 +++--
18
tests/qemu-iotests/060 | 6 ++++--
19
tests/qemu-iotests/061 | 6 ++++--
20
tests/qemu-iotests/062 | 2 +-
21
tests/qemu-iotests/066 | 4 +++-
22
tests/qemu-iotests/067 | 6 ++++--
23
tests/qemu-iotests/068 | 5 +++--
24
tests/qemu-iotests/071 | 3 +++
25
tests/qemu-iotests/073 | 4 ++++
26
tests/qemu-iotests/074 | 2 ++
27
tests/qemu-iotests/080 | 5 +++--
28
tests/qemu-iotests/090 | 2 ++
29
tests/qemu-iotests/098 | 6 ++++--
30
tests/qemu-iotests/099 | 3 ++-
31
tests/qemu-iotests/103 | 5 +++--
32
tests/qemu-iotests/108 | 6 ++++--
33
tests/qemu-iotests/112 | 5 +++--
34
tests/qemu-iotests/114 | 2 ++
35
tests/qemu-iotests/121 | 3 +++
36
tests/qemu-iotests/138 | 3 +++
37
tests/qemu-iotests/156 | 2 ++
38
tests/qemu-iotests/176 | 7 +++++--
39
tests/qemu-iotests/191 | 2 ++
40
tests/qemu-iotests/201 | 6 +++---
41
tests/qemu-iotests/214 | 3 ++-
42
tests/qemu-iotests/217 | 3 ++-
43
tests/qemu-iotests/220 | 5 +++--
44
tests/qemu-iotests/243 | 6 ++++--
45
tests/qemu-iotests/244 | 5 +++--
46
tests/qemu-iotests/250 | 2 ++
47
tests/qemu-iotests/261 | 3 ++-
48
tests/qemu-iotests/267 | 5 +++--
49
tests/qemu-iotests/273 | 3 +++
50
44 files changed, 127 insertions(+), 53 deletions(-)
51
14
52
diff --git a/tests/qemu-iotests/007 b/tests/qemu-iotests/007
15
diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
53
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
54
--- a/tests/qemu-iotests/007
17
--- a/include/block/blockjob_int.h
55
+++ b/tests/qemu-iotests/007
18
+++ b/include/block/blockjob_int.h
56
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
19
@@ -XXX,XX +XXX,XX @@ struct BlockJobDriver {
57
_supported_fmt qcow2
20
* besides job->blk to the new AioContext.
58
_supported_proto generic
21
*/
59
# refcount_bits must be at least 4 so we can create ten internal snapshots
22
void (*attached_aio_context)(BlockJob *job, AioContext *new_context);
60
-# (1 bit supports none, 2 bits support two, 4 bits support 14)
23
+
61
-_unsupported_imgopts 'refcount_bits=\(1\|2\)[^0-9]'
24
+ void (*set_speed)(BlockJob *job, int64_t speed);
62
+# (1 bit supports none, 2 bits support two, 4 bits support 14);
25
};
63
+# snapshot are generally impossible with external data files
26
64
+_unsupported_imgopts 'refcount_bits=\(1\|2\)[^0-9]' data_file
27
/**
65
28
diff --git a/blockjob.c b/blockjob.c
66
echo
29
index XXXXXXX..XXXXXXX 100644
67
echo "creating image"
30
--- a/blockjob.c
68
diff --git a/tests/qemu-iotests/014 b/tests/qemu-iotests/014
31
+++ b/blockjob.c
69
index XXXXXXX..XXXXXXX 100755
32
@@ -XXX,XX +XXX,XX @@ static bool job_timer_pending(Job *job)
70
--- a/tests/qemu-iotests/014
33
71
+++ b/tests/qemu-iotests/014
34
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
72
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
73
_supported_fmt qcow2
74
_supported_proto file
75
_supported_os Linux
76
+# Compression and snapshots do not work with external data files
77
+_unsupported_imgopts data_file
78
79
TEST_OFFSETS="0 4294967296"
80
TEST_OPS="writev read write readv"
81
diff --git a/tests/qemu-iotests/015 b/tests/qemu-iotests/015
82
index XXXXXXX..XXXXXXX 100755
83
--- a/tests/qemu-iotests/015
84
+++ b/tests/qemu-iotests/015
85
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
86
# actually any format that supports snapshots
87
_supported_fmt qcow2
88
_supported_proto generic
89
-# Internal snapshots are (currently) impossible with refcount_bits=1
90
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
91
+# Internal snapshots are (currently) impossible with refcount_bits=1,
92
+# and generally impossible with external data files
93
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
94
95
echo
96
echo "creating image"
97
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
98
index XXXXXXX..XXXXXXX 100755
99
--- a/tests/qemu-iotests/026
100
+++ b/tests/qemu-iotests/026
101
@@ -XXX,XX +XXX,XX @@ _supported_cache_modes writethrough none
102
# 32 and 64 bits do not work either, however, due to different leaked cluster
103
# count on error.
104
# Thus, the only remaining option is refcount_bits=16.
105
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
106
+#
107
+# As for data_file, none of the refcount tests can work for it.
108
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' \
109
+ data_file
110
111
echo "Errors while writing 128 kB"
112
echo
113
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
114
index XXXXXXX..XXXXXXX 100755
115
--- a/tests/qemu-iotests/029
116
+++ b/tests/qemu-iotests/029
117
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
118
_supported_fmt qcow2
119
_supported_proto generic
120
_unsupported_proto vxhs
121
-# Internal snapshots are (currently) impossible with refcount_bits=1
122
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
123
+# Internal snapshots are (currently) impossible with refcount_bits=1,
124
+# and generally impossible with external data files
125
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
126
127
offset_size=24
128
offset_l1_size=36
129
diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031
130
index XXXXXXX..XXXXXXX 100755
131
--- a/tests/qemu-iotests/031
132
+++ b/tests/qemu-iotests/031
133
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
134
# This tests qcow2-specific low-level functionality
135
_supported_fmt qcow2
136
_supported_proto file
137
-# We want to test compat=0.10, which does not support refcount widths
138
-# other than 16
139
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
140
+# We want to test compat=0.10, which does not support external data
141
+# files or refcount widths other than 16
142
+_unsupported_imgopts data_file 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
143
144
CLUSTER_SIZE=65536
145
146
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
147
index XXXXXXX..XXXXXXX 100755
148
--- a/tests/qemu-iotests/036
149
+++ b/tests/qemu-iotests/036
150
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
151
# This tests qcow2-specific low-level functionality
152
_supported_fmt qcow2
153
_supported_proto file
154
-# Only qcow2v3 and later supports feature bits
155
-_unsupported_imgopts 'compat=0.10'
156
+# Only qcow2v3 and later supports feature bits;
157
+# qcow2.py does not support external data files
158
+_unsupported_imgopts 'compat=0.10' data_file
159
160
echo
161
echo === Image with unknown incompatible feature bit ===
162
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
163
index XXXXXXX..XXXXXXX 100755
164
--- a/tests/qemu-iotests/039
165
+++ b/tests/qemu-iotests/039
166
@@ -XXX,XX +XXX,XX @@ _supported_proto file
167
_supported_os Linux
168
_default_cache_mode writethrough
169
_supported_cache_modes writethrough
170
+# Some of these test cases expect no external data file so that all
171
+# clusters are part of the qcow2 image and refcounted
172
+_unsupported_imgopts data_file
173
174
size=128M
175
176
diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046
177
index XXXXXXX..XXXXXXX 100755
178
--- a/tests/qemu-iotests/046
179
+++ b/tests/qemu-iotests/046
180
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
181
182
_supported_fmt qcow2
183
_supported_proto file
184
+# data_file does not support compressed clusters
185
+_unsupported_imgopts data_file
186
187
CLUSTER_SIZE=64k
188
size=128M
189
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
190
index XXXXXXX..XXXXXXX 100755
191
--- a/tests/qemu-iotests/048
192
+++ b/tests/qemu-iotests/048
193
@@ -XXX,XX +XXX,XX @@ _compare()
194
_supported_fmt raw qcow2 qed luks
195
_supported_proto file
196
_supported_os Linux
197
+# Using 'cp' is incompatible with external data files
198
+_unsupported_imgopts data_file
199
200
# Remove once all tests are fixed to use TEST_IMG_FILE
201
# correctly and common.rc sets it unconditionally
202
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
203
index XXXXXXX..XXXXXXX 100755
204
--- a/tests/qemu-iotests/051
205
+++ b/tests/qemu-iotests/051
206
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
207
_supported_fmt qcow2
208
_supported_proto file
209
# A compat=0.10 image is created in this test which does not support anything
210
-# other than refcount_bits=16
211
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
212
+# other than refcount_bits=16;
213
+# it also will not support an external data file
214
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
215
_require_drivers nbd
216
217
do_run_qemu()
218
diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058
219
index XXXXXXX..XXXXXXX 100755
220
--- a/tests/qemu-iotests/058
221
+++ b/tests/qemu-iotests/058
222
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2
223
_supported_proto file
224
_supported_os Linux
225
_require_command QEMU_NBD
226
-# Internal snapshots are (currently) impossible with refcount_bits=1
227
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
228
+# Internal snapshots are (currently) impossible with refcount_bits=1,
229
+# and generally impossible with external data files
230
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
231
232
nbd_snapshot_img="nbd:unix:$nbd_unix_socket"
233
234
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
235
index XXXXXXX..XXXXXXX 100755
236
--- a/tests/qemu-iotests/060
237
+++ b/tests/qemu-iotests/060
238
@@ -XXX,XX +XXX,XX @@ _filter_io_error()
239
_supported_fmt qcow2
240
_supported_proto file
241
_supported_os Linux
242
-# These tests only work for compat=1.1 images with refcount_bits=16
243
-_unsupported_imgopts 'compat=0.10' 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
244
+# These tests only work for compat=1.1 images without an external
245
+# data file with refcount_bits=16
246
+_unsupported_imgopts 'compat=0.10' data_file \
247
+ 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
248
249
# The repair process will create a large file - so check for availability first
250
_require_large_file 64G
251
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
252
index XXXXXXX..XXXXXXX 100755
253
--- a/tests/qemu-iotests/061
254
+++ b/tests/qemu-iotests/061
255
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2
256
_supported_proto file
257
_supported_os Linux
258
# Conversion between different compat versions can only really work
259
-# with refcount_bits=16
260
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
261
+# with refcount_bits=16;
262
+# we have explicit tests for data_file here, but the whole test does
263
+# not work with it
264
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
265
266
echo
267
echo "=== Testing version downgrade with zero expansion ==="
268
diff --git a/tests/qemu-iotests/062 b/tests/qemu-iotests/062
269
index XXXXXXX..XXXXXXX 100755
270
--- a/tests/qemu-iotests/062
271
+++ b/tests/qemu-iotests/062
272
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
273
_supported_fmt qcow2
274
_supported_proto generic
275
# We need zero clusters and snapshots
276
-_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
277
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
278
279
IMG_SIZE=64M
280
281
diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
282
index XXXXXXX..XXXXXXX 100755
283
--- a/tests/qemu-iotests/066
284
+++ b/tests/qemu-iotests/066
285
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
286
_supported_fmt qcow2
287
_supported_proto generic
288
# We need zero clusters and snapshots
289
-_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
290
+# (TODO: Consider splitting the snapshot part into a separate test
291
+# file, so this one runs with refcount_bits=1 and data_file)
292
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
293
294
# Intentionally create an unaligned image
295
IMG_SIZE=$((64 * 1024 * 1024 + 512))
296
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
297
index XXXXXXX..XXXXXXX 100755
298
--- a/tests/qemu-iotests/067
299
+++ b/tests/qemu-iotests/067
300
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
301
302
_supported_fmt qcow2
303
_supported_proto file
304
-# Because anything other than 16 would change the output of query-block
305
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
306
+# Because anything other than 16 would change the output of query-block,
307
+# and external data files would change the output of
308
+# query-named-block-nodes
309
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
310
311
do_run_qemu()
312
{
35
{
313
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
36
+ const BlockJobDriver *drv = block_job_driver(job);
314
index XXXXXXX..XXXXXXX 100755
37
int64_t old_speed = job->speed;
315
--- a/tests/qemu-iotests/068
38
316
+++ b/tests/qemu-iotests/068
39
if (job_apply_verb(&job->job, JOB_VERB_SET_SPEED, errp)) {
317
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
40
@@ -XXX,XX +XXX,XX @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
318
# This tests qcow2-specific low-level functionality
41
ratelimit_set_speed(&job->limit, speed, BLOCK_JOB_SLICE_TIME);
319
_supported_fmt qcow2
42
320
_supported_proto generic
43
job->speed = speed;
321
-# Internal snapshots are (currently) impossible with refcount_bits=1
44
+
322
-_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
45
+ if (drv->set_speed) {
323
+# Internal snapshots are (currently) impossible with refcount_bits=1,
46
+ drv->set_speed(job, speed);
324
+# and generally impossible with external data files
47
+ }
325
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file
48
+
326
49
if (speed && speed <= old_speed) {
327
IMG_SIZE=128K
50
return;
328
51
}
329
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
330
index XXXXXXX..XXXXXXX 100755
331
--- a/tests/qemu-iotests/071
332
+++ b/tests/qemu-iotests/071
333
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
334
_supported_fmt qcow2
335
_supported_proto file
336
_require_drivers blkdebug blkverify
337
+# blkdebug can only inject errors on bs->file, not on the data_file,
338
+# so thie test does not work with external data files
339
+_unsupported_imgopts data_file
340
341
do_run_qemu()
342
{
343
diff --git a/tests/qemu-iotests/073 b/tests/qemu-iotests/073
344
index XXXXXXX..XXXXXXX 100755
345
--- a/tests/qemu-iotests/073
346
+++ b/tests/qemu-iotests/073
347
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
348
_supported_fmt qcow2
349
_supported_proto generic
350
_unsupported_proto vxhs
351
+# External data files do not support compressed clusters
352
+# (TODO: Consider writing a version for external data files that does
353
+# not test compressed clusters)
354
+_unsupported_imgopts data_file
355
356
CLUSTER_SIZE=64k
357
size=128M
358
diff --git a/tests/qemu-iotests/074 b/tests/qemu-iotests/074
359
index XXXXXXX..XXXXXXX 100755
360
--- a/tests/qemu-iotests/074
361
+++ b/tests/qemu-iotests/074
362
@@ -XXX,XX +XXX,XX @@ _compare()
363
_supported_fmt qcow2
364
_supported_proto file
365
_supported_os Linux
366
+# blkdebug can only inject errors on bs->file
367
+_unsupported_imgopts data_file
368
369
# Setup test basic parameters
370
TEST_IMG2=$TEST_IMG.2
371
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
372
index XXXXXXX..XXXXXXX 100755
373
--- a/tests/qemu-iotests/080
374
+++ b/tests/qemu-iotests/080
375
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
376
_supported_fmt qcow2
377
_supported_proto file
378
_supported_os Linux
379
-# - Internal snapshots are (currently) impossible with refcount_bits=1
380
+# - Internal snapshots are (currently) impossible with refcount_bits=1,
381
+# and generally impossible with external data files
382
# - This is generally a test for compat=1.1 images
383
-_unsupported_imgopts 'refcount_bits=1[^0-9]' 'compat=0.10'
384
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file 'compat=0.10'
385
386
header_size=104
387
388
diff --git a/tests/qemu-iotests/090 b/tests/qemu-iotests/090
389
index XXXXXXX..XXXXXXX 100755
390
--- a/tests/qemu-iotests/090
391
+++ b/tests/qemu-iotests/090
392
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
393
394
_supported_fmt qcow2
395
_supported_proto file nfs
396
+# External data files do not support compressed clusters
397
+_unsupported_imgopts data_file
398
399
IMG_SIZE=128K
400
401
diff --git a/tests/qemu-iotests/098 b/tests/qemu-iotests/098
402
index XXXXXXX..XXXXXXX 100755
403
--- a/tests/qemu-iotests/098
404
+++ b/tests/qemu-iotests/098
405
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
406
407
_supported_fmt qcow2
408
_supported_proto file
409
-# The code path we want to test here only works for compat=1.1 images
410
-_unsupported_imgopts 'compat=0.10'
411
+# The code path we want to test here only works for compat=1.1 images;
412
+# blkdebug can only inject errors on bs->file, so external data files
413
+# do not work with this test
414
+_unsupported_imgopts 'compat=0.10' data_file
415
416
for event in l1_update empty_image_prepare reftable_update refblock_alloc; do
417
418
diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099
419
index XXXXXXX..XXXXXXX 100755
420
--- a/tests/qemu-iotests/099
421
+++ b/tests/qemu-iotests/099
422
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow qcow2 qed vdi vhdx vmdk vpc
423
_supported_proto file
424
_supported_os Linux
425
_require_drivers blkdebug blkverify
426
+# data_file would change the json:{} filenames
427
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
428
- "subformat=twoGbMaxExtentSparse"
429
+ "subformat=twoGbMaxExtentSparse" data_file
430
431
do_run_qemu()
432
{
433
diff --git a/tests/qemu-iotests/103 b/tests/qemu-iotests/103
434
index XXXXXXX..XXXXXXX 100755
435
--- a/tests/qemu-iotests/103
436
+++ b/tests/qemu-iotests/103
437
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
438
439
_supported_fmt qcow2
440
_supported_proto file nfs
441
-# Internal snapshots are (currently) impossible with refcount_bits=1
442
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
443
+# Internal snapshots are (currently) impossible with refcount_bits=1,
444
+# and generally impossible with external data files
445
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
446
447
IMG_SIZE=64K
448
449
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
450
index XXXXXXX..XXXXXXX 100755
451
--- a/tests/qemu-iotests/108
452
+++ b/tests/qemu-iotests/108
453
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
454
_supported_fmt qcow2
455
_supported_proto file
456
_supported_os Linux
457
-# This test directly modifies a refblock so it relies on refcount_bits being 16
458
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
459
+# This test directly modifies a refblock so it relies on refcount_bits being 16;
460
+# and the low-level modification it performs are not tuned for external data
461
+# files
462
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
463
464
echo
465
echo '=== Repairing an image without any refcount table ==='
466
diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112
467
index XXXXXXX..XXXXXXX 100755
468
--- a/tests/qemu-iotests/112
469
+++ b/tests/qemu-iotests/112
470
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
471
_supported_fmt qcow2
472
_supported_proto file
473
# This test will set refcount_bits on its own which would conflict with the
474
-# manual setting; compat will be overridden as well
475
-_unsupported_imgopts refcount_bits 'compat=0.10'
476
+# manual setting; compat will be overridden as well;
477
+# and external data files do not work well with our refcount testing
478
+_unsupported_imgopts refcount_bits 'compat=0.10' data_file
479
480
print_refcount_bits()
481
{
482
diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114
483
index XXXXXXX..XXXXXXX 100755
484
--- a/tests/qemu-iotests/114
485
+++ b/tests/qemu-iotests/114
486
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
487
_supported_fmt qcow2
488
_supported_proto generic
489
_unsupported_proto vxhs
490
+# qcow2.py does not work too well with external data files
491
+_unsupported_imgopts data_file
492
493
494
TEST_IMG="$TEST_IMG.base" _make_test_img 64M
495
diff --git a/tests/qemu-iotests/121 b/tests/qemu-iotests/121
496
index XXXXXXX..XXXXXXX 100755
497
--- a/tests/qemu-iotests/121
498
+++ b/tests/qemu-iotests/121
499
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
500
_supported_fmt qcow2
501
_supported_proto file
502
_supported_os Linux
503
+# Refcount structures are used much differently with external data
504
+# files
505
+_unsupported_imgopts data_file
506
507
echo
508
echo '=== New refcount structures may not conflict with existing structures ==='
509
diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138
510
index XXXXXXX..XXXXXXX 100755
511
--- a/tests/qemu-iotests/138
512
+++ b/tests/qemu-iotests/138
513
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
514
_supported_fmt qcow2
515
_supported_proto file
516
_supported_os Linux
517
+# With an external data file, data clusters are not refcounted
518
+# (and so qemu-img check does not check their refcount)
519
+_unsupported_imgopts data_file
520
521
echo
522
echo '=== Check on an image with a multiple of 2^32 clusters ==='
523
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
524
index XXXXXXX..XXXXXXX 100755
525
--- a/tests/qemu-iotests/156
526
+++ b/tests/qemu-iotests/156
527
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
528
_supported_fmt qcow2 qed
529
_supported_proto generic
530
_unsupported_proto vxhs
531
+# Copying files around with cp does not work with external data files
532
+_unsupported_imgopts data_file
533
534
# Create source disk
535
TEST_IMG="$TEST_IMG.backing" _make_test_img 1M
536
diff --git a/tests/qemu-iotests/176 b/tests/qemu-iotests/176
537
index XXXXXXX..XXXXXXX 100755
538
--- a/tests/qemu-iotests/176
539
+++ b/tests/qemu-iotests/176
540
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
541
_supported_fmt qcow2
542
_supported_proto file
543
_supported_os Linux
544
-# Persistent dirty bitmaps require compat=1.1
545
-_unsupported_imgopts 'compat=0.10'
546
+# Persistent dirty bitmaps require compat=1.1;
547
+# Internal snapshots forbid using an external data file
548
+# (they work with refcount_bits=1 here, though, because there actually
549
+# is no data when creating the snapshot)
550
+_unsupported_imgopts 'compat=0.10' data_file
551
552
run_qemu()
553
{
554
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
555
index XXXXXXX..XXXXXXX 100755
556
--- a/tests/qemu-iotests/191
557
+++ b/tests/qemu-iotests/191
558
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
559
560
_supported_fmt qcow2
561
_supported_proto file
562
+# An external data file would change the query-named-block-nodes output
563
+_unsupported_imgopts data_file
564
565
size=64M
566
567
diff --git a/tests/qemu-iotests/201 b/tests/qemu-iotests/201
568
index XXXXXXX..XXXXXXX 100755
569
--- a/tests/qemu-iotests/201
570
+++ b/tests/qemu-iotests/201
571
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2
572
_supported_proto generic
573
_supported_os Linux
574
575
-# Internal snapshots are (currently) impossible with refcount_bits=1
576
-# This was taken from test 080
577
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
578
+# Internal snapshots are (currently) impossible with refcount_bits=1,
579
+# and generally impossible with external data files
580
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
581
582
size=64M
583
_make_test_img $size
584
diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214
585
index XXXXXXX..XXXXXXX 100755
586
--- a/tests/qemu-iotests/214
587
+++ b/tests/qemu-iotests/214
588
@@ -XXX,XX +XXX,XX @@ _supported_proto file
589
590
# Repairing the corrupted image requires qemu-img check to store a
591
# refcount up to 3, which requires at least two refcount bits.
592
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
593
+# External data files do not support compressed clusters.
594
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
595
596
597
echo
598
diff --git a/tests/qemu-iotests/217 b/tests/qemu-iotests/217
599
index XXXXXXX..XXXXXXX 100755
600
--- a/tests/qemu-iotests/217
601
+++ b/tests/qemu-iotests/217
602
@@ -XXX,XX +XXX,XX @@ _supported_proto file
603
604
# This test needs clusters with at least a refcount of 2 so that
605
# OFLAG_COPIED is not set. refcount_bits=1 is therefore unsupported.
606
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
607
+# (As are external data files.)
608
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
609
610
echo
611
echo '=== Simulating an I/O error during snapshot deletion ==='
612
diff --git a/tests/qemu-iotests/220 b/tests/qemu-iotests/220
613
index XXXXXXX..XXXXXXX 100755
614
--- a/tests/qemu-iotests/220
615
+++ b/tests/qemu-iotests/220
616
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
617
_supported_fmt qcow2
618
_supported_proto file
619
_supported_os Linux
620
-# To use a different refcount width but 16 bits we need compat=1.1
621
-_unsupported_imgopts 'compat=0.10'
622
+# To use a different refcount width but 16 bits we need compat=1.1,
623
+# and external data files do not support compressed clusters.
624
+_unsupported_imgopts 'compat=0.10' data_file
625
626
echo "== Creating huge file =="
627
628
diff --git a/tests/qemu-iotests/243 b/tests/qemu-iotests/243
629
index XXXXXXX..XXXXXXX 100755
630
--- a/tests/qemu-iotests/243
631
+++ b/tests/qemu-iotests/243
632
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
633
_supported_fmt qcow2
634
_supported_proto file
635
_supported_os Linux
636
-# External data files do not work with compat=0.10
637
-_unsupported_imgopts 'compat=0.10'
638
+# External data files do not work with compat=0.10, and because there
639
+# is an explicit case for external data files here, we cannot allow
640
+# the user to specify whether to use one
641
+_unsupported_imgopts 'compat=0.10' data_file
642
643
for mode in off metadata falloc full; do
644
645
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
646
index XXXXXXX..XXXXXXX 100755
647
--- a/tests/qemu-iotests/244
648
+++ b/tests/qemu-iotests/244
649
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
650
_supported_fmt qcow2
651
_supported_proto file
652
_supported_os Linux
653
-# External data files do not work with compat=0.10
654
-_unsupported_imgopts 'compat=0.10'
655
+# External data files do not work with compat=0.10, and because we use
656
+# our own external data file, we cannot let the user specify one
657
+_unsupported_imgopts 'compat=0.10' data_file
658
659
echo
660
echo "=== Create and open image with external data file ==="
661
diff --git a/tests/qemu-iotests/250 b/tests/qemu-iotests/250
662
index XXXXXXX..XXXXXXX 100755
663
--- a/tests/qemu-iotests/250
664
+++ b/tests/qemu-iotests/250
665
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
666
_supported_fmt qcow2
667
_supported_proto file
668
_supported_os Linux
669
+# This test does not make much sense with external data files
670
+_unsupported_imgopts data_file
671
672
# This test checks that qcow2_process_discards does not truncate a discard
673
# request > 2G.
674
diff --git a/tests/qemu-iotests/261 b/tests/qemu-iotests/261
675
index XXXXXXX..XXXXXXX 100755
676
--- a/tests/qemu-iotests/261
677
+++ b/tests/qemu-iotests/261
678
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
679
# (1) We create a v2 image that supports nothing but refcount_bits=16
680
# (2) We do some refcount management on our own which expects
681
# refcount_bits=16
682
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
683
+# As for data files, they do not support snapshots at all.
684
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
685
686
# Parameters:
687
# $1: image filename
688
diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267
689
index XXXXXXX..XXXXXXX 100755
690
--- a/tests/qemu-iotests/267
691
+++ b/tests/qemu-iotests/267
692
@@ -XXX,XX +XXX,XX @@ _supported_proto file
693
_supported_os Linux
694
_require_drivers copy-on-read
695
696
-# Internal snapshots are (currently) impossible with refcount_bits=1
697
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
698
+# Internal snapshots are (currently) impossible with refcount_bits=1,
699
+# and generally impossible with external data files
700
+_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
701
702
do_run_qemu()
703
{
704
diff --git a/tests/qemu-iotests/273 b/tests/qemu-iotests/273
705
index XXXXXXX..XXXXXXX 100755
706
--- a/tests/qemu-iotests/273
707
+++ b/tests/qemu-iotests/273
708
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
709
_supported_fmt qcow2
710
_supported_proto file
711
_supported_os Linux
712
+# External data files would add nodes to the block graph, so it would
713
+# not match the reference output
714
+_unsupported_imgopts data_file
715
716
do_run_qemu()
717
{
718
--
52
--
719
2.24.1
53
2.29.2
720
54
721
55
diff view generated by jsdifflib
1
This will not work with external data files, so try to get tests working
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
without it as far as possible.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
If main job coroutine called job_yield (while some background process
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
is in progress), we should give it a chance to call job_pause_point().
6
Message-id: 20191107163708.833192-17-mreitz@redhat.com
5
It will be used in backup, when moved on async block-copy.
6
7
Note, that job_user_pause is not enough: we want to handle
8
child_job_drained_begin() as well, which call job_pause().
9
10
Still, if job is already in job_do_yield() in job_pause_point() we
11
should not enter it.
12
13
iotest 109 output is modified: on stop we do bdrv_drain_all() which now
14
triggers job pause immediately (and pause after ready is standby).
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Message-Id: <20210116214705.822267-10-vsementsov@virtuozzo.com>
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
20
---
9
tests/qemu-iotests/063 | 12 ++++--------
21
job.c | 3 +++
10
tests/qemu-iotests/063.out | 3 ++-
22
tests/qemu-iotests/109.out | 24 ++++++++++++++++++++++++
11
tests/qemu-iotests/085 | 9 +++------
23
2 files changed, 27 insertions(+)
12
tests/qemu-iotests/085.out | 8 ++++----
13
4 files changed, 13 insertions(+), 19 deletions(-)
14
24
15
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
25
diff --git a/job.c b/job.c
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/063
18
+++ b/tests/qemu-iotests/063
19
@@ -XXX,XX +XXX,XX @@ _unsupported_imgopts "subformat=monolithicFlat" \
20
_make_test_img 4M
21
22
echo "== Testing conversion with -n fails with no target file =="
23
-# check .orig file does not exist
24
-rm -f "$TEST_IMG.orig"
25
if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" >/dev/null 2>&1; then
26
exit 1
27
fi
28
29
echo "== Testing conversion with -n succeeds with a target file =="
30
-rm -f "$TEST_IMG.orig"
31
-cp "$TEST_IMG" "$TEST_IMG.orig"
32
+_rm_test_img "$TEST_IMG.orig"
33
+TEST_IMG="$TEST_IMG.orig" _make_test_img 4M
34
if ! $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" ; then
35
exit 1
36
fi
37
@@ -XXX,XX +XXX,XX @@ fi
38
_check_test_img
39
40
echo "== Testing conversion to a smaller file fails =="
41
-rm -f "$TEST_IMG.orig"
42
-mv "$TEST_IMG" "$TEST_IMG.orig"
43
-_make_test_img 2M
44
-if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG.orig" "$TEST_IMG" >/dev/null 2>&1; then
45
+TEST_IMG="$TEST_IMG.target" _make_test_img 2M
46
+if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.target" >/dev/null 2>&1; then
47
exit 1
48
fi
49
50
diff --git a/tests/qemu-iotests/063.out b/tests/qemu-iotests/063.out
51
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
52
--- a/tests/qemu-iotests/063.out
27
--- a/job.c
53
+++ b/tests/qemu-iotests/063.out
28
+++ b/job.c
54
@@ -XXX,XX +XXX,XX @@ QA output created by 063
29
@@ -XXX,XX +XXX,XX @@ static bool job_timer_not_pending(Job *job)
55
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
30
void job_pause(Job *job)
56
== Testing conversion with -n fails with no target file ==
57
== Testing conversion with -n succeeds with a target file ==
58
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=4194304
59
== Testing conversion to raw is the same after conversion with -n ==
60
== Testing conversion back to original format ==
61
No errors were found on the image.
62
== Testing conversion to a smaller file fails ==
63
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152
64
+Formatting 'TEST_DIR/t.IMGFMT.target', fmt=IMGFMT size=2097152
65
== Regression testing for copy offloading bug ==
66
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
67
Formatting 'TEST_DIR/t.IMGFMT.target', fmt=IMGFMT size=1048576
68
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
69
index XXXXXXX..XXXXXXX 100755
70
--- a/tests/qemu-iotests/085
71
+++ b/tests/qemu-iotests/085
72
@@ -XXX,XX +XXX,XX @@ add_snapshot_image()
73
{
31
{
74
base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}"
32
job->pause_count++;
75
snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}"
33
+ if (!job->paused) {
76
- _make_test_img -u -b "${base_image}" "$size"
34
+ job_enter(job);
77
- mv "${TEST_IMG}" "${snapshot_file}"
35
+ }
78
+ TEST_IMG=$snapshot_file _make_test_img -u -b "${base_image}" "$size"
79
do_blockdev_add "$1" "'backing': null, " "${snapshot_file}"
80
}
36
}
81
37
82
@@ -XXX,XX +XXX,XX @@ blockdev_snapshot()
38
void job_resume(Job *job)
83
39
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
84
size=128M
85
86
-_make_test_img $size
87
-mv "${TEST_IMG}" "${TEST_IMG}.1"
88
-_make_test_img $size
89
-mv "${TEST_IMG}" "${TEST_IMG}.2"
90
+TEST_IMG="$TEST_IMG.1" _make_test_img $size
91
+TEST_IMG="$TEST_IMG.2" _make_test_img $size
92
93
echo
94
echo === Running QEMU ===
95
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
96
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
97
--- a/tests/qemu-iotests/085.out
41
--- a/tests/qemu-iotests/109.out
98
+++ b/tests/qemu-iotests/085.out
42
+++ b/tests/qemu-iotests/109.out
99
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
100
QA output created by 085
44
{"execute":"quit"}
101
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
102
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
103
+Formatting 'TEST_DIR/t.IMGFMT.1', fmt=IMGFMT size=134217728
104
+Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
105
106
=== Running QEMU ===
107
108
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_fil
109
110
=== Create a couple of snapshots using blockdev-snapshot ===
111
112
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT
113
+Formatting 'TEST_DIR/11-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT
114
{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_11', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/11-snapshot-v0.IMGFMT', 'node-name': 'file_11' } } }
115
{"return": {}}
45
{"return": {}}
116
{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } }
46
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
47
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
48
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
49
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
50
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
51
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
52
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
53
{"execute":"quit"}
117
{"return": {}}
54
{"return": {}}
118
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT
55
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
119
+Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT
56
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
120
{ 'execute': 'blockdev-add', 'arguments': { 'driver': 'IMGFMT', 'node-name': 'snap_12', 'backing': null, 'file': { 'driver': 'file', 'filename': 'TEST_DIR/12-snapshot-v0.IMGFMT', 'node-name': 'file_12' } } }
57
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
58
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
59
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
60
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
61
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
62
{"execute":"quit"}
121
{"return": {}}
63
{"return": {}}
122
{ 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_12' } }
64
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
65
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
66
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
67
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
68
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
69
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
70
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
71
{"execute":"quit"}
72
{"return": {}}
73
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
74
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
75
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
76
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
77
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
78
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
79
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
80
{"execute":"quit"}
81
{"return": {}}
82
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
83
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
84
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
85
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
86
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
87
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
88
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
89
{"execute":"quit"}
90
{"return": {}}
91
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
92
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
93
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
94
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
95
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
96
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
97
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
98
{"execute":"quit"}
99
{"return": {}}
100
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
101
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
102
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
103
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
104
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
105
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
106
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
107
{"execute":"quit"}
108
{"return": {}}
109
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
110
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
111
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
112
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
113
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
114
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
115
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
116
{"execute":"quit"}
117
{"return": {}}
118
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
119
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
120
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
121
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
122
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
123
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
124
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
125
{"execute":"quit"}
126
{"return": {}}
127
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
128
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
129
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
130
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
131
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
132
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
133
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
134
{"execute":"quit"}
135
{"return": {}}
136
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
137
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
138
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
139
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
140
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
141
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
142
@@ -XXX,XX +XXX,XX @@ Images are identical.
143
{"execute":"quit"}
144
{"return": {}}
145
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
146
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}}
147
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}}
148
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}}
149
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}}
150
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
123
--
151
--
124
2.24.1
152
2.29.2
125
153
126
154
diff view generated by jsdifflib
1
Sometimes it is useful to be able to add a node to the block graph that
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
takes or unshare a certain set of permissions for debugging purposes.
3
This patch adds this capability to blkdebug.
4
2
5
(Note that you cannot make blkdebug release or share permissions that it
3
Add new parameters to configure future backup features. The patch
6
needs to take or cannot share, because this might result in assertion
4
doesn't introduce aio backup requests (so we actually have only one
7
failures in the block layer. But if the blkdebug node has no parents,
5
worker) neither requests larger than one cluster. Still, formally we
8
it will not take any permissions and share everything by default, so you
6
satisfy these maximums anyway, so add the parameters now, to facilitate
9
can then freely choose what permissions to take and share.)
7
further patch which will really change backup job behavior.
10
8
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Message-id: 20191108123455.39445-4-mreitz@redhat.com
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20210116214705.822267-11-vsementsov@virtuozzo.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
13
---
16
block/blkdebug.c | 93 +++++++++++++++++++++++++++++++++++++++++++-
14
qapi/block-core.json | 13 ++++++++++++-
17
qapi/block-core.json | 14 ++++++-
15
block/backup.c | 28 +++++++++++++++++++++++-----
18
2 files changed, 105 insertions(+), 2 deletions(-)
16
block/replication.c | 2 +-
17
blockdev.c | 8 +++++++-
18
4 files changed, 43 insertions(+), 8 deletions(-)
19
19
20
diff --git a/block/blkdebug.c b/block/blkdebug.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/blkdebug.c
23
+++ b/block/blkdebug.c
24
@@ -XXX,XX +XXX,XX @@
25
#include "qemu/cutils.h"
26
#include "qemu/config-file.h"
27
#include "block/block_int.h"
28
+#include "block/qdict.h"
29
#include "qemu/module.h"
30
#include "qemu/option.h"
31
+#include "qapi/qapi-visit-block-core.h"
32
#include "qapi/qmp/qdict.h"
33
+#include "qapi/qmp/qlist.h"
34
#include "qapi/qmp/qstring.h"
35
+#include "qapi/qobject-input-visitor.h"
36
#include "sysemu/qtest.h"
37
38
typedef struct BDRVBlkdebugState {
39
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVBlkdebugState {
40
uint64_t opt_discard;
41
uint64_t max_discard;
42
43
+ uint64_t take_child_perms;
44
+ uint64_t unshare_child_perms;
45
+
46
/* For blkdebug_refresh_filename() */
47
char *config_file;
48
49
@@ -XXX,XX +XXX,XX @@ static void blkdebug_parse_filename(const char *filename, QDict *options,
50
qdict_put_str(options, "x-image", filename);
51
}
52
53
+static int blkdebug_parse_perm_list(uint64_t *dest, QDict *options,
54
+ const char *prefix, Error **errp)
55
+{
56
+ int ret = 0;
57
+ QDict *subqdict = NULL;
58
+ QObject *crumpled_subqdict = NULL;
59
+ Visitor *v = NULL;
60
+ BlockPermissionList *perm_list = NULL, *element;
61
+ Error *local_err = NULL;
62
+
63
+ *dest = 0;
64
+
65
+ qdict_extract_subqdict(options, &subqdict, prefix);
66
+ if (!qdict_size(subqdict)) {
67
+ goto out;
68
+ }
69
+
70
+ crumpled_subqdict = qdict_crumple(subqdict, errp);
71
+ if (!crumpled_subqdict) {
72
+ ret = -EINVAL;
73
+ goto out;
74
+ }
75
+
76
+ v = qobject_input_visitor_new(crumpled_subqdict);
77
+ visit_type_BlockPermissionList(v, NULL, &perm_list, &local_err);
78
+ if (local_err) {
79
+ error_propagate(errp, local_err);
80
+ ret = -EINVAL;
81
+ goto out;
82
+ }
83
+
84
+ for (element = perm_list; element; element = element->next) {
85
+ *dest |= bdrv_qapi_perm_to_blk_perm(element->value);
86
+ }
87
+
88
+out:
89
+ qapi_free_BlockPermissionList(perm_list);
90
+ visit_free(v);
91
+ qobject_unref(subqdict);
92
+ qobject_unref(crumpled_subqdict);
93
+ return ret;
94
+}
95
+
96
+static int blkdebug_parse_perms(BDRVBlkdebugState *s, QDict *options,
97
+ Error **errp)
98
+{
99
+ int ret;
100
+
101
+ ret = blkdebug_parse_perm_list(&s->take_child_perms, options,
102
+ "take-child-perms.", errp);
103
+ if (ret < 0) {
104
+ return ret;
105
+ }
106
+
107
+ ret = blkdebug_parse_perm_list(&s->unshare_child_perms, options,
108
+ "unshare-child-perms.", errp);
109
+ if (ret < 0) {
110
+ return ret;
111
+ }
112
+
113
+ return 0;
114
+}
115
+
116
static QemuOptsList runtime_opts = {
117
.name = "blkdebug",
118
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
119
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
120
/* Set initial state */
121
s->state = 1;
122
123
+ /* Parse permissions modifiers before opening the image file */
124
+ ret = blkdebug_parse_perms(s, options, errp);
125
+ if (ret < 0) {
126
+ goto out;
127
+ }
128
+
129
/* Open the image file */
130
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
131
bs, &child_file, false, &local_err);
132
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
133
return 0;
134
}
135
136
+static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
137
+ const BdrvChildRole *role,
138
+ BlockReopenQueue *reopen_queue,
139
+ uint64_t perm, uint64_t shared,
140
+ uint64_t *nperm, uint64_t *nshared)
141
+{
142
+ BDRVBlkdebugState *s = bs->opaque;
143
+
144
+ bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
145
+ nperm, nshared);
146
+
147
+ *nperm |= s->take_child_perms;
148
+ *nshared &= ~s->unshare_child_perms;
149
+}
150
+
151
static const char *const blkdebug_strong_runtime_opts[] = {
152
"config",
153
"inject-error.",
154
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
155
.bdrv_file_open = blkdebug_open,
156
.bdrv_close = blkdebug_close,
157
.bdrv_reopen_prepare = blkdebug_reopen_prepare,
158
- .bdrv_child_perm = bdrv_filter_default_perms,
159
+ .bdrv_child_perm = blkdebug_child_perm,
160
161
.bdrv_getlength = blkdebug_getlength,
162
.bdrv_refresh_filename = blkdebug_refresh_filename,
163
diff --git a/qapi/block-core.json b/qapi/block-core.json
20
diff --git a/qapi/block-core.json b/qapi/block-core.json
164
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
165
--- a/qapi/block-core.json
22
--- a/qapi/block-core.json
166
+++ b/qapi/block-core.json
23
+++ b/qapi/block-core.json
167
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
168
#
25
#
169
# @set-state: array of state-change descriptions
26
# @use-copy-range: Use copy offloading. Default true.
170
#
27
#
171
+# @take-child-perms: Permissions to take on @image in addition to what
28
+# @max-workers: Maximum number of parallel requests for the sustained background
172
+# is necessary anyway (which depends on how the
29
+# copying process. Doesn't influence copy-before-write operations.
173
+# blkdebug node is used). Defaults to none.
30
+# Default 64.
174
+# (since 5.0)
175
+#
31
+#
176
+# @unshare-child-perms: Permissions not to share on @image in addition
32
+# @max-chunk: Maximum request length for the sustained background copying
177
+# to what cannot be shared anyway (which depends
33
+# process. Doesn't influence copy-before-write operations.
178
+# on how the blkdebug node is used). Defaults
34
+# 0 means unlimited. If max-chunk is non-zero then it should not be
179
+# to none. (since 5.0)
35
+# less than job cluster size which is calculated as maximum of
36
+# target image cluster size and 64k. Default 0.
180
+#
37
+#
181
# Since: 2.9
38
# Since: 6.0
182
##
39
##
183
{ 'struct': 'BlockdevOptionsBlkdebug',
40
{ 'struct': 'BackupPerf',
184
@@ -XXX,XX +XXX,XX @@
41
- 'data': { '*use-copy-range': 'bool' }}
185
'*opt-write-zero': 'int32', '*max-write-zero': 'int32',
42
+ 'data': { '*use-copy-range': 'bool',
186
'*opt-discard': 'int32', '*max-discard': 'int32',
43
+ '*max-workers': 'int', '*max-chunk': 'int64' } }
187
'*inject-error': ['BlkdebugInjectErrorOptions'],
188
- '*set-state': ['BlkdebugSetStateOptions'] } }
189
+ '*set-state': ['BlkdebugSetStateOptions'],
190
+ '*take-child-perms': ['BlockPermission'],
191
+ '*unshare-child-perms': ['BlockPermission'] } }
192
44
193
##
45
##
194
# @BlockdevOptionsBlklogwrites:
46
# @BackupCommon:
47
diff --git a/block/backup.c b/block/backup.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/backup.c
50
+++ b/block/backup.c
51
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
52
return NULL;
53
}
54
55
+ cluster_size = backup_calculate_cluster_size(target, errp);
56
+ if (cluster_size < 0) {
57
+ goto error;
58
+ }
59
+
60
+ if (perf->max_workers < 1) {
61
+ error_setg(errp, "max-workers must be greater than zero");
62
+ return NULL;
63
+ }
64
+
65
+ if (perf->max_chunk < 0) {
66
+ error_setg(errp, "max-chunk must be zero (which means no limit) or "
67
+ "positive");
68
+ return NULL;
69
+ }
70
+
71
+ if (perf->max_chunk && perf->max_chunk < cluster_size) {
72
+ error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
73
+ "cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
74
+ return NULL;
75
+ }
76
+
77
+
78
if (sync_bitmap) {
79
/* If we need to write to this bitmap, check that we can: */
80
if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
81
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
82
goto error;
83
}
84
85
- cluster_size = backup_calculate_cluster_size(target, errp);
86
- if (cluster_size < 0) {
87
- goto error;
88
- }
89
-
90
/*
91
* If source is in backing chain of target assume that target is going to be
92
* used for "image fleecing", i.e. it should represent a kind of snapshot of
93
diff --git a/block/replication.c b/block/replication.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/block/replication.c
96
+++ b/block/replication.c
97
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
98
int64_t active_length, hidden_length, disk_length;
99
AioContext *aio_context;
100
Error *local_err = NULL;
101
- BackupPerf perf = { .use_copy_range = true };
102
+ BackupPerf perf = { .use_copy_range = true, .max_workers = 1 };
103
104
aio_context = bdrv_get_aio_context(bs);
105
aio_context_acquire(aio_context);
106
diff --git a/blockdev.c b/blockdev.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/blockdev.c
109
+++ b/blockdev.c
110
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
111
{
112
BlockJob *job = NULL;
113
BdrvDirtyBitmap *bmap = NULL;
114
- BackupPerf perf = { .use_copy_range = true };
115
+ BackupPerf perf = { .use_copy_range = true, .max_workers = 64 };
116
int job_flags = JOB_DEFAULT;
117
118
if (!backup->has_speed) {
119
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
120
if (backup->x_perf->has_use_copy_range) {
121
perf.use_copy_range = backup->x_perf->use_copy_range;
122
}
123
+ if (backup->x_perf->has_max_workers) {
124
+ perf.max_workers = backup->x_perf->max_workers;
125
+ }
126
+ if (backup->x_perf->has_max_chunk) {
127
+ perf.max_chunk = backup->x_perf->max_chunk;
128
+ }
129
}
130
131
if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) ||
195
--
132
--
196
2.24.1
133
2.29.2
197
134
198
135
diff view generated by jsdifflib
1
The image end offset as reported by qemu-img check is different when
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
using an external data file; we do not care about its value here, so we
3
can just filter it. Incidentally, common.rc already has _check_test_img
4
for us which does exactly that.
5
2
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
After introducing parallel async copy requests instead of plain
7
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
cluster-by-cluster copying loop, we'll have to wait for paused status,
8
Message-id: 20191107163708.833192-18-mreitz@redhat.com
5
as we need to wait for several parallel request. So, let's gently wait
6
instead of just asserting that job already paused.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210116214705.822267-12-vsementsov@virtuozzo.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
12
---
11
tests/qemu-iotests/091 | 2 +-
13
tests/qemu-iotests/056 | 9 +++++++--
12
tests/qemu-iotests/091.out | 2 --
14
1 file changed, 7 insertions(+), 2 deletions(-)
13
2 files changed, 1 insertion(+), 3 deletions(-)
14
15
15
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
16
diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
16
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/091
18
--- a/tests/qemu-iotests/056
18
+++ b/tests/qemu-iotests/091
19
+++ b/tests/qemu-iotests/056
19
@@ -XXX,XX +XXX,XX @@ echo "Check image pattern"
20
@@ -XXX,XX +XXX,XX @@ class BackupTest(iotests.QMPTestCase):
20
${QEMU_IO} -c "read -P 0x22 0 4M" "${TEST_IMG}" | _filter_testdir | _filter_qemu_io
21
event = self.vm.event_wait(name="BLOCK_JOB_ERROR",
21
22
match={'data': {'device': 'drive0'}})
22
echo "Running 'qemu-img check -r all \$TEST_IMG'"
23
self.assertNotEqual(event, None)
23
-"${QEMU_IMG}" check -r all "${TEST_IMG}" 2>&1 | _filter_testdir | _filter_qemu
24
- # OK, job should be wedged
24
+_check_test_img -r all
25
- res = self.vm.qmp('query-block-jobs')
25
26
+ # OK, job should pause, but it can't do it immediately, as it can't
26
echo "*** done"
27
+ # cancel other parallel requests (which didn't fail)
27
rm -f $seq.full
28
+ with iotests.Timeout(60, "Timeout waiting for backup actually paused"):
28
diff --git a/tests/qemu-iotests/091.out b/tests/qemu-iotests/091.out
29
+ while True:
29
index XXXXXXX..XXXXXXX 100644
30
+ res = self.vm.qmp('query-block-jobs')
30
--- a/tests/qemu-iotests/091.out
31
+ if res['return'][0]['status'] == 'paused':
31
+++ b/tests/qemu-iotests/091.out
32
+ break
32
@@ -XXX,XX +XXX,XX @@ read 4194304/4194304 bytes at offset 0
33
self.assert_qmp(res, 'return[0]/status', 'paused')
33
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
34
res = self.vm.qmp('block-job-dismiss', id='drive0')
34
Running 'qemu-img check -r all $TEST_IMG'
35
self.assert_qmp(res, 'error/desc',
35
No errors were found on the image.
36
-80/16384 = 0.49% allocated, 0.00% fragmented, 0.00% compressed clusters
37
-Image end offset: 5570560
38
*** done
39
--
36
--
40
2.24.1
37
2.29.2
41
38
42
39
diff view generated by jsdifflib
1
IMGOPTS can never be empty for qcow2, because the check scripts adds
1
Right now, this does not change anything, because backup ignores
2
compat=1.1 unless the user specified any compat option themselves.
2
max-chunk and max-workers. However, as soon as backup is switched over
3
Thus, this block does not do anything and can be dropped.
3
to block-copy for the background copying process, we will need it to
4
keep 129 passing.
4
5
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
7
Message-Id: <20210120102043.28346-1-mreitz@redhat.com>
7
Message-id: 20191107163708.833192-8-mreitz@redhat.com
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
9
---
10
tests/qemu-iotests/050 | 4 ----
10
tests/qemu-iotests/129 | 7 ++++++-
11
1 file changed, 4 deletions(-)
11
1 file changed, 6 insertions(+), 1 deletion(-)
12
12
13
diff --git a/tests/qemu-iotests/050 b/tests/qemu-iotests/050
13
diff --git a/tests/qemu-iotests/129 b/tests/qemu-iotests/129
14
index XXXXXXX..XXXXXXX 100755
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/050
15
--- a/tests/qemu-iotests/129
16
+++ b/tests/qemu-iotests/050
16
+++ b/tests/qemu-iotests/129
17
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
17
@@ -XXX,XX +XXX,XX @@ class TestStopWithBlockJob(iotests.QMPTestCase):
18
_supported_fmt qcow2 qed
18
sync="full", buf_size=65536)
19
_supported_proto file
19
20
20
def test_drive_backup(self):
21
-if test "$IMGFMT" = qcow2 && test $IMGOPTS = ""; then
21
+ # Limit max-chunk and max-workers so that block-copy will not
22
- IMGOPTS=compat=1.1
22
+ # launch so many workers working on so much data each that
23
-fi
23
+ # stop's bdrv_drain_all() would finish the job
24
-
24
self.do_test_stop("drive-backup", device="drive0",
25
echo
25
target=self.target_img, format=iotests.imgfmt,
26
echo "== Creating images =="
26
- sync="full")
27
27
+ sync="full",
28
+ x_perf={ 'max-chunk': 65536,
29
+ 'max-workers': 8 })
30
31
def test_block_commit(self):
32
# Add overlay above the source node so that we actually use a
28
--
33
--
29
2.24.1
34
2.29.2
30
35
31
36
diff view generated by jsdifflib
1
Just rm will not delete external data files. Use _rm_test_img every
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
time we delete a test image.
3
2
4
(In the process, clean up the indentation of every _cleanup() this patch
3
The further change of moving backup to be a one block-copy call will
5
touches.)
4
make copying chunk-size and cluster-size two separate things. So, even
5
with 64k cluster sized qcow2 image, default chunk would be 1M.
6
185 test however assumes, that with speed limited to 64K, one iteration
7
would result in offset=64K. It will change, as first iteration would
8
result in offset=1M independently of speed.
6
9
7
((Also, use quotes consistently. I am happy to see unquoted instances
10
So, let's explicitly specify, what test wants: set max-chunk to 64K, so
8
like "rm -rf $TEST_DIR/..." go.))
11
that one iteration is 64K. Note, that we don't need to limit
12
max-workers, as block-copy rate limiter will handle the situation and
13
wouldn't start new workers when speed limit is obviously reached.
9
14
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-id: 20191107163708.833192-16-mreitz@redhat.com
17
Message-Id: <20210116214705.822267-13-vsementsov@virtuozzo.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
19
---
15
tests/qemu-iotests/019 | 6 +++---
20
tests/qemu-iotests/185 | 3 ++-
16
tests/qemu-iotests/020 | 6 +++---
21
tests/qemu-iotests/185.out | 3 ++-
17
tests/qemu-iotests/024 | 10 +++++-----
22
2 files changed, 4 insertions(+), 2 deletions(-)
18
tests/qemu-iotests/028 | 2 +-
19
tests/qemu-iotests/029 | 2 +-
20
tests/qemu-iotests/043 | 4 +++-
21
tests/qemu-iotests/048 | 2 +-
22
tests/qemu-iotests/050 | 4 ++--
23
tests/qemu-iotests/053 | 4 ++--
24
tests/qemu-iotests/058 | 2 +-
25
tests/qemu-iotests/059 | 2 +-
26
tests/qemu-iotests/061 | 2 +-
27
tests/qemu-iotests/063 | 6 ++++--
28
tests/qemu-iotests/069 | 2 +-
29
tests/qemu-iotests/074 | 2 +-
30
tests/qemu-iotests/080 | 2 +-
31
tests/qemu-iotests/081 | 6 +++---
32
tests/qemu-iotests/085 | 9 ++++++---
33
tests/qemu-iotests/088 | 2 +-
34
tests/qemu-iotests/092 | 2 +-
35
tests/qemu-iotests/094 | 2 +-
36
tests/qemu-iotests/095 | 5 +++--
37
tests/qemu-iotests/099 | 7 ++++---
38
tests/qemu-iotests/109 | 4 ++--
39
tests/qemu-iotests/110 | 4 ++--
40
tests/qemu-iotests/122 | 6 ++++--
41
tests/qemu-iotests/123 | 2 +-
42
tests/qemu-iotests/141 | 4 +++-
43
tests/qemu-iotests/142 | 2 +-
44
tests/qemu-iotests/144 | 4 +++-
45
tests/qemu-iotests/153 | 10 +++-------
46
tests/qemu-iotests/156 | 8 ++++++--
47
tests/qemu-iotests/159 | 2 +-
48
tests/qemu-iotests/160 | 3 ++-
49
tests/qemu-iotests/161 | 4 ++--
50
tests/qemu-iotests/170 | 2 +-
51
tests/qemu-iotests/172 | 6 +++---
52
tests/qemu-iotests/173 | 3 ++-
53
tests/qemu-iotests/178 | 2 +-
54
tests/qemu-iotests/182 | 2 +-
55
tests/qemu-iotests/183 | 2 +-
56
tests/qemu-iotests/185 | 4 ++--
57
tests/qemu-iotests/187 | 6 +++---
58
tests/qemu-iotests/190 | 2 +-
59
tests/qemu-iotests/191 | 6 +++---
60
tests/qemu-iotests/195 | 2 +-
61
tests/qemu-iotests/197 | 2 +-
62
tests/qemu-iotests/200 | 3 ++-
63
tests/qemu-iotests/215 | 2 +-
64
tests/qemu-iotests/225 | 2 +-
65
tests/qemu-iotests/229 | 3 ++-
66
tests/qemu-iotests/232 | 4 +++-
67
tests/qemu-iotests/243 | 2 +-
68
tests/qemu-iotests/244 | 4 ++--
69
tests/qemu-iotests/247 | 4 +++-
70
tests/qemu-iotests/249 | 4 ++--
71
tests/qemu-iotests/252 | 2 +-
72
57 files changed, 118 insertions(+), 95 deletions(-)
73
23
74
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
75
index XXXXXXX..XXXXXXX 100755
76
--- a/tests/qemu-iotests/019
77
+++ b/tests/qemu-iotests/019
78
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
79
80
_cleanup()
81
{
82
-    _cleanup_test_img
83
- rm -f "$TEST_IMG.base"
84
- rm -f "$TEST_IMG.orig"
85
+ _cleanup_test_img
86
+ _rm_test_img "$TEST_IMG.base"
87
+ _rm_test_img "$TEST_IMG.orig"
88
}
89
trap "_cleanup; exit \$status" 0 1 2 3 15
90
91
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
92
index XXXXXXX..XXXXXXX 100755
93
--- a/tests/qemu-iotests/020
94
+++ b/tests/qemu-iotests/020
95
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
96
97
_cleanup()
98
{
99
-    _cleanup_test_img
100
- rm -f "$TEST_IMG.base"
101
- rm -f "$TEST_IMG.orig"
102
+ _cleanup_test_img
103
+ _rm_test_img "$TEST_IMG.base"
104
+ _rm_test_img "$TEST_IMG.orig"
105
}
106
trap "_cleanup; exit \$status" 0 1 2 3 15
107
108
diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
109
index XXXXXXX..XXXXXXX 100755
110
--- a/tests/qemu-iotests/024
111
+++ b/tests/qemu-iotests/024
112
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
113
_cleanup()
114
{
115
_cleanup_test_img
116
- rm -f "$TEST_DIR/t.$IMGFMT.base_old"
117
- rm -f "$TEST_DIR/t.$IMGFMT.base_new"
118
+ _rm_test_img "$TEST_DIR/t.$IMGFMT.base_old"
119
+ _rm_test_img "$TEST_DIR/t.$IMGFMT.base_new"
120
121
- rm -f "$TEST_DIR/subdir/t.$IMGFMT"
122
- rm -f "$TEST_DIR/subdir/t.$IMGFMT.base_old"
123
- rm -f "$TEST_DIR/subdir/t.$IMGFMT.base_new"
124
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT"
125
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base_old"
126
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base_new"
127
rmdir "$TEST_DIR/subdir" 2> /dev/null
128
}
129
trap "_cleanup; exit \$status" 0 1 2 3 15
130
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
131
index XXXXXXX..XXXXXXX 100755
132
--- a/tests/qemu-iotests/028
133
+++ b/tests/qemu-iotests/028
134
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
135
_cleanup()
136
{
137
_cleanup_qemu
138
- rm -f "${TEST_IMG}.copy"
139
+ _rm_test_img "${TEST_IMG}.copy"
140
_cleanup_test_img
141
}
142
trap "_cleanup; exit \$status" 0 1 2 3 15
143
diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029
144
index XXXXXXX..XXXXXXX 100755
145
--- a/tests/qemu-iotests/029
146
+++ b/tests/qemu-iotests/029
147
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
148
149
_cleanup()
150
{
151
- rm -f $TEST_IMG.snap
152
+ _rm_test_img "$TEST_IMG.snap"
153
_cleanup_test_img
154
}
155
trap "_cleanup; exit \$status" 0 1 2 3 15
156
diff --git a/tests/qemu-iotests/043 b/tests/qemu-iotests/043
157
index XXXXXXX..XXXXXXX 100755
158
--- a/tests/qemu-iotests/043
159
+++ b/tests/qemu-iotests/043
160
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
161
_cleanup()
162
{
163
_cleanup_test_img
164
- rm -f "$TEST_IMG".[123].base
165
+ for img in "$TEST_IMG".[123].base; do
166
+ _rm_test_img "$img"
167
+ done
168
}
169
trap "_cleanup; exit \$status" 0 1 2 3 15
170
171
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
172
index XXXXXXX..XXXXXXX 100755
173
--- a/tests/qemu-iotests/048
174
+++ b/tests/qemu-iotests/048
175
@@ -XXX,XX +XXX,XX @@ _cleanup()
176
{
177
echo "Cleanup"
178
_cleanup_test_img
179
- rm "${TEST_IMG_FILE2}"
180
+ _rm_test_img "${TEST_IMG_FILE2}"
181
}
182
trap "_cleanup; exit \$status" 0 1 2 3 15
183
184
diff --git a/tests/qemu-iotests/050 b/tests/qemu-iotests/050
185
index XXXXXXX..XXXXXXX 100755
186
--- a/tests/qemu-iotests/050
187
+++ b/tests/qemu-iotests/050
188
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
189
_cleanup()
190
{
191
_cleanup_test_img
192
- rm -f "$TEST_IMG.old"
193
- rm -f "$TEST_IMG.new"
194
+ _rm_test_img "$TEST_IMG.old"
195
+ _rm_test_img "$TEST_IMG.new"
196
}
197
trap "_cleanup; exit \$status" 0 1 2 3 15
198
199
diff --git a/tests/qemu-iotests/053 b/tests/qemu-iotests/053
200
index XXXXXXX..XXXXXXX 100755
201
--- a/tests/qemu-iotests/053
202
+++ b/tests/qemu-iotests/053
203
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
204
205
_cleanup()
206
{
207
-    rm -f "$TEST_IMG.orig"
208
-    _cleanup_test_img
209
+ _rm_test_img "$TEST_IMG.orig"
210
+ _cleanup_test_img
211
}
212
trap "_cleanup; exit \$status" 0 1 2 3 15
213
214
diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058
215
index XXXXXXX..XXXXXXX 100755
216
--- a/tests/qemu-iotests/058
217
+++ b/tests/qemu-iotests/058
218
@@ -XXX,XX +XXX,XX @@ _cleanup()
219
{
220
nbd_server_stop
221
_cleanup_test_img
222
- rm -f "$converted_image"
223
+ _rm_test_img "$converted_image"
224
}
225
trap "_cleanup; exit \$status" 0 1 2 3 15
226
227
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
228
index XXXXXXX..XXXXXXX 100755
229
--- a/tests/qemu-iotests/059
230
+++ b/tests/qemu-iotests/059
231
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
232
_cleanup()
233
{
234
_cleanup_test_img
235
- rm -f "$TEST_IMG.qcow2"
236
+ IMGFMT=qcow2 _rm_test_img "$TEST_IMG.qcow2"
237
}
238
trap "_cleanup; exit \$status" 0 1 2 3 15
239
240
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
241
index XXXXXXX..XXXXXXX 100755
242
--- a/tests/qemu-iotests/061
243
+++ b/tests/qemu-iotests/061
244
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
245
_cleanup()
246
{
247
_cleanup_test_img
248
- rm -f $TEST_IMG.data
249
+ _rm_test_img "$TEST_IMG.data"
250
}
251
trap "_cleanup; exit \$status" 0 1 2 3 15
252
253
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
254
index XXXXXXX..XXXXXXX 100755
255
--- a/tests/qemu-iotests/063
256
+++ b/tests/qemu-iotests/063
257
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
258
259
_cleanup()
260
{
261
-    _cleanup_test_img
262
-    rm -f "$TEST_IMG.orig" "$TEST_IMG.raw1" "$TEST_IMG.raw2"
263
+ _cleanup_test_img
264
+ for img in "$TEST_IMG".{orig,raw1,raw2,target}; do
265
+ _rm_test_img "$img"
266
+ done
267
}
268
trap "_cleanup; exit \$status" 0 1 2 3 15
269
270
diff --git a/tests/qemu-iotests/069 b/tests/qemu-iotests/069
271
index XXXXXXX..XXXXXXX 100755
272
--- a/tests/qemu-iotests/069
273
+++ b/tests/qemu-iotests/069
274
@@ -XXX,XX +XXX,XX @@ echo "=== Creating an image with a backing file and deleting that file ==="
275
echo
276
TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE
277
_make_test_img -b "$TEST_IMG.base" $IMG_SIZE
278
-rm -f "$TEST_IMG.base"
279
+_rm_test_img "$TEST_IMG.base"
280
# Just open the image and close it right again (this should print an error message)
281
$QEMU_IO -c quit "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
282
283
diff --git a/tests/qemu-iotests/074 b/tests/qemu-iotests/074
284
index XXXXXXX..XXXXXXX 100755
285
--- a/tests/qemu-iotests/074
286
+++ b/tests/qemu-iotests/074
287
@@ -XXX,XX +XXX,XX @@ _cleanup()
288
{
289
echo "Cleanup"
290
_cleanup_test_img
291
- rm "${TEST_IMG2}"
292
+ _rm_test_img "${TEST_IMG2}"
293
rm -f "$TEST_DIR/blkdebug.conf"
294
}
295
trap "_cleanup; exit \$status" 0 1 2 3 15
296
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
297
index XXXXXXX..XXXXXXX 100755
298
--- a/tests/qemu-iotests/080
299
+++ b/tests/qemu-iotests/080
300
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
301
302
_cleanup()
303
{
304
- rm -f $TEST_IMG.snap
305
+ _rm_test_img "$TEST_IMG.snap"
306
_cleanup_test_img
307
}
308
trap "_cleanup; exit \$status" 0 1 2 3 15
309
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
310
index XXXXXXX..XXXXXXX 100755
311
--- a/tests/qemu-iotests/081
312
+++ b/tests/qemu-iotests/081
313
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
314
315
_cleanup()
316
{
317
- rm -rf $TEST_DIR/1.raw
318
- rm -rf $TEST_DIR/2.raw
319
- rm -rf $TEST_DIR/3.raw
320
+ _rm_test_img "$TEST_DIR/1.raw"
321
+ _rm_test_img "$TEST_DIR/2.raw"
322
+ _rm_test_img "$TEST_DIR/3.raw"
323
}
324
trap "_cleanup; exit \$status" 0 1 2 3 15
325
326
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
327
index XXXXXXX..XXXXXXX 100755
328
--- a/tests/qemu-iotests/085
329
+++ b/tests/qemu-iotests/085
330
@@ -XXX,XX +XXX,XX @@ _cleanup()
331
_cleanup_qemu
332
for i in $(seq 1 ${SNAPSHOTS})
333
do
334
- rm -f "${TEST_DIR}/${i}-${snapshot_virt0}"
335
- rm -f "${TEST_DIR}/${i}-${snapshot_virt1}"
336
+ _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt0}"
337
+ _rm_test_img "${TEST_DIR}/${i}-${snapshot_virt1}"
338
+ done
339
+ for img in "${TEST_IMG}".{1,2,base}
340
+ do
341
+ _rm_test_img "$img"
342
done
343
- rm -f "${TEST_IMG}" "${TEST_IMG}.1" "${TEST_IMG}.2" "${TEST_IMG}.base"
344
345
}
346
trap "_cleanup; exit \$status" 0 1 2 3 15
347
diff --git a/tests/qemu-iotests/088 b/tests/qemu-iotests/088
348
index XXXXXXX..XXXXXXX 100755
349
--- a/tests/qemu-iotests/088
350
+++ b/tests/qemu-iotests/088
351
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
352
353
_cleanup()
354
{
355
- rm -f $TEST_IMG.snap
356
+ _rm_test_img "$TEST_IMG.snap"
357
_cleanup_test_img
358
}
359
trap "_cleanup; exit \$status" 0 1 2 3 15
360
diff --git a/tests/qemu-iotests/092 b/tests/qemu-iotests/092
361
index XXXXXXX..XXXXXXX 100755
362
--- a/tests/qemu-iotests/092
363
+++ b/tests/qemu-iotests/092
364
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
365
366
_cleanup()
367
{
368
- rm -f $TEST_IMG.snap
369
+ _rm_test_img "$TEST_IMG.snap"
370
_cleanup_test_img
371
}
372
trap "_cleanup; exit \$status" 0 1 2 3 15
373
diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
374
index XXXXXXX..XXXXXXX 100755
375
--- a/tests/qemu-iotests/094
376
+++ b/tests/qemu-iotests/094
377
@@ -XXX,XX +XXX,XX @@ _cleanup()
378
{
379
_cleanup_qemu
380
_cleanup_test_img
381
- rm -f "$TEST_DIR/source.$IMGFMT"
382
+ _rm_test_img "$TEST_DIR/source.$IMGFMT"
383
}
384
385
trap "_cleanup; exit \$status" 0 1 2 3 15
386
diff --git a/tests/qemu-iotests/095 b/tests/qemu-iotests/095
387
index XXXXXXX..XXXXXXX 100755
388
--- a/tests/qemu-iotests/095
389
+++ b/tests/qemu-iotests/095
390
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
391
_cleanup()
392
{
393
_cleanup_qemu
394
- rm -f "${TEST_IMG}.base" "${TEST_IMG}.snp1"
395
-    _cleanup_test_img
396
+ _rm_test_img "${TEST_IMG}.base"
397
+ _rm_test_img "${TEST_IMG}.snp1"
398
+ _cleanup_test_img
399
}
400
trap "_cleanup; exit \$status" 0 1 2 3 15
401
402
diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099
403
index XXXXXXX..XXXXXXX 100755
404
--- a/tests/qemu-iotests/099
405
+++ b/tests/qemu-iotests/099
406
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
407
408
_cleanup()
409
{
410
-    _cleanup_test_img
411
+ _cleanup_test_img
412
+ _rm_test_img "$TEST_IMG.compare"
413
+ rm -f "$TEST_DIR/blkdebug.conf"
414
+
415
}
416
trap "_cleanup; exit \$status" 0 1 2 3 15
417
418
@@ -XXX,XX +XXX,XX @@ echo
419
test_qemu "file.driver=blkdebug,file.image.filename=$TEST_IMG"
420
421
422
-rm -f "$TEST_IMG.compare" "$TEST_DIR/blkdebug.conf"
423
-
424
# success, all done
425
echo "*** done"
426
rm -f $seq.full
427
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
428
index XXXXXXX..XXXXXXX 100755
429
--- a/tests/qemu-iotests/109
430
+++ b/tests/qemu-iotests/109
431
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
432
_cleanup()
433
{
434
_cleanup_qemu
435
- rm -f $TEST_IMG.src
436
-    _cleanup_test_img
437
+ _rm_test_img "$TEST_IMG.src"
438
+ _cleanup_test_img
439
}
440
trap "_cleanup; exit \$status" 0 1 2 3 15
441
442
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
443
index XXXXXXX..XXXXXXX 100755
444
--- a/tests/qemu-iotests/110
445
+++ b/tests/qemu-iotests/110
446
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
447
448
_cleanup()
449
{
450
-    _cleanup_test_img
451
- rm -f "$TEST_IMG.copy"
452
+ _cleanup_test_img
453
+ _rm_test_img "$TEST_IMG.copy"
454
}
455
trap "_cleanup; exit \$status" 0 1 2 3 15
456
457
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
458
index XXXXXXX..XXXXXXX 100755
459
--- a/tests/qemu-iotests/122
460
+++ b/tests/qemu-iotests/122
461
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
462
463
_cleanup()
464
{
465
- rm -f "$TEST_IMG".[123]
466
-    _cleanup_test_img
467
+ for img in "$TEST_IMG".[123]; do
468
+ _rm_test_img "$img"
469
+ done
470
+ _cleanup_test_img
471
}
472
trap "_cleanup; exit \$status" 0 1 2 3 15
473
474
diff --git a/tests/qemu-iotests/123 b/tests/qemu-iotests/123
475
index XXXXXXX..XXXXXXX 100755
476
--- a/tests/qemu-iotests/123
477
+++ b/tests/qemu-iotests/123
478
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
479
_cleanup()
480
{
481
_cleanup_test_img
482
- rm -f "$SRC_IMG"
483
+ _rm_test_img "$SRC_IMG"
484
}
485
trap "_cleanup; exit \$status" 0 1 2 3 15
486
487
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
488
index XXXXXXX..XXXXXXX 100755
489
--- a/tests/qemu-iotests/141
490
+++ b/tests/qemu-iotests/141
491
@@ -XXX,XX +XXX,XX @@ _cleanup()
492
{
493
_cleanup_qemu
494
_cleanup_test_img
495
- rm -f "$TEST_DIR"/{b,m,o}.$IMGFMT
496
+ for img in "$TEST_DIR"/{b,m,o}.$IMGFMT; do
497
+ _rm_test_img "$img"
498
+ done
499
}
500
trap "_cleanup; exit \$status" 0 1 2 3 15
501
502
diff --git a/tests/qemu-iotests/142 b/tests/qemu-iotests/142
503
index XXXXXXX..XXXXXXX 100755
504
--- a/tests/qemu-iotests/142
505
+++ b/tests/qemu-iotests/142
506
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
507
_cleanup()
508
{
509
_cleanup_test_img
510
- rm -f $TEST_IMG.snap
511
+ _rm_test_img "$TEST_IMG.snap"
512
}
513
trap "_cleanup; exit \$status" 0 1 2 3 15
514
515
diff --git a/tests/qemu-iotests/144 b/tests/qemu-iotests/144
516
index XXXXXXX..XXXXXXX 100755
517
--- a/tests/qemu-iotests/144
518
+++ b/tests/qemu-iotests/144
519
@@ -XXX,XX +XXX,XX @@ TMP_SNAP2=${TEST_DIR}/tmp2.qcow2
520
_cleanup()
521
{
522
_cleanup_qemu
523
- rm -f "${TEST_IMG}" "${TMP_SNAP1}" "${TMP_SNAP2}"
524
+ for img in "${TEST_IMG}" "${TMP_SNAP1}" "${TMP_SNAP2}"; do
525
+ _rm_test_img "$img"
526
+ done
527
}
528
529
trap "_cleanup; exit \$status" 0 1 2 3 15
530
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
531
index XXXXXXX..XXXXXXX 100755
532
--- a/tests/qemu-iotests/153
533
+++ b/tests/qemu-iotests/153
534
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
535
_cleanup()
536
{
537
_cleanup_test_img
538
- rm -f "${TEST_IMG}.base"
539
- rm -f "${TEST_IMG}.overlay"
540
- rm -f "${TEST_IMG}.convert"
541
- rm -f "${TEST_IMG}.a"
542
- rm -f "${TEST_IMG}.b"
543
- rm -f "${TEST_IMG}.c"
544
- rm -f "${TEST_IMG}.lnk"
545
+ for img in "${TEST_IMG}".{base,overlay,convert,a,b,c,lnk}; do
546
+ _rm_test_img "$img"
547
+ done
548
}
549
trap "_cleanup; exit \$status" 0 1 2 3 15
550
551
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
552
index XXXXXXX..XXXXXXX 100755
553
--- a/tests/qemu-iotests/156
554
+++ b/tests/qemu-iotests/156
555
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
556
_cleanup()
557
{
558
_cleanup_qemu
559
- rm -f "$TEST_IMG"{,.target}{,.backing,.overlay}
560
+ for img in "$TEST_IMG"{,.target}{,.backing,.overlay}; do
561
+ _rm_test_img "$img"
562
+ done
563
}
564
trap "_cleanup; exit \$status" 0 1 2 3 15
565
566
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
567
'"status": "null"'
568
569
# Remove the source images
570
-rm -f "$TEST_IMG{,.backing,.overlay}"
571
+for img in "$TEST_IMG{,.backing,.overlay}"; do
572
+ _rm_test_img "$img"
573
+done
574
575
echo
576
577
diff --git a/tests/qemu-iotests/159 b/tests/qemu-iotests/159
578
index XXXXXXX..XXXXXXX 100755
579
--- a/tests/qemu-iotests/159
580
+++ b/tests/qemu-iotests/159
581
@@ -XXX,XX +XXX,XX @@ status=1
582
_cleanup()
583
{
584
_cleanup_test_img
585
- rm -f "$TEST_IMG.out"
586
+ _rm_test_img "$TEST_IMG.out"
587
}
588
trap "_cleanup; exit \$status" 0 1 2 3 15
589
590
diff --git a/tests/qemu-iotests/160 b/tests/qemu-iotests/160
591
index XXXXXXX..XXXXXXX 100755
592
--- a/tests/qemu-iotests/160
593
+++ b/tests/qemu-iotests/160
594
@@ -XXX,XX +XXX,XX @@ status=1
595
_cleanup()
596
{
597
_cleanup_test_img
598
- rm -f "$TEST_IMG.out" "$TEST_IMG.out.dd"
599
+ _rm_test_img "$TEST_IMG.out"
600
+ _rm_test_img "$TEST_IMG.out.dd"
601
}
602
trap "_cleanup; exit \$status" 0 1 2 3 15
603
604
diff --git a/tests/qemu-iotests/161 b/tests/qemu-iotests/161
605
index XXXXXXX..XXXXXXX 100755
606
--- a/tests/qemu-iotests/161
607
+++ b/tests/qemu-iotests/161
608
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
609
_cleanup()
610
{
611
_cleanup_test_img
612
- rm -f "$TEST_IMG.base"
613
- rm -f "$TEST_IMG.int"
614
+ _rm_test_img "$TEST_IMG.base"
615
+ _rm_test_img "$TEST_IMG.int"
616
}
617
trap "_cleanup; exit \$status" 0 1 2 3 15
618
619
diff --git a/tests/qemu-iotests/170 b/tests/qemu-iotests/170
620
index XXXXXXX..XXXXXXX 100755
621
--- a/tests/qemu-iotests/170
622
+++ b/tests/qemu-iotests/170
623
@@ -XXX,XX +XXX,XX @@ status=1
624
_cleanup()
625
{
626
_cleanup_test_img
627
- rm -f "$TEST_IMG.out"
628
+ _rm_test_img "$TEST_IMG.out"
629
}
630
trap "_cleanup; exit \$status" 0 1 2 3 15
631
632
diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172
633
index XXXXXXX..XXXXXXX 100755
634
--- a/tests/qemu-iotests/172
635
+++ b/tests/qemu-iotests/172
636
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
637
638
_cleanup()
639
{
640
-    _cleanup_test_img
641
- rm -f "$TEST_IMG.2"
642
- rm -f "$TEST_IMG.3"
643
+ _cleanup_test_img
644
+ _rm_test_img "$TEST_IMG.2"
645
+ _rm_test_img "$TEST_IMG.3"
646
}
647
trap "_cleanup; exit \$status" 0 1 2 3 15
648
649
diff --git a/tests/qemu-iotests/173 b/tests/qemu-iotests/173
650
index XXXXXXX..XXXXXXX 100755
651
--- a/tests/qemu-iotests/173
652
+++ b/tests/qemu-iotests/173
653
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
654
_cleanup()
655
{
656
_cleanup_qemu
657
- rm -f "${QEMU_TEST_DIR}/image.base" "${QEMU_TEST_DIR}/image.snp1"
658
+ _rm_test_img "${TEST_DIR}/image.base"
659
+ _rm_test_img "${TEST_DIR}/image.snp1"
660
_cleanup_test_img
661
}
662
trap "_cleanup; exit \$status" 0 1 2 3 15
663
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
664
index XXXXXXX..XXXXXXX 100755
665
--- a/tests/qemu-iotests/178
666
+++ b/tests/qemu-iotests/178
667
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
668
_cleanup()
669
{
670
_cleanup_test_img
671
- rm -f "$TEST_IMG.converted"
672
+ _rm_test_img "$TEST_IMG.converted"
673
}
674
trap "_cleanup; exit \$status" 0 1 2 3 15
675
676
diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182
677
index XXXXXXX..XXXXXXX 100755
678
--- a/tests/qemu-iotests/182
679
+++ b/tests/qemu-iotests/182
680
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
681
_cleanup()
682
{
683
_cleanup_test_img
684
- rm -f "$TEST_IMG.overlay"
685
+ _rm_test_img "$TEST_IMG.overlay"
686
rm -f "$SOCK_DIR/nbd.socket"
687
}
688
trap "_cleanup; exit \$status" 0 1 2 3 15
689
diff --git a/tests/qemu-iotests/183 b/tests/qemu-iotests/183
690
index XXXXXXX..XXXXXXX 100755
691
--- a/tests/qemu-iotests/183
692
+++ b/tests/qemu-iotests/183
693
@@ -XXX,XX +XXX,XX @@ MIG_SOCKET="${SOCK_DIR}/migrate"
694
_cleanup()
695
{
696
rm -f "${MIG_SOCKET}"
697
- rm -f "${TEST_IMG}.dest"
698
+ _rm_test_img "${TEST_IMG}.dest"
699
_cleanup_test_img
700
_cleanup_qemu
701
}
702
diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185
24
diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185
703
index XXXXXXX..XXXXXXX 100755
25
index XXXXXXX..XXXXXXX 100755
704
--- a/tests/qemu-iotests/185
26
--- a/tests/qemu-iotests/185
705
+++ b/tests/qemu-iotests/185
27
+++ b/tests/qemu-iotests/185
706
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
28
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $h \
707
29
'target': '$TEST_IMG.copy',
708
_cleanup()
30
'format': '$IMGFMT',
709
{
31
'sync': 'full',
710
- rm -f "${TEST_IMG}.mid"
32
- 'speed': 65536 } }" \
711
- rm -f "${TEST_IMG}.copy"
33
+ 'speed': 65536,
712
+ _rm_test_img "${TEST_IMG}.mid"
34
+ 'x-perf': {'max-chunk': 65536} } }" \
713
+ _rm_test_img "${TEST_IMG}.copy"
35
"return"
714
_cleanup_test_img
36
715
_cleanup_qemu
37
# If we don't sleep here 'quit' command races with disk I/O
716
}
38
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
717
diff --git a/tests/qemu-iotests/187 b/tests/qemu-iotests/187
39
index XXXXXXX..XXXXXXX 100644
718
index XXXXXXX..XXXXXXX 100755
40
--- a/tests/qemu-iotests/185.out
719
--- a/tests/qemu-iotests/187
41
+++ b/tests/qemu-iotests/185.out
720
+++ b/tests/qemu-iotests/187
42
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off
721
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
43
'target': 'TEST_DIR/t.IMGFMT.copy',
722
44
'format': 'IMGFMT',
723
_cleanup()
45
'sync': 'full',
724
{
46
- 'speed': 65536 } }
725
-    _cleanup_test_img
47
+ 'speed': 65536,
726
- rm -f "$TEST_IMG.2"
48
+ 'x-perf': { 'max-chunk': 65536 } } }
727
- rm -f "$TEST_IMG.3"
49
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
728
+ _cleanup_test_img
50
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
729
+ _rm_test_img "$TEST_IMG.2"
51
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
730
+ _rm_test_img "$TEST_IMG.3"
731
}
732
trap "_cleanup; exit \$status" 0 1 2 3 15
733
734
diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190
735
index XXXXXXX..XXXXXXX 100755
736
--- a/tests/qemu-iotests/190
737
+++ b/tests/qemu-iotests/190
738
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
739
_cleanup()
740
{
741
_cleanup_test_img
742
- rm -f "$TEST_IMG.converted"
743
+ _rm_test_img "$TEST_IMG.converted"
744
}
745
trap "_cleanup; exit \$status" 0 1 2 3 15
746
747
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
748
index XXXXXXX..XXXXXXX 100755
749
--- a/tests/qemu-iotests/191
750
+++ b/tests/qemu-iotests/191
751
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
752
753
_cleanup()
754
{
755
- rm -f "${TEST_IMG}.mid"
756
- rm -f "${TEST_IMG}.ovl2"
757
- rm -f "${TEST_IMG}.ovl3"
758
+ _rm_test_img "${TEST_IMG}.mid"
759
+ _rm_test_img "${TEST_IMG}.ovl2"
760
+ _rm_test_img "${TEST_IMG}.ovl3"
761
_cleanup_test_img
762
_cleanup_qemu
763
}
764
diff --git a/tests/qemu-iotests/195 b/tests/qemu-iotests/195
765
index XXXXXXX..XXXXXXX 100755
766
--- a/tests/qemu-iotests/195
767
+++ b/tests/qemu-iotests/195
768
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
769
_cleanup()
770
{
771
_cleanup_test_img
772
- rm -f "$TEST_IMG.mid"
773
+ _rm_test_img "$TEST_IMG.mid"
774
}
775
trap "_cleanup; exit \$status" 0 1 2 3 15
776
777
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
778
index XXXXXXX..XXXXXXX 100755
779
--- a/tests/qemu-iotests/197
780
+++ b/tests/qemu-iotests/197
781
@@ -XXX,XX +XXX,XX @@ esac
782
_cleanup()
783
{
784
_cleanup_test_img
785
- rm -f "$TEST_WRAP"
786
+ _rm_test_img "$TEST_WRAP"
787
rm -f "$BLKDBG_CONF"
788
}
789
trap "_cleanup; exit \$status" 0 1 2 3 15
790
diff --git a/tests/qemu-iotests/200 b/tests/qemu-iotests/200
791
index XXXXXXX..XXXXXXX 100755
792
--- a/tests/qemu-iotests/200
793
+++ b/tests/qemu-iotests/200
794
@@ -XXX,XX +XXX,XX @@ status=1 # failure is the default!
795
_cleanup()
796
{
797
_cleanup_qemu
798
- rm -f "${TEST_IMG}" "${BACKING_IMG}"
799
+ _rm_test_img "${TEST_IMG}"
800
+ _rm_test_img "${BACKING_IMG}"
801
}
802
trap "_cleanup; exit \$status" 0 1 2 3 15
803
804
diff --git a/tests/qemu-iotests/215 b/tests/qemu-iotests/215
805
index XXXXXXX..XXXXXXX 100755
806
--- a/tests/qemu-iotests/215
807
+++ b/tests/qemu-iotests/215
808
@@ -XXX,XX +XXX,XX @@ esac
809
_cleanup()
810
{
811
_cleanup_test_img
812
- rm -f "$TEST_WRAP"
813
+ _rm_test_img "$TEST_WRAP"
814
rm -f "$BLKDBG_CONF"
815
}
816
trap "_cleanup; exit \$status" 0 1 2 3 15
817
diff --git a/tests/qemu-iotests/225 b/tests/qemu-iotests/225
818
index XXXXXXX..XXXXXXX 100755
819
--- a/tests/qemu-iotests/225
820
+++ b/tests/qemu-iotests/225
821
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
822
_cleanup()
823
{
824
_cleanup_test_img
825
- rm -f "$TEST_IMG.not_base"
826
+ _rm_test_img "$TEST_IMG.not_base"
827
}
828
trap "_cleanup; exit \$status" 0 1 2 3 15
829
830
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
831
index XXXXXXX..XXXXXXX 100755
832
--- a/tests/qemu-iotests/229
833
+++ b/tests/qemu-iotests/229
834
@@ -XXX,XX +XXX,XX @@ _cleanup()
835
{
836
_cleanup_qemu
837
_cleanup_test_img
838
- rm -f "$TEST_IMG" "$DEST_IMG"
839
+ _rm_test_img "$TEST_IMG"
840
+ _rm_test_img "$DEST_IMG"
841
}
842
trap "_cleanup; exit \$status" 0 1 2 3 15
843
844
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
845
index XXXXXXX..XXXXXXX 100755
846
--- a/tests/qemu-iotests/232
847
+++ b/tests/qemu-iotests/232
848
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
849
_cleanup()
850
{
851
_cleanup_test_img
852
- rm -f $TEST_IMG.[01234]
853
+ for img in "$TEST_IMG".[01234]; do
854
+ _rm_test_img "$img"
855
+ done
856
}
857
trap "_cleanup; exit \$status" 0 1 2 3 15
858
859
diff --git a/tests/qemu-iotests/243 b/tests/qemu-iotests/243
860
index XXXXXXX..XXXXXXX 100755
861
--- a/tests/qemu-iotests/243
862
+++ b/tests/qemu-iotests/243
863
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
864
_cleanup()
865
{
866
_cleanup_test_img
867
- rm -f $TEST_IMG.data
868
+ _rm_test_img "$TEST_IMG.data"
869
}
870
trap "_cleanup; exit \$status" 0 1 2 3 15
871
872
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
873
index XXXXXXX..XXXXXXX 100755
874
--- a/tests/qemu-iotests/244
875
+++ b/tests/qemu-iotests/244
876
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
877
_cleanup()
878
{
879
_cleanup_test_img
880
- rm -f $TEST_IMG.data
881
- rm -f $TEST_IMG.src
882
+ _rm_test_img "$TEST_IMG.data"
883
+ _rm_test_img "$TEST_IMG.src"
884
}
885
trap "_cleanup; exit \$status" 0 1 2 3 15
886
887
diff --git a/tests/qemu-iotests/247 b/tests/qemu-iotests/247
888
index XXXXXXX..XXXXXXX 100755
889
--- a/tests/qemu-iotests/247
890
+++ b/tests/qemu-iotests/247
891
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
892
_cleanup()
893
{
894
_cleanup_test_img
895
- rm -f $TEST_IMG.[01234]
896
+ for img in "$TEST_IMG".[01234]; do
897
+ _rm_test_img "$img"
898
+ done
899
}
900
trap "_cleanup; exit \$status" 0 1 2 3 15
901
902
diff --git a/tests/qemu-iotests/249 b/tests/qemu-iotests/249
903
index XXXXXXX..XXXXXXX 100755
904
--- a/tests/qemu-iotests/249
905
+++ b/tests/qemu-iotests/249
906
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
907
_cleanup()
908
{
909
_cleanup_test_img
910
- rm -f "$TEST_IMG.base"
911
- rm -f "$TEST_IMG.int"
912
+ _rm_test_img "$TEST_IMG.base"
913
+ _rm_test_img "$TEST_IMG.int"
914
}
915
trap "_cleanup; exit \$status" 0 1 2 3 15
916
917
diff --git a/tests/qemu-iotests/252 b/tests/qemu-iotests/252
918
index XXXXXXX..XXXXXXX 100755
919
--- a/tests/qemu-iotests/252
920
+++ b/tests/qemu-iotests/252
921
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
922
_cleanup()
923
{
924
_cleanup_test_img
925
- rm -f "$TEST_IMG.base_new"
926
+ _rm_test_img "$TEST_IMG.base_new"
927
}
928
trap "_cleanup; exit \$status" 0 1 2 3 15
929
930
--
52
--
931
2.24.1
53
2.29.2
932
54
933
55
diff view generated by jsdifflib
1
This test can run just fine with other values for refcount_bits, so we
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
should filter the value from qcow2.py's dump-header. In fact, we can
3
filter everything but the feature bits and header extensions, because
4
that is what the test is about.
5
2
6
(036 currently ignores user-specified image options, but that will be
3
The further change of moving backup to be a one block-copy call will
7
fixed in the next patch.)
4
make copying chunk-size and cluster-size two separate things. So, even
5
with 64k cluster sized qcow2 image, default chunk would be 1M.
6
Test 219 depends on specified chunk-size. Update it for explicit
7
chunk-size for backup as for mirror.
8
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20191107163708.833192-6-mreitz@redhat.com
11
Message-Id: <20210116214705.822267-14-vsementsov@virtuozzo.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
13
---
14
tests/qemu-iotests/036 | 9 ++++---
14
tests/qemu-iotests/219 | 13 +++++++------
15
tests/qemu-iotests/036.out | 48 --------------------------------------
15
1 file changed, 7 insertions(+), 6 deletions(-)
16
2 files changed, 6 insertions(+), 51 deletions(-)
17
16
18
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
17
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
19
index XXXXXXX..XXXXXXX 100755
18
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/036
19
--- a/tests/qemu-iotests/219
21
+++ b/tests/qemu-iotests/036
20
+++ b/tests/qemu-iotests/219
22
@@ -XXX,XX +XXX,XX @@ $PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
21
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('disk.img') as disk_path, \
23
22
# but related to this also automatic state transitions like job
24
# Without feature table
23
# completion), but still get pause points often enough to avoid making this
25
$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
24
# test very slow, it's important to have the right ratio between speed and
26
-$PYTHON qcow2.py "$TEST_IMG" dump-header
25
- # buf_size.
27
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
26
+ # copy-chunk-size.
28
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
27
#
29
_img_info
28
- # For backup, buf_size is hard-coded to the source image cluster size (64k),
30
29
- # so we'll pick the same for mirror. The slice time, i.e. the granularity
31
# With feature table containing bit 63
30
- # of the rate limiting is 100ms. With a speed of 256k per second, we can
32
@@ -XXX,XX +XXX,XX @@ echo === Create image with unknown autoclear feature bit ===
31
- # get four pause points per second. This gives us 250ms per iteration,
33
echo
32
- # which should be enough to stay deterministic.
34
_make_test_img 64M
33
+ # Chose 64k copy-chunk-size both for mirror (by buf_size) and backup (by
35
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 63
34
+ # x-max-chunk). The slice time, i.e. the granularity of the rate limiting
36
-$PYTHON qcow2.py "$TEST_IMG" dump-header
35
+ # is 100ms. With a speed of 256k per second, we can get four pause points
37
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
36
+ # per second. This gives us 250ms per iteration, which should be enough to
38
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
37
+ # stay deterministic.
39
38
40
echo
39
test_job_lifecycle(vm, 'drive-mirror', has_ready=True, job_args={
41
echo === Repair image ===
40
'device': 'drive0-node',
42
echo
41
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('disk.img') as disk_path, \
43
_check_test_img -r all
42
'target': copy_path,
44
43
'sync': 'full',
45
-$PYTHON qcow2.py "$TEST_IMG" dump-header
44
'speed': 262144,
46
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep features
45
+ 'x-perf': {'max-chunk': 65536},
47
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
46
'auto-finalize': auto_finalize,
48
47
'auto-dismiss': auto_dismiss,
49
# success, all done
48
})
50
echo "*** done"
51
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/036.out
54
+++ b/tests/qemu-iotests/036.out
55
@@ -XXX,XX +XXX,XX @@ QA output created by 036
56
=== Image with unknown incompatible feature bit ===
57
58
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
59
-magic 0x514649fb
60
-version 3
61
-backing_file_offset 0x0
62
-backing_file_size 0x0
63
-cluster_bits 16
64
-size 67108864
65
-crypt_method 0
66
-l1_size 1
67
-l1_table_offset 0x30000
68
-refcount_table_offset 0x10000
69
-refcount_table_clusters 1
70
-nb_snapshots 0
71
-snapshot_offset 0x0
72
incompatible_features [63]
73
compatible_features []
74
autoclear_features []
75
-refcount_order 4
76
-header_length 104
77
-
78
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Unknown incompatible feature: 8000000000000000
79
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Test feature
80
81
@@ -XXX,XX +XXX,XX @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): tes
82
=== Create image with unknown autoclear feature bit ===
83
84
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
85
-magic 0x514649fb
86
-version 3
87
-backing_file_offset 0x0
88
-backing_file_size 0x0
89
-cluster_bits 16
90
-size 67108864
91
-crypt_method 0
92
-l1_size 1
93
-l1_table_offset 0x30000
94
-refcount_table_offset 0x10000
95
-refcount_table_clusters 1
96
-nb_snapshots 0
97
-snapshot_offset 0x0
98
incompatible_features []
99
compatible_features []
100
autoclear_features [63]
101
-refcount_order 4
102
-header_length 104
103
-
104
Header extension:
105
magic 0x6803f857
106
length 192
107
@@ -XXX,XX +XXX,XX @@ data <binary>
108
=== Repair image ===
109
110
No errors were found on the image.
111
-magic 0x514649fb
112
-version 3
113
-backing_file_offset 0x0
114
-backing_file_size 0x0
115
-cluster_bits 16
116
-size 67108864
117
-crypt_method 0
118
-l1_size 1
119
-l1_table_offset 0x30000
120
-refcount_table_offset 0x10000
121
-refcount_table_clusters 1
122
-nb_snapshots 0
123
-snapshot_offset 0x0
124
incompatible_features []
125
compatible_features []
126
autoclear_features []
127
-refcount_order 4
128
-header_length 104
129
-
130
Header extension:
131
magic 0x6803f857
132
length 192
133
--
49
--
134
2.24.1
50
2.29.2
135
51
136
52
diff view generated by jsdifflib
1
Some tests require compat=1.1 and thus set IMGOPTS='compat=1.1'
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
globally. That is not how it should be done; instead, they should
3
simply set _unsupported_imgopts to compat=0.10 (compat=1.1 is the
4
default anyway).
5
2
6
This makes the tests heed user-specified $IMGOPTS. Some do not work
3
Iotest 257 dumps a lot of in-progress information of backup job, such
7
with all image options, though, so we need to disable them accordingly.
4
as offset and bitmap dirtiness. Further commit will move backup to be
5
one block-copy call, which will introduce async parallel requests
6
instead of plain cluster-by-cluster copying. To keep things
7
deterministic, allow only one worker (only one copy request at a time)
8
for this test.
8
9
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Maxim Levitsky <mlevitsky@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20191107163708.833192-7-mreitz@redhat.com
12
Message-Id: <20210116214705.822267-15-vsementsov@virtuozzo.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
---
14
tests/qemu-iotests/036 | 3 +--
15
tests/qemu-iotests/257 | 1 +
15
tests/qemu-iotests/060 | 4 ++--
16
tests/qemu-iotests/257.out | 306 ++++++++++++++++++-------------------
16
tests/qemu-iotests/062 | 3 ++-
17
2 files changed, 154 insertions(+), 153 deletions(-)
17
tests/qemu-iotests/066 | 3 ++-
18
tests/qemu-iotests/068 | 3 ++-
19
tests/qemu-iotests/098 | 4 ++--
20
6 files changed, 11 insertions(+), 9 deletions(-)
21
18
22
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
19
diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257
23
index XXXXXXX..XXXXXXX 100755
20
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/036
21
--- a/tests/qemu-iotests/257
25
+++ b/tests/qemu-iotests/036
22
+++ b/tests/qemu-iotests/257
26
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
23
@@ -XXX,XX +XXX,XX @@ def blockdev_backup(vm, device, target, sync, **kwargs):
27
# This tests qcow2-specific low-level functionality
24
target=target,
28
_supported_fmt qcow2
25
sync=sync,
29
_supported_proto file
26
filter_node_name='backup-top',
30
-
27
+ x_perf={'max-workers': 1},
31
# Only qcow2v3 and later supports feature bits
28
**kwargs)
32
-IMGOPTS="compat=1.1"
29
return result
33
+_unsupported_imgopts 'compat=0.10'
30
34
31
diff --git a/tests/qemu-iotests/257.out b/tests/qemu-iotests/257.out
35
echo
32
index XXXXXXX..XXXXXXX 100644
36
echo === Image with unknown incompatible feature bit ===
33
--- a/tests/qemu-iotests/257.out
37
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
34
+++ b/tests/qemu-iotests/257.out
38
index XXXXXXX..XXXXXXX 100755
35
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
39
--- a/tests/qemu-iotests/060
36
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
40
+++ b/tests/qemu-iotests/060
37
{"return": {}}
41
@@ -XXX,XX +XXX,XX @@ _filter_io_error()
38
{}
42
_supported_fmt qcow2
39
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
43
_supported_proto file
40
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
44
_supported_os Linux
41
{"return": {}}
45
+# These tests only work for compat=1.1 images with refcount_bits=16
42
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
46
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
43
47
44
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
48
# The repair process will create a large file - so check for availability first
45
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
49
_require_large_file 64G
46
{"return": {}}
50
@@ -XXX,XX +XXX,XX @@ l1_offset=196608 # 0x30000 (XXX: just an assumption)
47
{}
51
l2_offset=262144 # 0x40000 (XXX: just an assumption)
48
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
52
l2_offset_after_snapshot=524288 # 0x80000 (XXX: just an assumption)
49
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
53
50
{"return": {}}
54
-IMGOPTS="compat=1.1"
51
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
55
-
52
56
OPEN_RW="open -o overlap-check=all $TEST_IMG"
53
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
57
# Overlap checks are done before write operations only, therefore opening an
54
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
58
# image read-only makes the overlap-check option irrelevant
55
{"return": {}}
59
diff --git a/tests/qemu-iotests/062 b/tests/qemu-iotests/062
56
{}
60
index XXXXXXX..XXXXXXX 100755
57
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
61
--- a/tests/qemu-iotests/062
58
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
62
+++ b/tests/qemu-iotests/062
59
{"return": {}}
63
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
60
64
# This tests qcow2-specific low-level functionality
61
--- Write #2 ---
65
_supported_fmt qcow2
62
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
66
_supported_proto generic
63
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
67
+# We need zero clusters and snapshots
64
{"return": {}}
68
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
65
{}
69
66
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
70
-IMGOPTS="compat=1.1"
67
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
71
IMG_SIZE=64M
68
{"return": {}}
72
69
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
73
echo
70
74
diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
71
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
75
index XXXXXXX..XXXXXXX 100755
72
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
76
--- a/tests/qemu-iotests/066
73
{"return": {}}
77
+++ b/tests/qemu-iotests/066
74
{}
78
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
75
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
79
# This tests qcow2-specific low-level functionality
76
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
80
_supported_fmt qcow2
77
{"return": {}}
81
_supported_proto generic
78
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
82
+# We need zero clusters and snapshots
79
{"return": {}}
83
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
80
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
84
81
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
85
# Intentionally create an unaligned image
82
{"return": {}}
86
-IMGOPTS="compat=1.1"
83
{}
87
IMG_SIZE=$((64 * 1024 * 1024 + 512))
84
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
88
85
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
89
echo
86
{"return": {}}
90
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
87
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
91
index XXXXXXX..XXXXXXX 100755
88
92
--- a/tests/qemu-iotests/068
89
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
93
+++ b/tests/qemu-iotests/068
90
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
94
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
91
{"return": {}}
95
# This tests qcow2-specific low-level functionality
92
{}
96
_supported_fmt qcow2
93
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
97
_supported_proto generic
94
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
98
+# Internal snapshots are (currently) impossible with refcount_bits=1
95
{"return": {}}
99
+_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]'
96
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
100
97
101
-IMGOPTS="compat=1.1"
98
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
102
IMG_SIZE=128K
99
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
103
100
{"return": {}}
104
case "$QEMU_DEFAULT_MACHINE" in
101
{}
105
diff --git a/tests/qemu-iotests/098 b/tests/qemu-iotests/098
102
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
106
index XXXXXXX..XXXXXXX 100755
103
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
107
--- a/tests/qemu-iotests/098
104
{"return": {}}
108
+++ b/tests/qemu-iotests/098
105
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
109
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
106
{"data": {"device": "backup_1", "error": "Input/output error", "len": 393216, "offset": 65536, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
110
107
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
111
_supported_fmt qcow2
108
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
112
_supported_proto file
109
{"return": {}}
113
-
110
{}
114
-IMGOPTS="compat=1.1"
111
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
115
+# The code path we want to test here only works for compat=1.1 images
112
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
116
+_unsupported_imgopts 'compat=0.10'
113
{"return": {}}
117
114
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
118
for event in l1_update empty_image_prepare reftable_update refblock_alloc; do
115
116
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
117
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
118
{"return": {}}
119
{}
120
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
121
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
122
{"return": {}}
123
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
124
{"return": {}}
125
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
126
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
127
{"return": {}}
128
{}
129
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
130
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
131
{"return": {}}
132
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
133
134
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
135
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
136
{"return": {}}
137
{}
138
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
139
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
140
{"return": {}}
141
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
142
143
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
144
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
145
{"return": {}}
146
{}
147
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
148
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
149
{"return": {}}
150
151
--- Write #2 ---
152
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
153
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
154
{"return": {}}
155
{}
156
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
157
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
158
{"return": {}}
159
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
160
161
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
162
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
163
{"return": {}}
164
{}
165
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
166
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
167
{"return": {}}
168
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
169
{"return": {}}
170
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
171
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
172
{"return": {}}
173
{}
174
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
175
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
176
{"return": {}}
177
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
178
179
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
180
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
181
{"return": {}}
182
{}
183
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
184
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
185
{"return": {}}
186
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
187
188
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
189
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
190
{"return": {}}
191
{}
192
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
193
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
194
{"return": {}}
195
196
--- Write #2 ---
197
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
198
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
199
{"return": {}}
200
{}
201
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
202
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
203
{"return": {}}
204
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
205
206
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
207
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
208
{"return": {}}
209
{}
210
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
211
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
212
{"return": {}}
213
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
214
{"return": {}}
215
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
216
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
217
{"return": {}}
218
{}
219
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
220
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
221
{"return": {}}
222
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
223
224
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
225
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
226
{"return": {}}
227
{}
228
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
229
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
230
{"return": {}}
231
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
232
233
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
234
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
235
{"return": {}}
236
{}
237
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
238
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
239
{"return": {}}
240
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
241
{"data": {"device": "backup_1", "error": "Input/output error", "len": 393216, "offset": 65536, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
242
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
243
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
244
{"return": {}}
245
{}
246
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
247
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
248
{"return": {}}
249
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
250
251
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
252
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
253
{"return": {}}
254
{}
255
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
256
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
257
{"return": {}}
258
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
259
{"return": {}}
260
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
261
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
262
{"return": {}}
263
{}
264
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
265
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
266
{"return": {}}
267
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
268
269
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
270
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
271
{"return": {}}
272
{}
273
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
274
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
275
{"return": {}}
276
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
277
278
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
279
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
280
{"return": {}}
281
{}
282
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
283
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
284
{"return": {}}
285
286
--- Write #2 ---
287
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
288
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
289
{"return": {}}
290
{}
291
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
292
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
293
{"return": {}}
294
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
295
296
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
297
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
298
{"return": {}}
299
{}
300
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
301
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
302
{"return": {}}
303
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
304
{"return": {}}
305
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
306
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
307
{"return": {}}
308
{}
309
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
310
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
311
{"return": {}}
312
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
313
314
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
315
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
316
{"return": {}}
317
{}
318
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
319
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
320
{"return": {}}
321
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
322
323
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
324
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
325
{"return": {}}
326
{}
327
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
328
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
329
{"return": {}}
330
331
--- Write #2 ---
332
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
333
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
334
{"return": {}}
335
{}
336
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
337
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
338
{"return": {}}
339
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
340
341
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
342
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
343
{"return": {}}
344
{}
345
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
346
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
347
{"return": {}}
348
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
349
{"return": {}}
350
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
351
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
352
{"return": {}}
353
{}
354
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
355
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
356
{"return": {}}
357
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
358
359
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
360
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
361
{"return": {}}
362
{}
363
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
364
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
365
{"return": {}}
366
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
367
368
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
369
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
370
{"return": {}}
371
{}
372
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
373
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
374
{"return": {}}
375
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
376
{"data": {"device": "backup_1", "error": "Input/output error", "len": 393216, "offset": 65536, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
377
@@ -XXX,XX +XXX,XX @@ expecting 13 dirty sectors; have 13. OK!
378
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
379
{"return": {}}
380
{}
381
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
382
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
383
{"return": {}}
384
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
385
386
@@ -XXX,XX +XXX,XX @@ expecting 13 dirty sectors; have 13. OK!
387
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
388
{"return": {}}
389
{}
390
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
391
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
392
{"return": {}}
393
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
394
{"return": {}}
395
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
396
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
397
{"return": {}}
398
{}
399
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
400
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
401
{"return": {}}
402
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
403
404
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
405
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
406
{"return": {}}
407
{}
408
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
409
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
410
{"return": {}}
411
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
412
413
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
414
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
415
{"return": {}}
416
{}
417
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
418
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
419
{"return": {}}
420
421
--- Write #2 ---
422
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
423
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
424
{"return": {}}
425
{}
426
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
427
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
428
{"return": {}}
429
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
430
431
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
432
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
433
{"return": {}}
434
{}
435
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
436
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
437
{"return": {}}
438
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
439
{"return": {}}
440
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
441
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
442
{"return": {}}
443
{}
444
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
445
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
446
{"return": {}}
447
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
448
449
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
450
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
451
{"return": {}}
452
{}
453
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
454
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
455
{"return": {}}
456
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
457
458
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
459
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
460
{"return": {}}
461
{}
462
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
463
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
464
{"return": {}}
465
466
--- Write #2 ---
467
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
468
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
469
{"return": {}}
470
{}
471
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
472
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
473
{"return": {}}
474
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
475
476
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
477
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
478
{"return": {}}
479
{}
480
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
481
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
482
{"return": {}}
483
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
484
{"return": {}}
485
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
486
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
487
{"return": {}}
488
{}
489
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
490
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
491
{"return": {}}
492
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
493
494
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
495
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
496
{"return": {}}
497
{}
498
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
499
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
500
{"return": {}}
501
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
502
503
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
504
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
505
{"return": {}}
506
{}
507
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
508
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
509
{"return": {}}
510
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
511
{"data": {"device": "backup_1", "error": "Input/output error", "len": 67108864, "offset": 983040, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
512
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
513
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
514
{"return": {}}
515
{}
516
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
517
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
518
{"return": {}}
519
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
520
521
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
522
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
523
{"return": {}}
524
{}
525
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
526
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
527
{"return": {}}
528
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
529
{"return": {}}
530
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
531
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
532
{"return": {}}
533
{}
534
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
535
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
536
{"return": {}}
537
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
538
539
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
540
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
541
{"return": {}}
542
{}
543
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
544
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
545
{"return": {}}
546
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
547
548
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
549
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
550
{"return": {}}
551
{}
552
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
553
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
554
{"return": {}}
555
556
--- Write #2 ---
557
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
558
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
559
{"return": {}}
560
{}
561
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
562
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
563
{"return": {}}
564
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
565
566
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
567
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
568
{"return": {}}
569
{}
570
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
571
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
572
{"return": {}}
573
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
574
{"return": {}}
575
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
576
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
577
{"return": {}}
578
{}
579
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
580
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
581
{"return": {}}
582
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
583
584
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
585
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
586
{"return": {}}
587
{}
588
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
589
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
590
{"return": {}}
591
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
592
593
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
594
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
595
{"return": {}}
596
{}
597
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
598
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
599
{"return": {}}
600
601
--- Write #2 ---
602
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
603
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
604
{"return": {}}
605
{}
606
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
607
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
608
{"return": {}}
609
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
610
611
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
612
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
613
{"return": {}}
614
{}
615
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
616
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
617
{"return": {}}
618
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
619
{"return": {}}
620
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
621
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
622
{"return": {}}
623
{}
624
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
625
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
626
{"return": {}}
627
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
628
629
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
630
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
631
{"return": {}}
632
{}
633
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
634
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
635
{"return": {}}
636
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
637
638
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
639
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
640
{"return": {}}
641
{}
642
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
643
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
644
{"return": {}}
645
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
646
{"data": {"device": "backup_1", "error": "Input/output error", "len": 67108864, "offset": 983040, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
647
@@ -XXX,XX +XXX,XX @@ expecting 1014 dirty sectors; have 1014. OK!
648
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
649
{"return": {}}
650
{}
651
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
652
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
653
{"return": {}}
654
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
655
656
@@ -XXX,XX +XXX,XX @@ expecting 1014 dirty sectors; have 1014. OK!
657
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
658
{"return": {}}
659
{}
660
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
661
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
662
{"return": {}}
663
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
664
{"return": {}}
665
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
666
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
667
{"return": {}}
668
{}
669
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
670
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
671
{"return": {}}
672
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
673
674
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
675
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
676
{"return": {}}
677
{}
678
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
679
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
680
{"return": {}}
681
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
682
683
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
684
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
685
{"return": {}}
686
{}
687
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
688
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "full", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
689
{"return": {}}
690
691
--- Write #2 ---
692
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
693
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
694
{"return": {}}
695
{}
696
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
697
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
698
{"return": {}}
699
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
700
701
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
702
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
703
{"return": {}}
704
{}
705
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
706
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
707
{"return": {}}
708
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
709
{"return": {}}
710
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
711
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
712
{"return": {}}
713
{}
714
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
715
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
716
{"return": {}}
717
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
718
719
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
720
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
721
{"return": {}}
722
{}
723
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
724
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
725
{"return": {}}
726
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
727
728
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
729
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
730
{"return": {}}
731
{}
732
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
733
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
734
{"return": {}}
735
736
--- Write #2 ---
737
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
738
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
739
{"return": {}}
740
{}
741
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
742
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
743
{"return": {}}
744
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
745
746
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
747
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
748
{"return": {}}
749
{}
750
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
751
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
752
{"return": {}}
753
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
754
{"return": {}}
755
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
756
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
757
{"return": {}}
758
{}
759
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
760
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
761
{"return": {}}
762
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
763
764
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
765
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
766
{"return": {}}
767
{}
768
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
769
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
770
{"return": {}}
771
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
772
773
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
774
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
775
{"return": {}}
776
{}
777
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
778
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
779
{"return": {}}
780
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
781
{"data": {"device": "backup_1", "error": "Input/output error", "len": 458752, "offset": 65536, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
782
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
783
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
784
{"return": {}}
785
{}
786
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
787
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
788
{"return": {}}
789
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
790
791
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
792
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
793
{"return": {}}
794
{}
795
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
796
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
797
{"return": {}}
798
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
799
{"return": {}}
800
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
801
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
802
{"return": {}}
803
{}
804
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
805
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
806
{"return": {}}
807
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
808
809
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
810
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
811
{"return": {}}
812
{}
813
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
814
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
815
{"return": {}}
816
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
817
818
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
819
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
820
{"return": {}}
821
{}
822
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
823
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
824
{"return": {}}
825
826
--- Write #2 ---
827
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
828
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
829
{"return": {}}
830
{}
831
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
832
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
833
{"return": {}}
834
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
835
836
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
837
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
838
{"return": {}}
839
{}
840
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
841
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
842
{"return": {}}
843
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
844
{"return": {}}
845
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
846
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
847
{"return": {}}
848
{}
849
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
850
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
851
{"return": {}}
852
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
853
854
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
855
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
856
{"return": {}}
857
{}
858
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
859
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
860
{"return": {}}
861
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
862
863
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
864
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
865
{"return": {}}
866
{}
867
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
868
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
869
{"return": {}}
870
871
--- Write #2 ---
872
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
873
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
874
{"return": {}}
875
{}
876
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
877
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
878
{"return": {}}
879
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
880
881
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
882
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
883
{"return": {}}
884
{}
885
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
886
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
887
{"return": {}}
888
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
889
{"return": {}}
890
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
891
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
892
{"return": {}}
893
{}
894
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
895
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
896
{"return": {}}
897
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
898
899
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
900
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
901
{"return": {}}
902
{}
903
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
904
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
905
{"return": {}}
906
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
907
908
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
909
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
910
{"return": {}}
911
{}
912
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
913
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
914
{"return": {}}
915
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
916
{"data": {"device": "backup_1", "error": "Input/output error", "len": 458752, "offset": 65536, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
917
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
918
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
919
{"return": {}}
920
{}
921
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
922
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
923
{"return": {}}
924
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
925
926
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
927
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
928
{"return": {}}
929
{}
930
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
931
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
932
{"return": {}}
933
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
934
{"return": {}}
935
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
936
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
937
{"return": {}}
938
{}
939
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
940
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0", "x-perf": {"max-workers": 1}}}
941
{"return": {}}
942
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
943
944
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
945
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
946
{"return": {}}
947
{}
948
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
949
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1", "x-perf": {"max-workers": 1}}}
950
{"return": {}}
951
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
952
953
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
954
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
955
{"return": {}}
956
{}
957
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
958
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_1", "sync": "top", "target": "backup_target_1", "x-perf": {"max-workers": 1}}}
959
{"return": {}}
960
961
--- Write #2 ---
962
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
963
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
964
{"return": {}}
965
{}
966
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
967
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2", "x-perf": {"max-workers": 1}}}
968
{"return": {}}
969
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
970
971
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
972
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
973
{"return": {}}
974
{}
975
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
976
+{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2", "x-perf": {"max-workers": 1}}}
977
{"return": {}}
978
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
979
{"return": {}}
980
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
981
982
-- Sync mode incremental tests --
983
984
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
985
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
986
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'incremental' sync mode"}}
987
988
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
989
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
990
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'incremental' sync mode"}}
991
992
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
993
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
994
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'incremental' sync mode"}}
995
996
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
997
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
998
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'incremental' sync mode"}}
999
1000
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1001
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1002
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1003
1004
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1005
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1006
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be 'on-success' when using sync mode 'incremental'"}}
1007
1008
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1009
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1010
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be 'on-success' when using sync mode 'incremental'"}}
1011
1012
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1013
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1014
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1015
1016
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1017
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1018
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be 'on-success' when using sync mode 'incremental'"}}
1019
1020
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1021
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1022
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be 'on-success' when using sync mode 'incremental'"}}
1023
1024
-- Sync mode bitmap tests --
1025
1026
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1027
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1028
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'bitmap' sync mode"}}
1029
1030
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1031
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1032
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'bitmap' sync mode"}}
1033
1034
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1035
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1036
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'bitmap' sync mode"}}
1037
1038
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1039
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1040
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'bitmap' sync mode"}}
1041
1042
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1043
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1044
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1045
1046
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1047
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1048
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1049
1050
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1051
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1052
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1053
1054
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1055
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1056
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1057
1058
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1059
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1060
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be given when providing a bitmap"}}
1061
1062
-- Sync mode full tests --
1063
1064
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1065
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1066
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1067
1068
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1069
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1070
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1071
1072
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1073
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1074
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1075
1076
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1077
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1078
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1079
1080
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1081
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1082
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1083
1084
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1085
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1086
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1087
1088
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1089
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1090
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1091
1092
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1093
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1094
{"error": {"class": "GenericError", "desc": "Bitmap sync mode 'never' has no meaningful effect when combined with sync mode 'full'"}}
1095
1096
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1097
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1098
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be given when providing a bitmap"}}
1099
1100
-- Sync mode top tests --
1101
1102
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1103
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1104
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1105
1106
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1107
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1108
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1109
1110
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1111
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1112
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1113
1114
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1115
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1116
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1117
1118
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1119
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1120
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1121
1122
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1123
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1124
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1125
1126
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1127
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1128
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1129
1130
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1131
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1132
{"error": {"class": "GenericError", "desc": "Bitmap sync mode 'never' has no meaningful effect when combined with sync mode 'top'"}}
1133
1134
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1135
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1136
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be given when providing a bitmap"}}
1137
1138
-- Sync mode none tests --
1139
1140
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1141
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1142
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1143
1144
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1145
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1146
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1147
1148
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1149
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1150
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1151
1152
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1153
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1154
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1155
1156
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1157
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1158
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1159
1160
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1161
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1162
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1163
1164
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1165
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1166
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1167
1168
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1169
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1170
{"error": {"class": "GenericError", "desc": "sync mode 'none' does not produce meaningful bitmap outputs"}}
1171
1172
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1173
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1174
{"error": {"class": "GenericError", "desc": "sync mode 'none' does not produce meaningful bitmap outputs"}}
1175
1176
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1177
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1178
{"error": {"class": "GenericError", "desc": "sync mode 'none' does not produce meaningful bitmap outputs"}}
1179
1180
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1181
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target", "x-perf": {"max-workers": 1}}}
1182
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be given when providing a bitmap"}}
119
1183
120
--
1184
--
121
2.24.1
1185
2.29.2
122
1186
123
1187
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
qcow2_can_store_new_dirty_bitmap works wrong, as it considers only
3
We are going to stop use of this callback in the following commit.
4
bitmaps already stored in the qcow2 image and ignores persistent
4
Still the callback handling code will be dropped in a separate commit.
5
BdrvDirtyBitmap objects.
5
So, for now let's make it optional.
6
7
So, let's instead count persistent BdrvDirtyBitmaps. We load all qcow2
8
bitmaps on open, so there should not be any bitmap in the image for
9
which we don't have BdrvDirtyBitmaps version. If it is - it's a kind of
10
corruption, and no reason to check for corruptions here (open() and
11
close() are better places for it).
12
6
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Message-id: 20191014115126.15360-2-vsementsov@virtuozzo.com
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Cc: qemu-stable@nongnu.org
9
Message-Id: <20210116214705.822267-16-vsementsov@virtuozzo.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
11
---
19
block/qcow2-bitmap.c | 41 ++++++++++++++++++-----------------------
12
block/block-copy.c | 4 +++-
20
1 file changed, 18 insertions(+), 23 deletions(-)
13
1 file changed, 3 insertions(+), 1 deletion(-)
21
14
22
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
15
diff --git a/block/block-copy.c b/block/block-copy.c
23
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2-bitmap.c
17
--- a/block/block-copy.c
25
+++ b/block/qcow2-bitmap.c
18
+++ b/block/block-copy.c
26
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
19
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
27
Error **errp)
20
t->call_state->error_is_read = error_is_read;
28
{
21
} else {
29
BDRVQcow2State *s = bs->opaque;
22
progress_work_done(t->s->progress, t->bytes);
30
- bool found;
23
- t->s->progress_bytes_callback(t->bytes, t->s->progress_opaque);
31
- Qcow2BitmapList *bm_list;
24
+ if (t->s->progress_bytes_callback) {
32
+ BdrvDirtyBitmap *bitmap;
25
+ t->s->progress_bytes_callback(t->bytes, t->s->progress_opaque);
33
+ uint64_t bitmap_directory_size = 0;
34
+ uint32_t nb_bitmaps = 0;
35
+
36
+ if (bdrv_find_dirty_bitmap(bs, name)) {
37
+ error_setg(errp, "Bitmap already exists: %s", name);
38
+ return false;
39
+ }
40
41
if (s->qcow_version < 3) {
42
/* Without autoclear_features, we would always have to assume
43
@@ -XXX,XX +XXX,XX @@ bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
44
goto fail;
45
}
46
47
- if (s->nb_bitmaps == 0) {
48
- return true;
49
+ FOR_EACH_DIRTY_BITMAP(bs, bitmap) {
50
+ if (bdrv_dirty_bitmap_get_persistence(bitmap)) {
51
+ nb_bitmaps++;
52
+ bitmap_directory_size +=
53
+ calc_dir_entry_size(strlen(bdrv_dirty_bitmap_name(bitmap)), 0);
54
+ }
26
+ }
55
}
27
}
56
+ nb_bitmaps++;
28
co_put_to_shres(t->s->mem, t->bytes);
57
+ bitmap_directory_size += calc_dir_entry_size(strlen(name), 0);
29
block_copy_task_end(t, ret);
58
59
- if (s->nb_bitmaps >= QCOW2_MAX_BITMAPS) {
60
+ if (nb_bitmaps > QCOW2_MAX_BITMAPS) {
61
error_setg(errp,
62
"Maximum number of persistent bitmaps is already reached");
63
goto fail;
64
}
65
66
- if (s->bitmap_directory_size + calc_dir_entry_size(strlen(name), 0) >
67
- QCOW2_MAX_BITMAP_DIRECTORY_SIZE)
68
- {
69
+ if (bitmap_directory_size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) {
70
error_setg(errp, "Not enough space in the bitmap directory");
71
goto fail;
72
}
73
74
- qemu_co_mutex_lock(&s->lock);
75
- bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
76
- s->bitmap_directory_size, errp);
77
- qemu_co_mutex_unlock(&s->lock);
78
- if (bm_list == NULL) {
79
- goto fail;
80
- }
81
-
82
- found = find_bitmap_by_name(bm_list, name);
83
- bitmap_list_free(bm_list);
84
- if (found) {
85
- error_setg(errp, "Bitmap with the same name is already stored");
86
- goto fail;
87
- }
88
-
89
return true;
90
91
fail:
92
--
30
--
93
2.24.1
31
2.29.2
94
32
95
33
diff view generated by jsdifflib
1
Overwriting IMGOPTS means ignoring all user-supplied options, which is
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
not what we want. Replace the current IMGOPTS use by a new BACKING_FILE
3
variable.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20191107163708.833192-14-mreitz@redhat.com
5
Message-Id: <20210116214705.822267-17-vsementsov@virtuozzo.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
7
---
10
tests/qemu-iotests/267 | 12 ++++++++----
8
block/backup.c | 12 +++++-------
11
1 file changed, 8 insertions(+), 4 deletions(-)
9
1 file changed, 5 insertions(+), 7 deletions(-)
12
10
13
diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267
11
diff --git a/block/backup.c b/block/backup.c
14
index XXXXXXX..XXXXXXX 100755
12
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/267
13
--- a/block/backup.c
16
+++ b/tests/qemu-iotests/267
14
+++ b/block/backup.c
17
@@ -XXX,XX +XXX,XX @@ size=128M
15
@@ -XXX,XX +XXX,XX @@ static void backup_init_bcs_bitmap(BackupBlockJob *job)
18
16
static int coroutine_fn backup_run(Job *job, Error **errp)
19
run_test()
20
{
17
{
21
- _make_test_img $size
18
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
22
+ if [ -n "$BACKING_FILE" ]; then
19
- int ret = 0;
23
+ _make_test_img -b "$BACKING_FILE" $size
20
+ int ret;
24
+ else
21
25
+ _make_test_img $size
22
backup_init_bcs_bitmap(s);
26
+ fi
23
27
printf "savevm snap0\ninfo snapshots\nloadvm snap0\n" | run_qemu "$@" | _filter_date
24
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
25
26
for (offset = 0; offset < s->len; ) {
27
if (yield_and_check(s)) {
28
- ret = -ECANCELED;
29
- goto out;
30
+ return -ECANCELED;
31
}
32
33
ret = block_copy_reset_unallocated(s->bcs, offset, &count);
34
if (ret < 0) {
35
- goto out;
36
+ return ret;
37
}
38
39
offset += count;
40
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
41
job_yield(job);
42
}
43
} else {
44
- ret = backup_loop(s);
45
+ return backup_loop(s);
46
}
47
48
- out:
49
- return ret;
50
+ return 0;
28
}
51
}
29
52
30
@@ -XXX,XX +XXX,XX @@ echo
53
static const BlockJobDriver backup_job_driver = {
31
32
TEST_IMG="$TEST_IMG.base" _make_test_img $size
33
34
-IMGOPTS="backing_file=$TEST_IMG.base" \
35
+BACKING_FILE="$TEST_IMG.base" \
36
run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \
37
-blockdev driver=file,filename="$TEST_IMG",node-name=file \
38
-blockdev driver=$IMGFMT,file=file,backing=backing-file,node-name=fmt
39
40
-IMGOPTS="backing_file=$TEST_IMG.base" \
41
+BACKING_FILE="$TEST_IMG.base" \
42
run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \
43
-blockdev driver=$IMGFMT,file=backing-file,node-name=backing-fmt \
44
-blockdev driver=file,filename="$TEST_IMG",node-name=file \
45
@@ -XXX,XX +XXX,XX @@ echo
46
echo "=== -blockdev with NBD server on the backing file ==="
47
echo
48
49
-IMGOPTS="backing_file=$TEST_IMG.base" _make_test_img $size
50
+_make_test_img -b "$TEST_IMG.base" $size
51
cat <<EOF |
52
nbd_server_start unix:$SOCK_DIR/nbd
53
nbd_server_add -w backing-fmt
54
--
54
--
55
2.24.1
55
2.29.2
56
56
57
57
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
3
This brings async request handling and block-status driven chunk sizes
4
to backup out of the box, which improves backup performance.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210116214705.822267-18-vsementsov@virtuozzo.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/backup.c | 187 +++++++++++++++++++++++++++++++------------------
12
1 file changed, 120 insertions(+), 67 deletions(-)
13
14
diff --git a/block/backup.c b/block/backup.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/backup.c
17
+++ b/block/backup.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "block/block-copy.h"
20
#include "qapi/error.h"
21
#include "qapi/qmp/qerror.h"
22
-#include "qemu/ratelimit.h"
23
#include "qemu/cutils.h"
24
#include "sysemu/block-backend.h"
25
#include "qemu/bitmap.h"
26
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
27
BlockdevOnError on_source_error;
28
BlockdevOnError on_target_error;
29
uint64_t len;
30
- uint64_t bytes_read;
31
int64_t cluster_size;
32
BackupPerf perf;
33
34
BlockCopyState *bcs;
35
+
36
+ bool wait;
37
+ BlockCopyCallState *bg_bcs_call;
38
} BackupBlockJob;
39
40
static const BlockJobDriver backup_job_driver;
41
42
-static void backup_progress_bytes_callback(int64_t bytes, void *opaque)
43
-{
44
- BackupBlockJob *s = opaque;
45
-
46
- s->bytes_read += bytes;
47
-}
48
-
49
-static int coroutine_fn backup_do_cow(BackupBlockJob *job,
50
- int64_t offset, uint64_t bytes,
51
- bool *error_is_read)
52
-{
53
- int ret = 0;
54
- int64_t start, end; /* bytes */
55
-
56
- start = QEMU_ALIGN_DOWN(offset, job->cluster_size);
57
- end = QEMU_ALIGN_UP(bytes + offset, job->cluster_size);
58
-
59
- trace_backup_do_cow_enter(job, start, offset, bytes);
60
-
61
- ret = block_copy(job->bcs, start, end - start, true, error_is_read);
62
-
63
- trace_backup_do_cow_return(job, offset, bytes, ret);
64
-
65
- return ret;
66
-}
67
-
68
static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
69
{
70
BdrvDirtyBitmap *bm;
71
@@ -XXX,XX +XXX,XX @@ static BlockErrorAction backup_error_action(BackupBlockJob *job,
72
}
73
}
74
75
-static bool coroutine_fn yield_and_check(BackupBlockJob *job)
76
+static void coroutine_fn backup_block_copy_callback(void *opaque)
77
{
78
- uint64_t delay_ns;
79
-
80
- if (job_is_cancelled(&job->common.job)) {
81
- return true;
82
- }
83
-
84
- /*
85
- * We need to yield even for delay_ns = 0 so that bdrv_drain_all() can
86
- * return. Without a yield, the VM would not reboot.
87
- */
88
- delay_ns = block_job_ratelimit_get_delay(&job->common, job->bytes_read);
89
- job->bytes_read = 0;
90
- job_sleep_ns(&job->common.job, delay_ns);
91
+ BackupBlockJob *s = opaque;
92
93
- if (job_is_cancelled(&job->common.job)) {
94
- return true;
95
+ if (s->wait) {
96
+ s->wait = false;
97
+ aio_co_wake(s->common.job.co);
98
+ } else {
99
+ job_enter(&s->common.job);
100
}
101
-
102
- return false;
103
}
104
105
static int coroutine_fn backup_loop(BackupBlockJob *job)
106
{
107
- bool error_is_read;
108
- int64_t offset;
109
- BdrvDirtyBitmapIter *bdbi;
110
+ BlockCopyCallState *s = NULL;
111
int ret = 0;
112
+ bool error_is_read;
113
+ BlockErrorAction act;
114
+
115
+ while (true) { /* retry loop */
116
+ job->bg_bcs_call = s = block_copy_async(job->bcs, 0,
117
+ QEMU_ALIGN_UP(job->len, job->cluster_size),
118
+ job->perf.max_workers, job->perf.max_chunk,
119
+ backup_block_copy_callback, job);
120
+
121
+ while (!block_copy_call_finished(s) &&
122
+ !job_is_cancelled(&job->common.job))
123
+ {
124
+ job_yield(&job->common.job);
125
+ }
126
127
- bdbi = bdrv_dirty_iter_new(block_copy_dirty_bitmap(job->bcs));
128
- while ((offset = bdrv_dirty_iter_next(bdbi)) != -1) {
129
- do {
130
- if (yield_and_check(job)) {
131
- goto out;
132
- }
133
- ret = backup_do_cow(job, offset, job->cluster_size, &error_is_read);
134
- if (ret < 0 && backup_error_action(job, error_is_read, -ret) ==
135
- BLOCK_ERROR_ACTION_REPORT)
136
- {
137
- goto out;
138
- }
139
- } while (ret < 0);
140
+ if (!block_copy_call_finished(s)) {
141
+ assert(job_is_cancelled(&job->common.job));
142
+ /*
143
+ * Note that we can't use job_yield() here, as it doesn't work for
144
+ * cancelled job.
145
+ */
146
+ block_copy_call_cancel(s);
147
+ job->wait = true;
148
+ qemu_coroutine_yield();
149
+ assert(block_copy_call_finished(s));
150
+ ret = 0;
151
+ goto out;
152
+ }
153
+
154
+ if (job_is_cancelled(&job->common.job) ||
155
+ block_copy_call_succeeded(s))
156
+ {
157
+ ret = 0;
158
+ goto out;
159
+ }
160
+
161
+ if (block_copy_call_cancelled(s)) {
162
+ /*
163
+ * Job is not cancelled but only block-copy call. This is possible
164
+ * after job pause. Now the pause is finished, start new block-copy
165
+ * iteration.
166
+ */
167
+ block_copy_call_free(s);
168
+ continue;
169
+ }
170
+
171
+ /* The only remaining case is failed block-copy call. */
172
+ assert(block_copy_call_failed(s));
173
+
174
+ ret = block_copy_call_status(s, &error_is_read);
175
+ act = backup_error_action(job, error_is_read, -ret);
176
+ switch (act) {
177
+ case BLOCK_ERROR_ACTION_REPORT:
178
+ goto out;
179
+ case BLOCK_ERROR_ACTION_STOP:
180
+ /*
181
+ * Go to pause prior to starting new block-copy call on the next
182
+ * iteration.
183
+ */
184
+ job_pause_point(&job->common.job);
185
+ break;
186
+ case BLOCK_ERROR_ACTION_IGNORE:
187
+ /* Proceed to new block-copy call to retry. */
188
+ break;
189
+ default:
190
+ abort();
191
+ }
192
+
193
+ block_copy_call_free(s);
194
}
195
196
- out:
197
- bdrv_dirty_iter_free(bdbi);
198
+out:
199
+ block_copy_call_free(s);
200
+ job->bg_bcs_call = NULL;
201
return ret;
202
}
203
204
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
205
int64_t count;
206
207
for (offset = 0; offset < s->len; ) {
208
- if (yield_and_check(s)) {
209
+ if (job_is_cancelled(job)) {
210
+ return -ECANCELED;
211
+ }
212
+
213
+ job_pause_point(job);
214
+
215
+ if (job_is_cancelled(job)) {
216
return -ECANCELED;
217
}
218
219
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
220
return 0;
221
}
222
223
+static void coroutine_fn backup_pause(Job *job)
224
+{
225
+ BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
226
+
227
+ if (s->bg_bcs_call && !block_copy_call_finished(s->bg_bcs_call)) {
228
+ block_copy_call_cancel(s->bg_bcs_call);
229
+ s->wait = true;
230
+ qemu_coroutine_yield();
231
+ }
232
+}
233
+
234
+static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
235
+{
236
+ BackupBlockJob *s = container_of(job, BackupBlockJob, common);
237
+
238
+ /*
239
+ * block_job_set_speed() is called first from block_job_create(), when we
240
+ * don't yet have s->bcs.
241
+ */
242
+ if (s->bcs) {
243
+ block_copy_set_speed(s->bcs, speed);
244
+ if (s->bg_bcs_call) {
245
+ block_copy_kick(s->bg_bcs_call);
246
+ }
247
+ }
248
+}
249
+
250
static const BlockJobDriver backup_job_driver = {
251
.job_driver = {
252
.instance_size = sizeof(BackupBlockJob),
253
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver backup_job_driver = {
254
.commit = backup_commit,
255
.abort = backup_abort,
256
.clean = backup_clean,
257
- }
258
+ .pause = backup_pause,
259
+ },
260
+ .set_speed = backup_set_speed,
261
};
262
263
static int64_t backup_calculate_cluster_size(BlockDriverState *target,
264
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
265
job->len = len;
266
job->perf = *perf;
267
268
- block_copy_set_progress_callback(bcs, backup_progress_bytes_callback, job);
269
block_copy_set_progress_meter(bcs, &job->common.job.progress);
270
+ block_copy_set_speed(bcs, speed);
271
272
/* Required permissions are already taken by backup-top target */
273
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
274
--
275
2.29.2
276
277
diff view generated by jsdifflib
1
Print the feature fields as a set of bits so that filtering is easier.
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Further commit will add a benchmark
4
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
(scripts/simplebench/bench-backup.py), which will show that backup
5
Message-id: 20191107163708.833192-4-mreitz@redhat.com
5
works better with async parallel requests (previous commit) and
6
disabled copy_range. So, let's disable copy_range by default.
7
8
Note: the option was added several commits ago with default to true,
9
to follow old behavior (the feature was enabled unconditionally), and
10
only now we are going to change the default behavior.
11
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Message-Id: <20210116214705.822267-19-vsementsov@virtuozzo.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
16
---
8
tests/qemu-iotests/031.out | 36 +++++++++----------
17
qapi/block-core.json | 2 +-
9
tests/qemu-iotests/036.out | 18 +++++-----
18
blockdev.c | 2 +-
10
tests/qemu-iotests/039.out | 22 ++++++------
19
2 files changed, 2 insertions(+), 2 deletions(-)
11
tests/qemu-iotests/060.out | 20 +++++------
12
tests/qemu-iotests/061.out | 72 ++++++++++++++++++-------------------
13
tests/qemu-iotests/137.out | 2 +-
14
tests/qemu-iotests/qcow2.py | 18 +++++++---
15
7 files changed, 99 insertions(+), 89 deletions(-)
16
20
17
diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/031.out
23
--- a/qapi/block-core.json
20
+++ b/tests/qemu-iotests/031.out
24
+++ b/qapi/block-core.json
21
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
25
@@ -XXX,XX +XXX,XX @@
22
refcount_table_clusters 1
26
# Optional parameters for backup. These parameters don't affect
23
nb_snapshots 0
27
# functionality, but may significantly affect performance.
24
snapshot_offset 0x0
28
#
25
-incompatible_features 0x0
29
-# @use-copy-range: Use copy offloading. Default true.
26
-compatible_features 0x0
30
+# @use-copy-range: Use copy offloading. Default false.
27
-autoclear_features 0x0
31
#
28
+incompatible_features []
32
# @max-workers: Maximum number of parallel requests for the sustained background
29
+compatible_features []
33
# copying process. Doesn't influence copy-before-write operations.
30
+autoclear_features []
34
diff --git a/blockdev.c b/blockdev.c
31
refcount_order 4
32
header_length 72
33
34
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
35
refcount_table_clusters 1
36
nb_snapshots 0
37
snapshot_offset 0x0
38
-incompatible_features 0x0
39
-compatible_features 0x0
40
-autoclear_features 0x0
41
+incompatible_features []
42
+compatible_features []
43
+autoclear_features []
44
refcount_order 4
45
header_length 72
46
47
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
48
refcount_table_clusters 1
49
nb_snapshots 0
50
snapshot_offset 0x0
51
-incompatible_features 0x0
52
-compatible_features 0x0
53
-autoclear_features 0x0
54
+incompatible_features []
55
+compatible_features []
56
+autoclear_features []
57
refcount_order 4
58
header_length 72
59
60
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
61
refcount_table_clusters 1
62
nb_snapshots 0
63
snapshot_offset 0x0
64
-incompatible_features 0x0
65
-compatible_features 0x0
66
-autoclear_features 0x0
67
+incompatible_features []
68
+compatible_features []
69
+autoclear_features []
70
refcount_order 4
71
header_length 104
72
73
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
74
refcount_table_clusters 1
75
nb_snapshots 0
76
snapshot_offset 0x0
77
-incompatible_features 0x0
78
-compatible_features 0x0
79
-autoclear_features 0x0
80
+incompatible_features []
81
+compatible_features []
82
+autoclear_features []
83
refcount_order 4
84
header_length 104
85
86
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
87
refcount_table_clusters 1
88
nb_snapshots 0
89
snapshot_offset 0x0
90
-incompatible_features 0x0
91
-compatible_features 0x0
92
-autoclear_features 0x0
93
+incompatible_features []
94
+compatible_features []
95
+autoclear_features []
96
refcount_order 4
97
header_length 104
98
99
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
100
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
101
--- a/tests/qemu-iotests/036.out
36
--- a/blockdev.c
102
+++ b/tests/qemu-iotests/036.out
37
+++ b/blockdev.c
103
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
38
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
104
refcount_table_clusters 1
39
{
105
nb_snapshots 0
40
BlockJob *job = NULL;
106
snapshot_offset 0x0
41
BdrvDirtyBitmap *bmap = NULL;
107
-incompatible_features 0x8000000000000000
42
- BackupPerf perf = { .use_copy_range = true, .max_workers = 64 };
108
-compatible_features 0x0
43
+ BackupPerf perf = { .max_workers = 64 };
109
-autoclear_features 0x0
44
int job_flags = JOB_DEFAULT;
110
+incompatible_features [63]
45
111
+compatible_features []
46
if (!backup->has_speed) {
112
+autoclear_features []
113
refcount_order 4
114
header_length 104
115
116
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
117
refcount_table_clusters 1
118
nb_snapshots 0
119
snapshot_offset 0x0
120
-incompatible_features 0x0
121
-compatible_features 0x0
122
-autoclear_features 0x8000000000000000
123
+incompatible_features []
124
+compatible_features []
125
+autoclear_features [63]
126
refcount_order 4
127
header_length 104
128
129
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
130
refcount_table_clusters 1
131
nb_snapshots 0
132
snapshot_offset 0x0
133
-incompatible_features 0x0
134
-compatible_features 0x0
135
-autoclear_features 0x0
136
+incompatible_features []
137
+compatible_features []
138
+autoclear_features []
139
refcount_order 4
140
header_length 104
141
142
diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out
143
index XXXXXXX..XXXXXXX 100644
144
--- a/tests/qemu-iotests/039.out
145
+++ b/tests/qemu-iotests/039.out
146
@@ -XXX,XX +XXX,XX @@ QA output created by 039
147
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
148
wrote 512/512 bytes at offset 0
149
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
150
-incompatible_features 0x0
151
+incompatible_features []
152
No errors were found on the image.
153
154
== Creating a dirty image file ==
155
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
156
wrote 512/512 bytes at offset 0
157
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
158
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
159
-incompatible_features 0x1
160
+incompatible_features [0]
161
ERROR cluster 5 refcount=0 reference=1
162
ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
163
164
@@ -XXX,XX +XXX,XX @@ Data may be corrupted, or further writes to the image may corrupt it.
165
== Read-only access must still work ==
166
read 512/512 bytes at offset 0
167
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
168
-incompatible_features 0x1
169
+incompatible_features [0]
170
171
== Repairing the image file must succeed ==
172
ERROR cluster 5 refcount=0 reference=1
173
@@ -XXX,XX +XXX,XX @@ The following inconsistencies were found and repaired:
174
175
Double checking the fixed image now...
176
No errors were found on the image.
177
-incompatible_features 0x0
178
+incompatible_features []
179
180
== Data should still be accessible after repair ==
181
read 512/512 bytes at offset 0
182
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
183
wrote 512/512 bytes at offset 0
184
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
185
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
186
-incompatible_features 0x1
187
+incompatible_features [0]
188
ERROR cluster 5 refcount=0 reference=1
189
Rebuilding refcount structure
190
Repairing cluster 1 refcount=1 reference=0
191
Repairing cluster 2 refcount=1 reference=0
192
wrote 512/512 bytes at offset 0
193
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
-incompatible_features 0x0
195
+incompatible_features []
196
197
== Creating an image file with lazy_refcounts=off ==
198
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
199
wrote 512/512 bytes at offset 0
200
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
201
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
202
-incompatible_features 0x0
203
+incompatible_features []
204
No errors were found on the image.
205
206
== Committing to a backing file with lazy_refcounts=on ==
207
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/
208
wrote 512/512 bytes at offset 0
209
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
210
Image committed.
211
-incompatible_features 0x0
212
-incompatible_features 0x0
213
+incompatible_features []
214
+incompatible_features []
215
No errors were found on the image.
216
No errors were found on the image.
217
218
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
219
wrote 512/512 bytes at offset 0
220
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
221
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
222
-incompatible_features 0x1
223
+incompatible_features [0]
224
ERROR cluster 5 refcount=0 reference=1
225
ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
226
227
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
228
wrote 512/512 bytes at offset 0
229
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
230
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
231
-incompatible_features 0x0
232
+incompatible_features []
233
No errors were found on the image.
234
*** done
235
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
236
index XXXXXXX..XXXXXXX 100644
237
--- a/tests/qemu-iotests/060.out
238
+++ b/tests/qemu-iotests/060.out
239
@@ -XXX,XX +XXX,XX @@ ERROR cluster 3 refcount=1 reference=3
240
241
1 errors were found on the image.
242
Data may be corrupted, or further writes to the image may corrupt it.
243
-incompatible_features 0x0
244
+incompatible_features []
245
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L1 table); further corruption events will be suppressed
246
write failed: Input/output error
247
-incompatible_features 0x2
248
+incompatible_features [1]
249
image: TEST_DIR/t.IMGFMT
250
file format: IMGFMT
251
virtual size: 64 MiB (67108864 bytes)
252
@@ -XXX,XX +XXX,XX @@ ERROR cluster 2 refcount=1 reference=2
253
254
2 errors were found on the image.
255
Data may be corrupted, or further writes to the image may corrupt it.
256
-incompatible_features 0x0
257
+incompatible_features []
258
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount block); further corruption events will be suppressed
259
write failed: Input/output error
260
-incompatible_features 0x2
261
+incompatible_features [1]
262
ERROR refcount block 0 refcount=2
263
ERROR cluster 2 refcount=1 reference=2
264
Rebuilding refcount structure
265
@@ -XXX,XX +XXX,XX @@ The following inconsistencies were found and repaired:
266
267
Double checking the fixed image now...
268
No errors were found on the image.
269
-incompatible_features 0x0
270
+incompatible_features []
271
wrote 512/512 bytes at offset 0
272
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
-incompatible_features 0x0
274
+incompatible_features []
275
276
=== Testing cluster data reference into inactive L2 table ===
277
278
@@ -XXX,XX +XXX,XX @@ Data may be corrupted, or further writes to the image may corrupt it.
279
280
1 leaked clusters were found on the image.
281
This means waste of disk space, but no harm to data.
282
-incompatible_features 0x0
283
+incompatible_features []
284
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with inactive L2 table); further corruption events will be suppressed
285
write failed: Input/output error
286
-incompatible_features 0x2
287
+incompatible_features [1]
288
ERROR cluster 4 refcount=1 reference=2
289
Leaked cluster 9 refcount=1 reference=0
290
Repairing cluster 4 refcount=1 reference=2
291
@@ -XXX,XX +XXX,XX @@ The following inconsistencies were found and repaired:
292
293
Double checking the fixed image now...
294
No errors were found on the image.
295
-incompatible_features 0x0
296
+incompatible_features []
297
wrote 512/512 bytes at offset 0
298
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
299
-incompatible_features 0x0
300
+incompatible_features []
301
read 512/512 bytes at offset 0
302
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
303
No errors were found on the image.
304
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
305
index XXXXXXX..XXXXXXX 100644
306
--- a/tests/qemu-iotests/061.out
307
+++ b/tests/qemu-iotests/061.out
308
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
309
refcount_table_clusters 1
310
nb_snapshots 0
311
snapshot_offset 0x0
312
-incompatible_features 0x0
313
-compatible_features 0x1
314
-autoclear_features 0x0
315
+incompatible_features []
316
+compatible_features [0]
317
+autoclear_features []
318
refcount_order 4
319
header_length 104
320
321
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
322
refcount_table_clusters 1
323
nb_snapshots 0
324
snapshot_offset 0x0
325
-incompatible_features 0x0
326
-compatible_features 0x0
327
-autoclear_features 0x0
328
+incompatible_features []
329
+compatible_features []
330
+autoclear_features []
331
refcount_order 4
332
header_length 72
333
334
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
335
refcount_table_clusters 1
336
nb_snapshots 0
337
snapshot_offset 0x0
338
-incompatible_features 0x0
339
-compatible_features 0x1
340
-autoclear_features 0x0
341
+incompatible_features []
342
+compatible_features [0]
343
+autoclear_features []
344
refcount_order 4
345
header_length 104
346
347
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
348
refcount_table_clusters 1
349
nb_snapshots 0
350
snapshot_offset 0x0
351
-incompatible_features 0x0
352
-compatible_features 0x0
353
-autoclear_features 0x0
354
+incompatible_features []
355
+compatible_features []
356
+autoclear_features []
357
refcount_order 4
358
header_length 72
359
360
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
361
refcount_table_clusters 1
362
nb_snapshots 0
363
snapshot_offset 0x0
364
-incompatible_features 0x1
365
-compatible_features 0x1
366
-autoclear_features 0x0
367
+incompatible_features [0]
368
+compatible_features [0]
369
+autoclear_features []
370
refcount_order 4
371
header_length 104
372
373
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x80000
374
refcount_table_clusters 1
375
nb_snapshots 0
376
snapshot_offset 0x0
377
-incompatible_features 0x0
378
-compatible_features 0x0
379
-autoclear_features 0x0
380
+incompatible_features []
381
+compatible_features []
382
+autoclear_features []
383
refcount_order 4
384
header_length 72
385
386
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
387
refcount_table_clusters 1
388
nb_snapshots 0
389
snapshot_offset 0x0
390
-incompatible_features 0x0
391
-compatible_features 0x40000000000
392
-autoclear_features 0x40000000000
393
+incompatible_features []
394
+compatible_features [42]
395
+autoclear_features [42]
396
refcount_order 4
397
header_length 104
398
399
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
400
refcount_table_clusters 1
401
nb_snapshots 0
402
snapshot_offset 0x0
403
-incompatible_features 0x0
404
-compatible_features 0x0
405
-autoclear_features 0x0
406
+incompatible_features []
407
+compatible_features []
408
+autoclear_features []
409
refcount_order 4
410
header_length 72
411
412
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
413
refcount_table_clusters 1
414
nb_snapshots 0
415
snapshot_offset 0x0
416
-incompatible_features 0x0
417
-compatible_features 0x0
418
-autoclear_features 0x0
419
+incompatible_features []
420
+compatible_features []
421
+autoclear_features []
422
refcount_order 4
423
header_length 72
424
425
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
426
refcount_table_clusters 1
427
nb_snapshots 0
428
snapshot_offset 0x0
429
-incompatible_features 0x0
430
-compatible_features 0x1
431
-autoclear_features 0x0
432
+incompatible_features []
433
+compatible_features [0]
434
+autoclear_features []
435
refcount_order 4
436
header_length 104
437
438
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x10000
439
refcount_table_clusters 1
440
nb_snapshots 0
441
snapshot_offset 0x0
442
-incompatible_features 0x1
443
-compatible_features 0x1
444
-autoclear_features 0x0
445
+incompatible_features [0]
446
+compatible_features [0]
447
+autoclear_features []
448
refcount_order 4
449
header_length 104
450
451
@@ -XXX,XX +XXX,XX @@ refcount_table_offset 0x80000
452
refcount_table_clusters 1
453
nb_snapshots 0
454
snapshot_offset 0x0
455
-incompatible_features 0x0
456
-compatible_features 0x0
457
-autoclear_features 0x0
458
+incompatible_features []
459
+compatible_features []
460
+autoclear_features []
461
refcount_order 4
462
header_length 104
463
464
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
465
index XXXXXXX..XXXXXXX 100644
466
--- a/tests/qemu-iotests/137.out
467
+++ b/tests/qemu-iotests/137.out
468
@@ -XXX,XX +XXX,XX @@ qemu-io: Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are
469
wrote 512/512 bytes at offset 0
470
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
471
./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" )
472
-incompatible_features 0x0
473
+incompatible_features []
474
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
475
wrote 65536/65536 bytes at offset 0
476
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
477
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
478
index XXXXXXX..XXXXXXX 100755
479
--- a/tests/qemu-iotests/qcow2.py
480
+++ b/tests/qemu-iotests/qcow2.py
481
@@ -XXX,XX +XXX,XX @@ class QcowHeader:
482
[ uint64_t, '%#x', 'snapshot_offset' ],
483
484
# Version 3 header fields
485
- [ uint64_t, '%#x', 'incompatible_features' ],
486
- [ uint64_t, '%#x', 'compatible_features' ],
487
- [ uint64_t, '%#x', 'autoclear_features' ],
488
+ [ uint64_t, 'mask', 'incompatible_features' ],
489
+ [ uint64_t, 'mask', 'compatible_features' ],
490
+ [ uint64_t, 'mask', 'autoclear_features' ],
491
[ uint32_t, '%d', 'refcount_order' ],
492
[ uint32_t, '%d', 'header_length' ],
493
];
494
@@ -XXX,XX +XXX,XX @@ class QcowHeader:
495
496
def dump(self):
497
for f in QcowHeader.fields:
498
- print("%-25s" % f[2], f[1] % self.__dict__[f[2]])
499
+ value = self.__dict__[f[2]]
500
+ if f[1] == 'mask':
501
+ bits = []
502
+ for bit in range(64):
503
+ if value & (1 << bit):
504
+ bits.append(bit)
505
+ value_str = str(bits)
506
+ else:
507
+ value_str = f[1] % value
508
+
509
+ print("%-25s" % f[2], value_str)
510
print("")
511
512
def dump_extensions(self):
513
--
47
--
514
2.24.1
48
2.29.2
515
49
516
50
diff view generated by jsdifflib
1
Tests should not overwrite all user-supplied image options, but only add
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
to it (which will effectively overwrite conflicting values). Accomplish
3
this by passing options to _make_test_img via -o instead of $IMGOPTS.
4
2
5
For some tests, there is no functional change because they already only
3
Drop unused code.
6
appended options to IMGOPTS. For these, this patch is just a
7
simplification.
8
4
9
For others, this is a change, so they now heed user-specified $IMGOPTS.
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Some of those tests do not work with all image options, though, so we
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
need to disable them accordingly.
7
Message-Id: <20210116214705.822267-20-vsementsov@virtuozzo.com>
12
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
15
Message-id: 20191107163708.833192-12-mreitz@redhat.com
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
9
---
18
tests/qemu-iotests/031 | 9 ++++---
10
include/block/block-copy.h | 6 ------
19
tests/qemu-iotests/039 | 24 ++++++------------
11
block/block-copy.c | 15 ---------------
20
tests/qemu-iotests/059 | 18 ++++++-------
12
2 files changed, 21 deletions(-)
21
tests/qemu-iotests/060 | 6 ++---
22
tests/qemu-iotests/061 | 57 ++++++++++++++++++++++--------------------
23
tests/qemu-iotests/079 | 3 +--
24
tests/qemu-iotests/106 | 2 +-
25
tests/qemu-iotests/108 | 2 +-
26
tests/qemu-iotests/112 | 32 ++++++++++++------------
27
tests/qemu-iotests/115 | 3 +--
28
tests/qemu-iotests/121 | 6 ++---
29
tests/qemu-iotests/125 | 2 +-
30
tests/qemu-iotests/137 | 2 +-
31
tests/qemu-iotests/138 | 3 +--
32
tests/qemu-iotests/175 | 2 +-
33
tests/qemu-iotests/190 | 2 +-
34
tests/qemu-iotests/191 | 3 +--
35
tests/qemu-iotests/220 | 4 ++-
36
tests/qemu-iotests/243 | 6 +++--
37
tests/qemu-iotests/244 | 10 +++++---
38
tests/qemu-iotests/250 | 3 +--
39
tests/qemu-iotests/265 | 2 +-
40
22 files changed, 100 insertions(+), 101 deletions(-)
41
13
42
diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031
14
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
43
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
44
--- a/tests/qemu-iotests/031
16
--- a/include/block/block-copy.h
45
+++ b/tests/qemu-iotests/031
17
+++ b/include/block/block-copy.h
46
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
18
@@ -XXX,XX +XXX,XX @@
47
# This tests qcow2-specific low-level functionality
19
#include "block/block.h"
48
_supported_fmt qcow2
20
#include "qemu/co-shared-resource.h"
49
_supported_proto file
21
50
+# We want to test compat=0.10, which does not support refcount widths
22
-typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
51
+# other than 16
23
typedef void (*BlockCopyAsyncCallbackFunc)(void *opaque);
52
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
24
typedef struct BlockCopyState BlockCopyState;
53
25
typedef struct BlockCopyCallState BlockCopyCallState;
54
CLUSTER_SIZE=65536
26
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
55
27
BdrvRequestFlags write_flags,
56
# qcow2.py output depends on the exact options used, so override the command
28
Error **errp);
57
# line here as an exception
29
58
-for IMGOPTS in "compat=0.10" "compat=1.1"; do
30
-void block_copy_set_progress_callback(
59
+for compat in "compat=0.10" "compat=1.1"; do
31
- BlockCopyState *s,
60
32
- ProgressBytesCallbackFunc progress_bytes_callback,
61
echo
33
- void *progress_opaque);
62
- echo ===== Testing with -o $IMGOPTS =====
34
-
63
+ echo ===== Testing with -o $compat =====
35
void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
64
echo
36
65
echo === Create image with unknown header extension ===
37
void block_copy_state_free(BlockCopyState *s);
66
echo
38
diff --git a/block/block-copy.c b/block/block-copy.c
67
- _make_test_img 64M
39
index XXXXXXX..XXXXXXX 100644
68
+ _make_test_img -o $compat 64M
40
--- a/block/block-copy.c
69
$PYTHON qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension"
41
+++ b/block/block-copy.c
70
$PYTHON qcow2.py "$TEST_IMG" dump-header
42
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
71
_check_test_img
43
bool skip_unallocated;
72
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
44
73
index XXXXXXX..XXXXXXX 100755
45
ProgressMeter *progress;
74
--- a/tests/qemu-iotests/039
46
- /* progress_bytes_callback: called when some copying progress is done. */
75
+++ b/tests/qemu-iotests/039
47
- ProgressBytesCallbackFunc progress_bytes_callback;
76
@@ -XXX,XX +XXX,XX @@ size=128M
48
- void *progress_opaque;
77
echo
49
78
echo "== Checking that image is clean on shutdown =="
50
SharedResource *mem;
79
51
80
-IMGOPTS="compat=1.1,lazy_refcounts=on"
52
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
81
-_make_test_img $size
53
return s;
82
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
83
84
$QEMU_IO -c "write -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
85
86
@@ -XXX,XX +XXX,XX @@ _check_test_img
87
echo
88
echo "== Creating a dirty image file =="
89
90
-IMGOPTS="compat=1.1,lazy_refcounts=on"
91
-_make_test_img $size
92
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
93
94
_NO_VALGRIND \
95
$QEMU_IO -c "write -P 0x5a 0 512" \
96
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
97
echo
98
echo "== Opening a dirty image read/write should repair it =="
99
100
-IMGOPTS="compat=1.1,lazy_refcounts=on"
101
-_make_test_img $size
102
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
103
104
_NO_VALGRIND \
105
$QEMU_IO -c "write -P 0x5a 0 512" \
106
@@ -XXX,XX +XXX,XX @@ $PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
107
echo
108
echo "== Creating an image file with lazy_refcounts=off =="
109
110
-IMGOPTS="compat=1.1,lazy_refcounts=off"
111
-_make_test_img $size
112
+_make_test_img -o "compat=1.1,lazy_refcounts=off" $size
113
114
_NO_VALGRIND \
115
$QEMU_IO -c "write -P 0x5a 0 512" \
116
@@ -XXX,XX +XXX,XX @@ _check_test_img
117
echo
118
echo "== Committing to a backing file with lazy_refcounts=on =="
119
120
-IMGOPTS="compat=1.1,lazy_refcounts=on"
121
-TEST_IMG="$TEST_IMG".base _make_test_img $size
122
+TEST_IMG="$TEST_IMG".base _make_test_img -o "compat=1.1,lazy_refcounts=on" $size
123
124
-IMGOPTS="compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base"
125
-_make_test_img $size
126
+_make_test_img -o "compat=1.1,lazy_refcounts=on,backing_file=$TEST_IMG.base" $size
127
128
$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io
129
$QEMU_IMG commit "$TEST_IMG"
130
@@ -XXX,XX +XXX,XX @@ TEST_IMG="$TEST_IMG".base _check_test_img
131
echo
132
echo "== Changing lazy_refcounts setting at runtime =="
133
134
-IMGOPTS="compat=1.1,lazy_refcounts=off"
135
-_make_test_img $size
136
+_make_test_img -o "compat=1.1,lazy_refcounts=off" $size
137
138
_NO_VALGRIND \
139
$QEMU_IO -c "reopen -o lazy-refcounts=on" \
140
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "reopen -o lazy-refcounts=on" \
141
$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
142
_check_test_img
143
144
-IMGOPTS="compat=1.1,lazy_refcounts=on"
145
-_make_test_img $size
146
+_make_test_img -o "compat=1.1,lazy_refcounts=on" $size
147
148
_NO_VALGRIND \
149
$QEMU_IO -c "reopen -o lazy-refcounts=off" \
150
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
151
index XXXXXXX..XXXXXXX 100755
152
--- a/tests/qemu-iotests/059
153
+++ b/tests/qemu-iotests/059
154
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
155
156
echo
157
echo "=== Testing monolithicFlat creation and opening ==="
158
-IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
159
+_make_test_img -o "subformat=monolithicFlat" 2G
160
_img_info
161
_cleanup_test_img
162
163
echo
164
echo "=== Testing monolithicFlat with zeroed_grain ==="
165
-IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G
166
+_make_test_img -o "subformat=monolithicFlat,zeroed_grain=on" 2G
167
_cleanup_test_img
168
169
echo
170
echo "=== Testing big twoGbMaxExtentFlat ==="
171
-IMGOPTS="subformat=twoGbMaxExtentFlat" _make_test_img 1000G
172
+_make_test_img -o "subformat=twoGbMaxExtentFlat" 1000G
173
$QEMU_IMG info $TEST_IMG | _filter_testdir | sed -e 's/cid: [0-9]*/cid: XXXXXXXX/'
174
_cleanup_test_img
175
176
@@ -XXX,XX +XXX,XX @@ _img_info
177
178
echo
179
echo "=== Testing truncated sparse ==="
180
-IMGOPTS="subformat=monolithicSparse" _make_test_img 100G
181
+_make_test_img -o "subformat=monolithicSparse" 100G
182
truncate -s 10M $TEST_IMG
183
_img_info
184
185
echo
186
echo "=== Converting to streamOptimized from image with small cluster size==="
187
-TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 IMGOPTS="cluster_size=4096" _make_test_img 1G
188
+TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 _make_test_img -o "cluster_size=4096" 1G
189
$QEMU_IO -f qcow2 -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io
190
$QEMU_IO -f qcow2 -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io
191
$QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2" "$TEST_IMG" 2>&1
192
@@ -XXX,XX +XXX,XX @@ echo "=== Testing monolithicFlat with internally generated JSON file name ==="
193
194
echo '--- blkdebug ---'
195
# Should work, because bdrv_dirname() works fine with blkdebug
196
-IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
197
+_make_test_img -o "subformat=monolithicFlat" 64M
198
$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" \
199
-c info \
200
2>&1 \
201
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img
202
203
echo '--- quorum ---'
204
# Should not work, because bdrv_dirname() does not work with quorum
205
-IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
206
+_make_test_img -o "subformat=monolithicFlat" 64M
207
cp "$TEST_IMG" "$TEST_IMG.orig"
208
209
filename="json:{
210
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img
211
212
echo
213
echo "=== Testing 4TB monolithicFlat creation and IO ==="
214
-IMGOPTS="subformat=monolithicFlat" _make_test_img 4T
215
+_make_test_img -o "subformat=monolithicFlat" 4T
216
_img_info
217
$QEMU_IO -c "write -P 0xa 900G 512" "$TEST_IMG" | _filter_qemu_io
218
$QEMU_IO -c "read -v 900G 1024" "$TEST_IMG" | _filter_qemu_io
219
@@ -XXX,XX +XXX,XX @@ _cleanup_test_img
220
echo
221
echo "=== Testing qemu-img map on extents ==="
222
for fmt in monolithicSparse twoGbMaxExtentSparse; do
223
- IMGOPTS="subformat=$fmt" _make_test_img 31G
224
+ _make_test_img -o "subformat=$fmt" 31G
225
$QEMU_IO -c "write 65024 1k" "$TEST_IMG" | _filter_qemu_io
226
$QEMU_IO -c "write 2147483136 1k" "$TEST_IMG" | _filter_qemu_io
227
$QEMU_IO -c "write 5G 1k" "$TEST_IMG" | _filter_qemu_io
228
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
229
index XXXXXXX..XXXXXXX 100755
230
--- a/tests/qemu-iotests/060
231
+++ b/tests/qemu-iotests/060
232
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'write 0k 64k' "$BACKING_IMG" | _filter_qemu_io
233
# compat=0.10 is required in order to make the following discard actually
234
# unallocate the sector rather than make it a zero sector - we want COW, after
235
# all.
236
-IMGOPTS='compat=0.10' _make_test_img -b "$BACKING_IMG" 1G
237
+_make_test_img -o 'compat=0.10' -b "$BACKING_IMG" 1G
238
# Write two clusters, the second one enforces creation of an L2 table after
239
# the first data cluster.
240
$QEMU_IO -c 'write 0k 64k' -c 'write 512M 64k' "$TEST_IMG" | _filter_qemu_io
241
@@ -XXX,XX +XXX,XX @@ echo
242
echo "=== Discarding a non-covered in-bounds refblock ==="
243
echo
244
245
-IMGOPTS='refcount_bits=1' _make_test_img 64M
246
+_make_test_img -o 'refcount_bits=1' 64M
247
248
# Pretend there's a refblock somewhere where there is no refblock to
249
# cover it (but the covering refblock has a valid index in the
250
@@ -XXX,XX +XXX,XX @@ echo
251
echo "=== Discarding a refblock covered by an unaligned refblock ==="
252
echo
253
254
-IMGOPTS='refcount_bits=1' _make_test_img 64M
255
+_make_test_img -o 'refcount_bits=1' 64M
256
257
# Same as above
258
poke_file "$TEST_IMG" "$(($rt_offset+8))" "\x00\x00\x00\x10\x00\x00\x00\x00"
259
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
260
index XXXXXXX..XXXXXXX 100755
261
--- a/tests/qemu-iotests/061
262
+++ b/tests/qemu-iotests/061
263
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
264
_supported_fmt qcow2
265
_supported_proto file
266
_supported_os Linux
267
+# Conversion between different compat versions can only really work
268
+# with refcount_bits=16
269
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
270
271
echo
272
echo "=== Testing version downgrade with zero expansion ==="
273
echo
274
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
275
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
276
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
277
$PYTHON qcow2.py "$TEST_IMG" dump-header
278
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
279
@@ -XXX,XX +XXX,XX @@ _check_test_img
280
echo
281
echo "=== Testing version downgrade with zero expansion and 4K cache entries ==="
282
echo
283
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
284
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
285
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
286
$QEMU_IO -c "write -z 32M 128k" "$TEST_IMG" | _filter_qemu_io
287
$QEMU_IO -c map "$TEST_IMG" | _filter_qemu_io
288
@@ -XXX,XX +XXX,XX @@ _check_test_img
289
echo
290
echo "=== Testing dirty version downgrade ==="
291
echo
292
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
293
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
294
_NO_VALGRIND \
295
$QEMU_IO -c "write -P 0x2a 0 128k" -c flush \
296
-c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io
297
@@ -XXX,XX +XXX,XX @@ _check_test_img
298
echo
299
echo "=== Testing version downgrade with unknown compat/autoclear flags ==="
300
echo
301
-IMGOPTS="compat=1.1" _make_test_img 64M
302
+_make_test_img -o "compat=1.1" 64M
303
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit compatible 42
304
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 42
305
$PYTHON qcow2.py "$TEST_IMG" dump-header
306
@@ -XXX,XX +XXX,XX @@ _check_test_img
307
echo
308
echo "=== Testing version upgrade and resize ==="
309
echo
310
-IMGOPTS="compat=0.10" _make_test_img 64M
311
+_make_test_img -o "compat=0.10" 64M
312
$QEMU_IO -c "write -P 0x2a 42M 64k" "$TEST_IMG" | _filter_qemu_io
313
$PYTHON qcow2.py "$TEST_IMG" dump-header
314
$QEMU_IMG amend -o "compat=1.1,lazy_refcounts=on,size=128M" "$TEST_IMG"
315
@@ -XXX,XX +XXX,XX @@ _check_test_img
316
echo
317
echo "=== Testing dirty lazy_refcounts=off ==="
318
echo
319
-IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
320
+_make_test_img -o "compat=1.1,lazy_refcounts=on" 64M
321
_NO_VALGRIND \
322
$QEMU_IO -c "write -P 0x2a 0 128k" -c flush \
323
-c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io
324
@@ -XXX,XX +XXX,XX @@ _check_test_img
325
echo
326
echo "=== Testing backing file ==="
327
echo
328
-IMGOPTS="compat=1.1" _make_test_img 64M
329
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
330
+_make_test_img -o "compat=1.1" 64M
331
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
332
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
333
$QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
334
$QEMU_IMG amend -o "backing_file=$TEST_IMG.base,backing_fmt=qcow2" "$TEST_IMG"
335
@@ -XXX,XX +XXX,XX @@ _check_test_img
336
echo
337
echo "=== Testing invalid configurations ==="
338
echo
339
-IMGOPTS="compat=0.10" _make_test_img 64M
340
+_make_test_img -o "compat=0.10" 64M
341
$QEMU_IMG amend -o "lazy_refcounts=on" "$TEST_IMG"
342
$QEMU_IMG amend -o "compat=1.1" "$TEST_IMG" # actually valid
343
$QEMU_IMG amend -o "compat=0.10,lazy_refcounts=on" "$TEST_IMG"
344
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG amend -o "preallocation=on" "$TEST_IMG"
345
echo
346
echo "=== Testing correct handling of unset value ==="
347
echo
348
-IMGOPTS="compat=1.1,cluster_size=1k" _make_test_img 64M
349
+_make_test_img -o "compat=1.1,cluster_size=1k" 64M
350
echo "Should work:"
351
$QEMU_IMG amend -o "lazy_refcounts=on" "$TEST_IMG"
352
echo "Should not work:" # Just to know which of these tests actually fails
353
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG amend -o "cluster_size=64k" "$TEST_IMG"
354
echo
355
echo "=== Testing zero expansion on inactive clusters ==="
356
echo
357
-IMGOPTS="compat=1.1" _make_test_img 64M
358
+_make_test_img -o "compat=1.1" 64M
359
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
360
$QEMU_IMG snapshot -c foo "$TEST_IMG"
361
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG" | _filter_qemu_io
362
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
363
echo
364
echo "=== Testing zero expansion on shared L2 table ==="
365
echo
366
-IMGOPTS="compat=1.1" _make_test_img 64M
367
+_make_test_img -o "compat=1.1" 64M
368
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
369
$QEMU_IMG snapshot -c foo "$TEST_IMG"
370
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
371
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
372
echo
373
echo "=== Testing zero expansion on backed image ==="
374
echo
375
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
376
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
377
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
378
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
379
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
380
$QEMU_IO -c "read -P 0x2a 0 128k" -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io
381
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
382
_check_test_img
383
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 64k" -c "read -P 0x2a 64k 64k" "$TEST_IMG" | _filter_qe
384
echo
385
echo "=== Testing zero expansion on backed inactive clusters ==="
386
echo
387
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
388
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
389
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
390
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
391
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
392
$QEMU_IO -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io
393
$QEMU_IMG snapshot -c foo "$TEST_IMG"
394
$QEMU_IO -c "write -P 0x42 0 128k" "$TEST_IMG" | _filter_qemu_io
395
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 64k" -c "read -P 0x2a 64k 64k" "$TEST_IMG" | _filter_qe
396
echo
397
echo "=== Testing zero expansion on backed image with shared L2 table ==="
398
echo
399
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M
400
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 64M
401
$QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io
402
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M
403
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 64M
404
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
405
$QEMU_IMG snapshot -c foo "$TEST_IMG"
406
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
407
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
408
echo
409
echo "=== Testing preallocated zero expansion on full image ==="
410
echo
411
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG" _make_test_img 64M
412
+TEST_IMG="$TEST_IMG" _make_test_img -o "compat=1.1" 64M
413
$QEMU_IO -c "write -P 0x2a 0 64M" "$TEST_IMG" -c "write -z 0 64M" | _filter_qemu_io
414
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
415
_check_test_img
416
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 0 64M" "$TEST_IMG" | _filter_qemu_io
417
echo
418
echo "=== Testing progress report without snapshot ==="
419
echo
420
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 4G
421
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 4G
422
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 4G
423
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 4G
424
$QEMU_IO -c "write -z 0 64k" \
425
-c "write -z 1G 64k" \
426
-c "write -z 2G 64k" \
427
@@ -XXX,XX +XXX,XX @@ _check_test_img
428
echo
429
echo "=== Testing progress report with snapshot ==="
430
echo
431
-IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 4G
432
-IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 4G
433
+TEST_IMG="$TEST_IMG.base" _make_test_img -o "compat=1.1" 4G
434
+_make_test_img -o "compat=1.1" -b "$TEST_IMG.base" 4G
435
$QEMU_IO -c "write -z 0 64k" \
436
-c "write -z 1G 64k" \
437
-c "write -z 2G 64k" \
438
@@ -XXX,XX +XXX,XX @@ _check_test_img
439
echo
440
echo "=== Testing version downgrade with external data file ==="
441
echo
442
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data" _make_test_img 64M
443
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
444
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
445
_img_info --format-specific
446
_check_test_img
447
@@ -XXX,XX +XXX,XX @@ _check_test_img
448
echo
449
echo "=== Try changing the external data file ==="
450
echo
451
-IMGOPTS="compat=1.1" _make_test_img 64M
452
+_make_test_img -o "compat=1.1" 64M
453
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
454
455
echo
456
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data" _make_test_img 64M
457
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
458
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
459
_img_info --format-specific
460
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
461
@@ -XXX,XX +XXX,XX @@ TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info -
462
echo
463
echo "=== Clearing and setting data-file-raw ==="
464
echo
465
-IMGOPTS="compat=1.1,data_file=$TEST_IMG.data,data_file_raw=on" _make_test_img 64M
466
+_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data,data_file_raw=on" 64M
467
$QEMU_IMG amend -o "data_file_raw=on" "$TEST_IMG"
468
_img_info --format-specific
469
_check_test_img
470
diff --git a/tests/qemu-iotests/079 b/tests/qemu-iotests/079
471
index XXXXXXX..XXXXXXX 100755
472
--- a/tests/qemu-iotests/079
473
+++ b/tests/qemu-iotests/079
474
@@ -XXX,XX +XXX,XX @@ echo
475
cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304"
476
477
for s in $cluster_sizes; do
478
- IMGOPTS=$(_optstr_add "$IMGOPTS" "preallocation=metadata,cluster_size=$s") \
479
- _make_test_img 4G
480
+ _make_test_img -o "preallocation=metadata,cluster_size=$s" 4G
481
done
482
483
# success, all done
484
diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106
485
index XXXXXXX..XXXXXXX 100755
486
--- a/tests/qemu-iotests/106
487
+++ b/tests/qemu-iotests/106
488
@@ -XXX,XX +XXX,XX @@ for create_mode in off falloc full; do
489
echo
490
echo "--- create_mode=$create_mode growth_mode=$growth_mode ---"
491
492
- IMGOPTS="preallocation=$create_mode" _make_test_img ${CREATION_SIZE}K
493
+ _make_test_img -o "preallocation=$create_mode" ${CREATION_SIZE}K
494
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
495
496
expected_size=0
497
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
498
index XXXXXXX..XXXXXXX 100755
499
--- a/tests/qemu-iotests/108
500
+++ b/tests/qemu-iotests/108
501
@@ -XXX,XX +XXX,XX @@ echo
502
echo '=== Repairing unreferenced data cluster in new refblock area ==='
503
echo
504
505
-IMGOPTS='cluster_size=512' _make_test_img 64M
506
+_make_test_img -o 'cluster_size=512' 64M
507
# Allocate the first 128 kB in the image (first refblock)
508
$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io
509
# should be 131072 == 0x20000
510
diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112
511
index XXXXXXX..XXXXXXX 100755
512
--- a/tests/qemu-iotests/112
513
+++ b/tests/qemu-iotests/112
514
@@ -XXX,XX +XXX,XX @@ echo '=== refcount_bits limits ==='
515
echo
516
517
# Must be positive (non-zero)
518
-IMGOPTS="$IMGOPTS,refcount_bits=0" _make_test_img 64M
519
+_make_test_img -o "refcount_bits=0" 64M
520
# Must be positive (non-negative)
521
-IMGOPTS="$IMGOPTS,refcount_bits=-1" _make_test_img 64M
522
+_make_test_img -o "refcount_bits=-1" 64M
523
# May not exceed 64
524
-IMGOPTS="$IMGOPTS,refcount_bits=128" _make_test_img 64M
525
+_make_test_img -o "refcount_bits=128" 64M
526
# Must be a power of two
527
-IMGOPTS="$IMGOPTS,refcount_bits=42" _make_test_img 64M
528
+_make_test_img -o "refcount_bits=42" 64M
529
530
# 1 is the minimum
531
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
532
+_make_test_img -o "refcount_bits=1" 64M
533
print_refcount_bits
534
535
# 64 is the maximum
536
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
537
+_make_test_img -o "refcount_bits=64" 64M
538
print_refcount_bits
539
540
# 16 is the default
541
@@ -XXX,XX +XXX,XX @@ echo '=== refcount_bits and compat=0.10 ==='
542
echo
543
544
# Should work
545
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=16" _make_test_img 64M
546
+_make_test_img -o "compat=0.10,refcount_bits=16" 64M
547
print_refcount_bits
548
549
# Should not work
550
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=1" _make_test_img 64M
551
-IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=64" _make_test_img 64M
552
+_make_test_img -o "compat=0.10,refcount_bits=1" 64M
553
+_make_test_img -o "compat=0.10,refcount_bits=64" 64M
554
555
556
echo
557
echo '=== Snapshot limit on refcount_bits=1 ==='
558
echo
559
560
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
561
+_make_test_img -o "refcount_bits=1" 64M
562
print_refcount_bits
563
564
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
565
@@ -XXX,XX +XXX,XX @@ echo
566
echo '=== Snapshot limit on refcount_bits=2 ==='
567
echo
568
569
-IMGOPTS="$IMGOPTS,refcount_bits=2" _make_test_img 64M
570
+_make_test_img -o "refcount_bits=2" 64M
571
print_refcount_bits
572
573
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
574
@@ -XXX,XX +XXX,XX @@ echo
575
echo '=== Compressed clusters with refcount_bits=1 ==='
576
echo
577
578
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
579
+_make_test_img -o "refcount_bits=1" 64M
580
print_refcount_bits
581
582
# Both should fit into a single host cluster; instead of failing to increase the
583
@@ -XXX,XX +XXX,XX @@ echo
584
echo '=== MSb set in 64 bit refcount ==='
585
echo
586
587
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
588
+_make_test_img -o "refcount_bits=64" 64M
589
print_refcount_bits
590
591
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
592
@@ -XXX,XX +XXX,XX @@ echo
593
echo '=== Snapshot on maximum 64 bit refcount value ==='
594
echo
595
596
-IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
597
+_make_test_img -o "refcount_bits=64" 64M
598
print_refcount_bits
599
600
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
601
@@ -XXX,XX +XXX,XX @@ echo
602
echo '=== Testing too many references for check ==='
603
echo
604
605
-IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
606
+_make_test_img -o "refcount_bits=1" 64M
607
print_refcount_bits
608
609
# This cluster should be created at 0x50000
610
@@ -XXX,XX +XXX,XX @@ echo
611
echo '=== Multiple walks necessary during amend ==='
612
echo
613
614
-IMGOPTS="$IMGOPTS,refcount_bits=1,cluster_size=512" _make_test_img 64k
615
+_make_test_img -o "refcount_bits=1,cluster_size=512" 64k
616
617
# Cluster 0 is the image header, clusters 1 to 4 are used by the L1 table, a
618
# single L2 table, the reftable and a single refblock. This creates 58 data
619
diff --git a/tests/qemu-iotests/115 b/tests/qemu-iotests/115
620
index XXXXXXX..XXXXXXX 100755
621
--- a/tests/qemu-iotests/115
622
+++ b/tests/qemu-iotests/115
623
@@ -XXX,XX +XXX,XX @@ echo
624
# least 256 MB. We can achieve that by using preallocation=metadata for an image
625
# which has a guest disk size of 256 MB.
626
627
-IMGOPTS="$IMGOPTS,refcount_bits=64,cluster_size=512,preallocation=metadata" \
628
- _make_test_img 256M
629
+_make_test_img -o "refcount_bits=64,cluster_size=512,preallocation=metadata" 256M
630
631
# We know for sure that the L1 and refcount tables do not overlap with any other
632
# structure because the metadata overlap checks would have caught that case.
633
diff --git a/tests/qemu-iotests/121 b/tests/qemu-iotests/121
634
index XXXXXXX..XXXXXXX 100755
635
--- a/tests/qemu-iotests/121
636
+++ b/tests/qemu-iotests/121
637
@@ -XXX,XX +XXX,XX @@ echo
638
# Preallocation speeds up the write operation, but preallocating everything will
639
# destroy the purpose of the write; so preallocate one KB less than what would
640
# cause a reftable growth...
641
-IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64512K
642
+_make_test_img -o 'preallocation=metadata,cluster_size=1k' 64512K
643
# ...and make the image the desired size afterwards.
644
$QEMU_IMG resize "$TEST_IMG" 65M
645
646
@@ -XXX,XX +XXX,XX @@ echo
647
echo '--- Test 2 ---'
648
echo
649
650
-IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64513K
651
+_make_test_img -o 'preallocation=metadata,cluster_size=1k' 64513K
652
# This results in an L1 table growth which in turn results in some clusters at
653
# the start of the image becoming free
654
$QEMU_IMG resize "$TEST_IMG" 65M
655
@@ -XXX,XX +XXX,XX @@ echo
656
echo '=== Allocating a new refcount block must not leave holes in the image ==='
657
echo
658
659
-IMGOPTS='cluster_size=512,refcount_bits=16' _make_test_img 1M
660
+_make_test_img -o 'cluster_size=512,refcount_bits=16' 1M
661
662
# This results in an image with 256 used clusters: the qcow2 header,
663
# the refcount table, one refcount block, the L1 table, four L2 tables
664
diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125
665
index XXXXXXX..XXXXXXX 100755
666
--- a/tests/qemu-iotests/125
667
+++ b/tests/qemu-iotests/125
668
@@ -XXX,XX +XXX,XX @@ for GROWTH_SIZE in 16 48 80; do
669
for growth_mode in off metadata falloc full; do
670
echo "--- cluster_size=$cluster_size growth_size=$GROWTH_SIZE create_mode=$create_mode growth_mode=$growth_mode ---"
671
672
- IMGOPTS="preallocation=$create_mode,cluster_size=$cluster_size" _make_test_img ${CREATION_SIZE}
673
+ _make_test_img -o "preallocation=$create_mode,cluster_size=$cluster_size" ${CREATION_SIZE}
674
$QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K
675
676
host_size_0=$(get_image_size_on_host)
677
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
678
index XXXXXXX..XXXXXXX 100755
679
--- a/tests/qemu-iotests/137
680
+++ b/tests/qemu-iotests/137
681
@@ -XXX,XX +XXX,XX @@ $QEMU_IO \
682
-c "reopen -o cache-clean-interval=-1" \
683
"$TEST_IMG" | _filter_qemu_io
684
685
-IMGOPTS="cluster_size=256k" _make_test_img 32P
686
+_make_test_img -o "cluster_size=256k" 32P
687
$QEMU_IO \
688
-c "reopen -o l2-cache-entry-size=512,l2-cache-size=1T" \
689
"$TEST_IMG" | _filter_qemu_io
690
diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138
691
index XXXXXXX..XXXXXXX 100755
692
--- a/tests/qemu-iotests/138
693
+++ b/tests/qemu-iotests/138
694
@@ -XXX,XX +XXX,XX @@ echo
695
echo '=== Check on an image with a multiple of 2^32 clusters ==='
696
echo
697
698
-IMGOPTS=$(_optstr_add "$IMGOPTS" "cluster_size=512") \
699
- _make_test_img 512
700
+_make_test_img -o "cluster_size=512" 512
701
702
# Allocate L2 table
703
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
704
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
705
index XXXXXXX..XXXXXXX 100755
706
--- a/tests/qemu-iotests/175
707
+++ b/tests/qemu-iotests/175
708
@@ -XXX,XX +XXX,XX @@ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_block
709
for mode in off full falloc; do
710
echo
711
echo "== creating image with preallocation $mode =="
712
- IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt
713
+ _make_test_img -o preallocation=$mode $size | _filter_imgfmt
714
stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
715
done
716
717
diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190
718
index XXXXXXX..XXXXXXX 100755
719
--- a/tests/qemu-iotests/190
720
+++ b/tests/qemu-iotests/190
721
@@ -XXX,XX +XXX,XX @@ _supported_proto file
722
echo "== Huge file =="
723
echo
724
725
-IMGOPTS='cluster_size=2M' _make_test_img 2T
726
+_make_test_img -o 'cluster_size=2M' 2T
727
728
$QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG"
729
$QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG"
730
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
731
index XXXXXXX..XXXXXXX 100755
732
--- a/tests/qemu-iotests/191
733
+++ b/tests/qemu-iotests/191
734
@@ -XXX,XX +XXX,XX @@ echo === Preparing and starting VM ===
735
echo
736
737
TEST_IMG="${TEST_IMG}.base" _make_test_img $size
738
-IMGOPTS=$(_optstr_add "$IMGOPTS" "backing_fmt=$IMGFMT") \
739
- TEST_IMG="${TEST_IMG}.mid" _make_test_img -b "${TEST_IMG}.base"
740
+TEST_IMG="${TEST_IMG}.mid" _make_test_img -o "backing_fmt=$IMGFMT" -b "${TEST_IMG}.base"
741
_make_test_img -b "${TEST_IMG}.mid"
742
TEST_IMG="${TEST_IMG}.ovl2" _make_test_img -b "${TEST_IMG}.mid"
743
744
diff --git a/tests/qemu-iotests/220 b/tests/qemu-iotests/220
745
index XXXXXXX..XXXXXXX 100755
746
--- a/tests/qemu-iotests/220
747
+++ b/tests/qemu-iotests/220
748
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
749
_supported_fmt qcow2
750
_supported_proto file
751
_supported_os Linux
752
+# To use a different refcount width but 16 bits we need compat=1.1
753
+_unsupported_imgopts 'compat=0.10'
754
755
echo "== Creating huge file =="
756
757
@@ -XXX,XX +XXX,XX @@ echo "== Creating huge file =="
758
# of a HUGE (but very sparse) file. tmpfs works, ext4 does not.
759
_require_large_file 513T
760
761
-IMGOPTS='cluster_size=2M,refcount_bits=1' _make_test_img 513T
762
+_make_test_img -o 'cluster_size=2M,refcount_bits=1' 513T
763
764
echo "== Populating refcounts =="
765
# We want an image with 256M refcounts * 2M clusters = 512T referenced.
766
diff --git a/tests/qemu-iotests/243 b/tests/qemu-iotests/243
767
index XXXXXXX..XXXXXXX 100755
768
--- a/tests/qemu-iotests/243
769
+++ b/tests/qemu-iotests/243
770
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
771
_supported_fmt qcow2
772
_supported_proto file
773
_supported_os Linux
774
+# External data files do not work with compat=0.10
775
+_unsupported_imgopts 'compat=0.10'
776
777
for mode in off metadata falloc full; do
778
779
@@ -XXX,XX +XXX,XX @@ for mode in off metadata falloc full; do
780
echo "=== preallocation=$mode ==="
781
echo
782
783
- IMGOPTS="preallocation=$mode" _make_test_img 64M
784
+ _make_test_img -o "preallocation=$mode" 64M
785
786
printf "File size: "
787
du -b $TEST_IMG | cut -f1
788
@@ -XXX,XX +XXX,XX @@ for mode in off metadata falloc full; do
789
echo "=== External data file: preallocation=$mode ==="
790
echo
791
792
- IMGOPTS="data_file=$TEST_IMG.data,preallocation=$mode" _make_test_img 64M
793
+ _make_test_img -o "data_file=$TEST_IMG.data,preallocation=$mode" 64M
794
795
echo -n "qcow2 file size: "
796
du -b $TEST_IMG | cut -f1
797
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
798
index XXXXXXX..XXXXXXX 100755
799
--- a/tests/qemu-iotests/244
800
+++ b/tests/qemu-iotests/244
801
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
802
_supported_fmt qcow2
803
_supported_proto file
804
_supported_os Linux
805
+# External data files do not work with compat=0.10
806
+_unsupported_imgopts 'compat=0.10'
807
808
echo
809
echo "=== Create and open image with external data file ==="
810
echo
811
812
echo "With data file name in the image:"
813
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
814
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
815
_check_test_img
816
817
$QEMU_IO -c "open $TEST_IMG" -c "read -P 0 0 64k" 2>&1 | _filter_qemu_io | _filter_testdir
818
@@ -XXX,XX +XXX,XX @@ echo
819
echo "=== Standalone image with external data file (efficient) ==="
820
echo
821
822
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
823
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
824
825
echo -n "qcow2 file size before I/O: "
826
du -b $TEST_IMG | cut -f1
827
@@ -XXX,XX +XXX,XX @@ echo
828
echo "=== Standalone image with external data file (valid raw) ==="
829
echo
830
831
-IMGOPTS="data_file=$TEST_IMG.data,data_file_raw=on" _make_test_img 64M
832
+_make_test_img -o "data_file=$TEST_IMG.data,data_file_raw=on" 64M
833
834
echo -n "qcow2 file size before I/O: "
835
du -b $TEST_IMG | cut -f1
836
@@ -XXX,XX +XXX,XX @@ echo
837
echo "=== bdrv_co_block_status test for file and offset=0 ==="
838
echo
839
840
-IMGOPTS="data_file=$TEST_IMG.data" _make_test_img 64M
841
+_make_test_img -o "data_file=$TEST_IMG.data" 64M
842
843
$QEMU_IO -c 'write -P 0x11 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
844
$QEMU_IO -c 'read -P 0x11 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
845
diff --git a/tests/qemu-iotests/250 b/tests/qemu-iotests/250
846
index XXXXXXX..XXXXXXX 100755
847
--- a/tests/qemu-iotests/250
848
+++ b/tests/qemu-iotests/250
849
@@ -XXX,XX +XXX,XX @@ disk_usage()
850
}
54
}
851
55
852
size=2100M
56
-void block_copy_set_progress_callback(
853
-IMGOPTS="cluster_size=1M,preallocation=metadata"
57
- BlockCopyState *s,
854
58
- ProgressBytesCallbackFunc progress_bytes_callback,
855
-_make_test_img $size
59
- void *progress_opaque)
856
+_make_test_img -o "cluster_size=1M,preallocation=metadata" $size
60
-{
857
$QEMU_IO -c 'discard 0 10M' -c 'discard 2090M 10M' \
61
- s->progress_bytes_callback = progress_bytes_callback;
858
-c 'write 2090M 10M' -c 'write 0 10M' "$TEST_IMG" | _filter_qemu_io
62
- s->progress_opaque = progress_opaque;
859
63
-}
860
diff --git a/tests/qemu-iotests/265 b/tests/qemu-iotests/265
64
-
861
index XXXXXXX..XXXXXXX 100755
65
void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm)
862
--- a/tests/qemu-iotests/265
66
{
863
+++ b/tests/qemu-iotests/265
67
s->progress = pm;
864
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
68
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
865
echo '--- Writing to the image ---'
69
t->call_state->error_is_read = error_is_read;
866
70
} else {
867
# Reduce cluster size so we get more and quicker I/O
71
progress_work_done(t->s->progress, t->bytes);
868
-IMGOPTS='cluster_size=4096' _make_test_img 1M
72
- if (t->s->progress_bytes_callback) {
869
+_make_test_img -o 'cluster_size=4096' 1M
73
- t->s->progress_bytes_callback(t->bytes, t->s->progress_opaque);
870
(for ((kb = 1024 - 4; kb >= 0; kb -= 4)); do \
74
- }
871
echo "aio_write -P 42 $((kb + 1))k 2k"; \
75
}
872
done) \
76
co_put_to_shres(t->s->mem, t->bytes);
77
block_copy_task_end(t, ret);
873
--
78
--
874
2.24.1
79
2.29.2
875
80
876
81
diff view generated by jsdifflib
1
When dropping backup-top, we need to drain the node before freeing the
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
BlockCopyState. Otherwise, requests may still be in flight and then the
3
assertion in shres_destroy() will fail.
4
2
5
(This becomes visible in intermittent failure of 056.)
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Cc: qemu-stable@nongnu.org
5
Message-Id: <20210116214705.822267-21-vsementsov@virtuozzo.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20191219182638.104621-1-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
7
---
12
block/backup-top.c | 4 ++--
8
include/block/block-copy.h | 2 +-
13
1 file changed, 2 insertions(+), 2 deletions(-)
9
block/backup-top.c | 2 +-
10
block/block-copy.c | 10 ++--------
11
3 files changed, 4 insertions(+), 10 deletions(-)
14
12
13
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block-copy.h
16
+++ b/include/block/block-copy.h
17
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
18
int64_t offset, int64_t *count);
19
20
int coroutine_fn block_copy(BlockCopyState *s, int64_t offset, int64_t bytes,
21
- bool ignore_ratelimit, bool *error_is_read);
22
+ bool ignore_ratelimit);
23
24
/*
25
* Run block-copy in a coroutine, create corresponding BlockCopyCallState
15
diff --git a/block/backup-top.c b/block/backup-top.c
26
diff --git a/block/backup-top.c b/block/backup-top.c
16
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
17
--- a/block/backup-top.c
28
--- a/block/backup-top.c
18
+++ b/block/backup-top.c
29
+++ b/block/backup-top.c
19
@@ -XXX,XX +XXX,XX @@ void bdrv_backup_top_drop(BlockDriverState *bs)
30
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
20
BDRVBackupTopState *s = bs->opaque;
31
off = QEMU_ALIGN_DOWN(offset, s->cluster_size);
21
AioContext *aio_context = bdrv_get_aio_context(bs);
32
end = QEMU_ALIGN_UP(offset + bytes, s->cluster_size);
22
33
23
- block_copy_state_free(s->bcs);
34
- return block_copy(s->bcs, off, end - off, true, NULL);
35
+ return block_copy(s->bcs, off, end - off, true);
36
}
37
38
static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
39
diff --git a/block/block-copy.c b/block/block-copy.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/block-copy.c
42
+++ b/block/block-copy.c
43
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
44
}
45
46
int coroutine_fn block_copy(BlockCopyState *s, int64_t start, int64_t bytes,
47
- bool ignore_ratelimit, bool *error_is_read)
48
+ bool ignore_ratelimit)
49
{
50
BlockCopyCallState call_state = {
51
.s = s,
52
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s, int64_t start, int64_t bytes,
53
.max_workers = BLOCK_COPY_MAX_WORKERS,
54
};
55
56
- int ret = block_copy_common(&call_state);
24
-
57
-
25
aio_context_acquire(aio_context);
58
- if (error_is_read && ret < 0) {
26
59
- *error_is_read = call_state.error_is_read;
27
bdrv_drained_begin(bs);
60
- }
28
61
-
29
+ block_copy_state_free(s->bcs);
62
- return ret;
30
+
63
+ return block_copy_common(&call_state);
31
s->active = false;
64
}
32
bdrv_child_refresh_perms(bs, bs->backing, &error_abort);
65
33
bdrv_replace_node(bs, backing_bs(bs), &error_abort);
66
static void coroutine_fn block_copy_async_co_entry(void *opaque)
34
--
67
--
35
2.24.1
68
2.29.2
36
69
37
70
diff view generated by jsdifflib
1
It did not matter before, but now that _make_test_img understands -o, we
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
should use it properly here.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20191107163708.833192-11-mreitz@redhat.com
5
Message-Id: <20210116214705.822267-22-vsementsov@virtuozzo.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
7
---
9
tests/qemu-iotests/051 | 2 +-
8
scripts/simplebench/bench_block_job.py | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
11
10
12
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
11
diff --git a/scripts/simplebench/bench_block_job.py b/scripts/simplebench/bench_block_job.py
13
index XXXXXXX..XXXXXXX 100755
12
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/051
13
--- a/scripts/simplebench/bench_block_job.py
15
+++ b/tests/qemu-iotests/051
14
+++ b/scripts/simplebench/bench_block_job.py
16
@@ -XXX,XX +XXX,XX @@ echo
15
@@ -XXX,XX +XXX,XX @@
17
echo === With version 2 images enabling lazy refcounts must fail ===
16
-#!/usr/bin/env python
18
echo
17
+#!/usr/bin/env python3
19
18
#
20
-_make_test_img -ocompat=0.10 $size
19
# Benchmark block jobs
21
+_make_test_img -o compat=0.10 $size
20
#
22
23
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on
24
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off
25
--
21
--
26
2.24.1
22
2.29.2
27
23
28
24
diff view generated by jsdifflib
1
This is useful for tests that want to whitelist fields from dump-header
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
(with grep) but still print all header extensions.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Add argument to allow additional block-job options.
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
4
6
Message-id: 20191107163708.833192-3-mreitz@redhat.com
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20210116214705.822267-23-vsementsov@virtuozzo.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
---
9
tests/qemu-iotests/qcow2.py | 5 +++++
10
scripts/simplebench/bench-example.py | 2 +-
10
1 file changed, 5 insertions(+)
11
scripts/simplebench/bench_block_job.py | 11 +++++++----
12
2 files changed, 8 insertions(+), 5 deletions(-)
11
13
12
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
14
diff --git a/scripts/simplebench/bench-example.py b/scripts/simplebench/bench-example.py
15
index XXXXXXX..XXXXXXX 100644
16
--- a/scripts/simplebench/bench-example.py
17
+++ b/scripts/simplebench/bench-example.py
18
@@ -XXX,XX +XXX,XX @@ from bench_block_job import bench_block_copy, drv_file, drv_nbd
19
20
def bench_func(env, case):
21
""" Handle one "cell" of benchmarking table. """
22
- return bench_block_copy(env['qemu_binary'], env['cmd'],
23
+ return bench_block_copy(env['qemu_binary'], env['cmd'], {}
24
case['source'], case['target'])
25
26
27
diff --git a/scripts/simplebench/bench_block_job.py b/scripts/simplebench/bench_block_job.py
13
index XXXXXXX..XXXXXXX 100755
28
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/qcow2.py
29
--- a/scripts/simplebench/bench_block_job.py
15
+++ b/tests/qemu-iotests/qcow2.py
30
+++ b/scripts/simplebench/bench_block_job.py
16
@@ -XXX,XX +XXX,XX @@ def cmd_dump_header(fd):
31
@@ -XXX,XX +XXX,XX @@ def bench_block_job(cmd, cmd_args, qemu_args):
17
h.dump()
32
18
h.dump_extensions()
33
19
34
# Bench backup or mirror
20
+def cmd_dump_header_exts(fd):
35
-def bench_block_copy(qemu_binary, cmd, source, target):
21
+ h = QcowHeader(fd)
36
+def bench_block_copy(qemu_binary, cmd, cmd_options, source, target):
22
+ h.dump_extensions()
37
"""Helper to run bench_block_job() for mirror or backup"""
38
assert cmd in ('blockdev-backup', 'blockdev-mirror')
39
40
source['node-name'] = 'source'
41
target['node-name'] = 'target'
42
43
- return bench_block_job(cmd,
44
- {'job-id': 'job0', 'device': 'source',
45
- 'target': 'target', 'sync': 'full'},
46
+ cmd_options['job-id'] = 'job0'
47
+ cmd_options['device'] = 'source'
48
+ cmd_options['target'] = 'target'
49
+ cmd_options['sync'] = 'full'
23
+
50
+
24
def cmd_set_header(fd, name, value):
51
+ return bench_block_job(cmd, cmd_options,
25
try:
52
[qemu_binary,
26
value = int(value, 0)
53
'-blockdev', json.dumps(source),
27
@@ -XXX,XX +XXX,XX @@ def cmd_set_feature_bit(fd, group, bit):
54
'-blockdev', json.dumps(target)])
28
29
cmds = [
30
[ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
31
+ [ 'dump-header-exts', cmd_dump_header_exts, 0, 'Dump image header extensions' ],
32
[ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
33
[ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
34
[ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ],
35
--
55
--
36
2.24.1
56
2.29.2
37
57
38
58
diff view generated by jsdifflib
1
Probably due to blind copy-pasting, we have several instances of "qocw2"
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
in our iotests. Fix them.
3
2
4
Reported-by: Maxim Levitsky <mlevitsk@redhat.com>
3
Add script to benchmark new backup architecture.
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
6
Message-id: 20191107163708.833192-2-mreitz@redhat.com
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-Id: <20210116214705.822267-24-vsementsov@virtuozzo.com>
8
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
7
[mreitz: s/not unsupported/not supported/]
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
9
---
11
tests/qemu-iotests/060 | 2 +-
10
scripts/simplebench/bench-backup.py | 167 ++++++++++++++++++++++++++++
12
tests/qemu-iotests/061 | 2 +-
11
1 file changed, 167 insertions(+)
13
tests/qemu-iotests/062 | 2 +-
12
create mode 100755 scripts/simplebench/bench-backup.py
14
tests/qemu-iotests/066 | 2 +-
15
tests/qemu-iotests/068 | 2 +-
16
tests/qemu-iotests/108 | 2 +-
17
tests/qemu-iotests/138 | 2 +-
18
tests/qemu-iotests/261 | 2 +-
19
8 files changed, 8 insertions(+), 8 deletions(-)
20
13
21
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
14
diff --git a/scripts/simplebench/bench-backup.py b/scripts/simplebench/bench-backup.py
22
index XXXXXXX..XXXXXXX 100755
15
new file mode 100755
23
--- a/tests/qemu-iotests/060
16
index XXXXXXX..XXXXXXX
24
+++ b/tests/qemu-iotests/060
17
--- /dev/null
25
@@ -XXX,XX +XXX,XX @@ _filter_io_error()
18
+++ b/scripts/simplebench/bench-backup.py
26
. ./common.rc
19
@@ -XXX,XX +XXX,XX @@
27
. ./common.filter
20
+#!/usr/bin/env python3
28
21
+#
29
-# This tests qocw2-specific low-level functionality
22
+# Bench backup block-job
30
+# This tests qcow2-specific low-level functionality
23
+#
31
_supported_fmt qcow2
24
+# Copyright (c) 2020 Virtuozzo International GmbH.
32
_supported_proto file
25
+#
33
_supported_os Linux
26
+# This program is free software; you can redistribute it and/or modify
34
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
27
+# it under the terms of the GNU General Public License as published by
35
index XXXXXXX..XXXXXXX 100755
28
+# the Free Software Foundation; either version 2 of the License, or
36
--- a/tests/qemu-iotests/061
29
+# (at your option) any later version.
37
+++ b/tests/qemu-iotests/061
30
+#
38
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
31
+# This program is distributed in the hope that it will be useful,
39
. ./common.rc
32
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
40
. ./common.filter
33
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
34
+# GNU General Public License for more details.
42
-# This tests qocw2-specific low-level functionality
35
+#
43
+# This tests qcow2-specific low-level functionality
36
+# You should have received a copy of the GNU General Public License
44
_supported_fmt qcow2
37
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
45
_supported_proto file
38
+#
46
_supported_os Linux
39
+
47
diff --git a/tests/qemu-iotests/062 b/tests/qemu-iotests/062
40
+import argparse
48
index XXXXXXX..XXXXXXX 100755
41
+import json
49
--- a/tests/qemu-iotests/062
42
+
50
+++ b/tests/qemu-iotests/062
43
+import simplebench
51
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
44
+from results_to_text import results_to_text
52
. ./common.rc
45
+from bench_block_job import bench_block_copy, drv_file, drv_nbd
53
. ./common.filter
46
+
54
47
+
55
-# This tests qocw2-specific low-level functionality
48
+def bench_func(env, case):
56
+# This tests qcow2-specific low-level functionality
49
+ """ Handle one "cell" of benchmarking table. """
57
_supported_fmt qcow2
50
+ cmd_options = env['cmd-options'] if 'cmd-options' in env else {}
58
_supported_proto generic
51
+ return bench_block_copy(env['qemu-binary'], env['cmd'],
59
52
+ cmd_options,
60
diff --git a/tests/qemu-iotests/066 b/tests/qemu-iotests/066
53
+ case['source'], case['target'])
61
index XXXXXXX..XXXXXXX 100755
54
+
62
--- a/tests/qemu-iotests/066
55
+
63
+++ b/tests/qemu-iotests/066
56
+def bench(args):
64
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
57
+ test_cases = []
65
. ./common.rc
58
+
66
. ./common.filter
59
+ sources = {}
67
60
+ targets = {}
68
-# This tests qocw2-specific low-level functionality
61
+ for d in args.dir:
69
+# This tests qcow2-specific low-level functionality
62
+ label, path = d.split(':') # paths with colon not supported
70
_supported_fmt qcow2
63
+ sources[label] = drv_file(path + '/test-source')
71
_supported_proto generic
64
+ targets[label] = drv_file(path + '/test-target')
72
65
+
73
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
66
+ if args.nbd:
74
index XXXXXXX..XXXXXXX 100755
67
+ nbd = args.nbd.split(':')
75
--- a/tests/qemu-iotests/068
68
+ host = nbd[0]
76
+++ b/tests/qemu-iotests/068
69
+ port = '10809' if len(nbd) == 1 else nbd[1]
77
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
70
+ drv = drv_nbd(host, port)
78
. ./common.rc
71
+ sources['nbd'] = drv
79
. ./common.filter
72
+ targets['nbd'] = drv
80
73
+
81
-# This tests qocw2-specific low-level functionality
74
+ for t in args.test:
82
+# This tests qcow2-specific low-level functionality
75
+ src, dst = t.split(':')
83
_supported_fmt qcow2
76
+
84
_supported_proto generic
77
+ test_cases.append({
85
78
+ 'id': t,
86
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
79
+ 'source': sources[src],
87
index XXXXXXX..XXXXXXX 100755
80
+ 'target': targets[dst]
88
--- a/tests/qemu-iotests/108
81
+ })
89
+++ b/tests/qemu-iotests/108
82
+
90
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
83
+ binaries = [] # list of (<label>, <path>, [<options>])
91
. ./common.rc
84
+ for i, q in enumerate(args.env):
92
. ./common.filter
85
+ name_path = q.split(':')
93
86
+ if len(name_path) == 1:
94
-# This tests qocw2-specific low-level functionality
87
+ label = f'q{i}'
95
+# This tests qcow2-specific low-level functionality
88
+ path_opts = name_path[0].split(',')
96
_supported_fmt qcow2
89
+ else:
97
_supported_proto file
90
+ assert len(name_path) == 2 # paths with colon not supported
98
_supported_os Linux
91
+ label = name_path[0]
99
diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138
92
+ path_opts = name_path[1].split(',')
100
index XXXXXXX..XXXXXXX 100755
93
+
101
--- a/tests/qemu-iotests/138
94
+ binaries.append((label, path_opts[0], path_opts[1:]))
102
+++ b/tests/qemu-iotests/138
95
+
103
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
96
+ test_envs = []
104
. ./common.rc
97
+
105
. ./common.filter
98
+ bin_paths = {}
106
99
+ for i, q in enumerate(args.env):
107
-# This tests qocw2-specific low-level functionality
100
+ opts = q.split(',')
108
+# This tests qcow2-specific low-level functionality
101
+ label_path = opts[0]
109
_supported_fmt qcow2
102
+ opts = opts[1:]
110
_supported_proto file
103
+
111
_supported_os Linux
104
+ if ':' in label_path:
112
diff --git a/tests/qemu-iotests/261 b/tests/qemu-iotests/261
105
+ # path with colon inside is not supported
113
index XXXXXXX..XXXXXXX 100755
106
+ label, path = label_path.split(':')
114
--- a/tests/qemu-iotests/261
107
+ bin_paths[label] = path
115
+++ b/tests/qemu-iotests/261
108
+ elif label_path in bin_paths:
116
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
109
+ label = label_path
117
. ./common.rc
110
+ path = bin_paths[label]
118
. ./common.filter
111
+ else:
119
112
+ path = label_path
120
-# This tests qocw2-specific low-level functionality
113
+ label = f'q{i}'
121
+# This tests qcow2-specific low-level functionality
114
+ bin_paths[label] = path
122
_supported_fmt qcow2
115
+
123
_supported_proto file
116
+ x_perf = {}
124
_supported_os Linux
117
+ is_mirror = False
118
+ for opt in opts:
119
+ if opt == 'mirror':
120
+ is_mirror = True
121
+ elif opt == 'copy-range=on':
122
+ x_perf['use-copy-range'] = True
123
+ elif opt == 'copy-range=off':
124
+ x_perf['use-copy-range'] = False
125
+ elif opt.startswith('max-workers='):
126
+ x_perf['max-workers'] = int(opt.split('=')[1])
127
+
128
+ if is_mirror:
129
+ assert not x_perf
130
+ test_envs.append({
131
+ 'id': f'mirror({label})',
132
+ 'cmd': 'blockdev-mirror',
133
+ 'qemu-binary': path
134
+ })
135
+ else:
136
+ test_envs.append({
137
+ 'id': f'backup({label})\n' + '\n'.join(opts),
138
+ 'cmd': 'blockdev-backup',
139
+ 'cmd-options': {'x-perf': x_perf} if x_perf else {},
140
+ 'qemu-binary': path
141
+ })
142
+
143
+ result = simplebench.bench(bench_func, test_envs, test_cases, count=3)
144
+ with open('results.json', 'w') as f:
145
+ json.dump(result, f, indent=4)
146
+ print(results_to_text(result))
147
+
148
+
149
+class ExtendAction(argparse.Action):
150
+ def __call__(self, parser, namespace, values, option_string=None):
151
+ items = getattr(namespace, self.dest) or []
152
+ items.extend(values)
153
+ setattr(namespace, self.dest, items)
154
+
155
+
156
+if __name__ == '__main__':
157
+ p = argparse.ArgumentParser('Backup benchmark', epilog='''
158
+ENV format
159
+
160
+ (LABEL:PATH|LABEL|PATH)[,max-workers=N][,use-copy-range=(on|off)][,mirror]
161
+
162
+ LABEL short name for the binary
163
+ PATH path to the binary
164
+ max-workers set x-perf.max-workers of backup job
165
+ use-copy-range set x-perf.use-copy-range of backup job
166
+ mirror use mirror job instead of backup''',
167
+ formatter_class=argparse.RawTextHelpFormatter)
168
+ p.add_argument('--env', nargs='+', help='''\
169
+Qemu binaries with labels and options, see below
170
+"ENV format" section''',
171
+ action=ExtendAction)
172
+ p.add_argument('--dir', nargs='+', help='''\
173
+Directories, each containing "test-source" and/or
174
+"test-target" files, raw images to used in
175
+benchmarking. File path with label, like
176
+label:/path/to/directory''',
177
+ action=ExtendAction)
178
+ p.add_argument('--nbd', help='''\
179
+host:port for remote NBD image, (or just host, for
180
+default port 10809). Use it in tests, label is "nbd"
181
+(but you cannot create test nbd:nbd).''')
182
+ p.add_argument('--test', nargs='+', help='''\
183
+Tests, in form source-dir-label:target-dir-label''',
184
+ action=ExtendAction)
185
+
186
+ bench(p.parse_args())
125
--
187
--
126
2.24.1
188
2.29.2
127
189
128
190
diff view generated by jsdifflib
1
We can save some LoC in xdbg_graph_add_edge() by using
1
From: David Edmondson <david.edmondson@oracle.com>
2
bdrv_qapi_perm_to_blk_perm().
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
When a call to fcntl(2) for the purpose of adding file locks fails
5
Message-id: 20191108123455.39445-3-mreitz@redhat.com
4
with an error other than EAGAIN or EACCES, report the error returned
5
by fcntl.
6
7
EAGAIN or EACCES are elided as they are considered to be common
8
failures, indicating that a conflicting lock is held by another
9
process.
10
11
No errors are elided when removing file locks.
12
13
Signed-off-by: David Edmondson <david.edmondson@oracle.com>
14
Message-Id: <20210113164447.2545785-1-david.edmondson@oracle.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
17
---
9
block.c | 29 ++++++++---------------------
18
block/file-posix.c | 38 ++++++++++++++++++++++++++++----------
10
1 file changed, 8 insertions(+), 21 deletions(-)
19
1 file changed, 28 insertions(+), 10 deletions(-)
11
20
12
diff --git a/block.c b/block.c
21
diff --git a/block/file-posix.c b/block/file-posix.c
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/block.c
23
--- a/block/file-posix.c
15
+++ b/block.c
24
+++ b/block/file-posix.c
16
@@ -XXX,XX +XXX,XX @@ static void xdbg_graph_add_node(XDbgBlockGraphConstructor *gr, void *node,
25
@@ -XXX,XX +XXX,XX @@ typedef struct RawPosixAIOData {
17
static void xdbg_graph_add_edge(XDbgBlockGraphConstructor *gr, void *parent,
26
static int cdrom_reopen(BlockDriverState *bs);
18
const BdrvChild *child)
27
#endif
28
29
+/*
30
+ * Elide EAGAIN and EACCES details when failing to lock, as this
31
+ * indicates that the specified file region is already locked by
32
+ * another process, which is considered a common scenario.
33
+ */
34
+#define raw_lock_error_setg_errno(errp, err, fmt, ...) \
35
+ do { \
36
+ if ((err) == EAGAIN || (err) == EACCES) { \
37
+ error_setg((errp), (fmt), ## __VA_ARGS__); \
38
+ } else { \
39
+ error_setg_errno((errp), (err), (fmt), ## __VA_ARGS__); \
40
+ } \
41
+ } while (0)
42
+
43
#if defined(__NetBSD__)
44
static int raw_normalize_devicepath(const char **filename, Error **errp)
19
{
45
{
20
- typedef struct {
46
@@ -XXX,XX +XXX,XX @@ static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
21
- unsigned int flag;
47
if ((perm_lock_bits & bit) && !(locked_perm & bit)) {
22
- BlockPermission num;
48
ret = qemu_lock_fd(fd, off, 1, false);
23
- } PermissionMap;
49
if (ret) {
24
-
50
- error_setg(errp, "Failed to lock byte %d", off);
25
- static const PermissionMap permissions[] = {
51
+ raw_lock_error_setg_errno(errp, -ret, "Failed to lock byte %d",
26
- { BLK_PERM_CONSISTENT_READ, BLOCK_PERMISSION_CONSISTENT_READ },
52
+ off);
27
- { BLK_PERM_WRITE, BLOCK_PERMISSION_WRITE },
53
return ret;
28
- { BLK_PERM_WRITE_UNCHANGED, BLOCK_PERMISSION_WRITE_UNCHANGED },
54
} else if (s) {
29
- { BLK_PERM_RESIZE, BLOCK_PERMISSION_RESIZE },
55
s->locked_perm |= bit;
30
- { BLK_PERM_GRAPH_MOD, BLOCK_PERMISSION_GRAPH_MOD },
56
@@ -XXX,XX +XXX,XX @@ static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
31
- { 0, 0 }
57
} else if (unlock && (locked_perm & bit) && !(perm_lock_bits & bit)) {
32
- };
58
ret = qemu_unlock_fd(fd, off, 1);
33
- const PermissionMap *p;
59
if (ret) {
34
+ BlockPermission qapi_perm;
60
- error_setg(errp, "Failed to unlock byte %d", off);
35
XDbgBlockGraphEdge *edge;
61
+ error_setg_errno(errp, -ret, "Failed to unlock byte %d", off);
36
62
return ret;
37
- QEMU_BUILD_BUG_ON(1UL << (ARRAY_SIZE(permissions) - 1) != BLK_PERM_ALL + 1);
63
} else if (s) {
38
-
64
s->locked_perm &= ~bit;
39
edge = g_new0(XDbgBlockGraphEdge, 1);
65
@@ -XXX,XX +XXX,XX @@ static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
40
66
if ((shared_perm_lock_bits & bit) && !(locked_shared_perm & bit)) {
41
edge->parent = xdbg_graph_node_num(gr, parent);
67
ret = qemu_lock_fd(fd, off, 1, false);
42
edge->child = xdbg_graph_node_num(gr, child->bs);
68
if (ret) {
43
edge->name = g_strdup(child->name);
69
- error_setg(errp, "Failed to lock byte %d", off);
44
70
+ raw_lock_error_setg_errno(errp, -ret, "Failed to lock byte %d",
45
- for (p = permissions; p->flag; p++) {
71
+ off);
46
- if (p->flag & child->perm) {
72
return ret;
47
- QAPI_LIST_ADD(edge->perm, p->num);
73
} else if (s) {
48
+ for (qapi_perm = 0; qapi_perm < BLOCK_PERMISSION__MAX; qapi_perm++) {
74
s->locked_shared_perm |= bit;
49
+ uint64_t flag = bdrv_qapi_perm_to_blk_perm(qapi_perm);
75
@@ -XXX,XX +XXX,XX @@ static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
76
!(shared_perm_lock_bits & bit)) {
77
ret = qemu_unlock_fd(fd, off, 1);
78
if (ret) {
79
- error_setg(errp, "Failed to unlock byte %d", off);
80
+ error_setg_errno(errp, -ret, "Failed to unlock byte %d", off);
81
return ret;
82
} else if (s) {
83
s->locked_shared_perm &= ~bit;
84
@@ -XXX,XX +XXX,XX @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
85
ret = qemu_lock_fd_test(fd, off, 1, true);
86
if (ret) {
87
char *perm_name = bdrv_perm_names(p);
88
- error_setg(errp,
89
- "Failed to get \"%s\" lock",
90
- perm_name);
50
+
91
+
51
+ if (flag & child->perm) {
92
+ raw_lock_error_setg_errno(errp, -ret,
52
+ QAPI_LIST_ADD(edge->perm, qapi_perm);
93
+ "Failed to get \"%s\" lock",
53
}
94
+ perm_name);
54
- if (p->flag & child->shared_perm) {
95
g_free(perm_name);
55
- QAPI_LIST_ADD(edge->shared_perm, p->num);
96
return ret;
56
+ if (flag & child->shared_perm) {
97
}
57
+ QAPI_LIST_ADD(edge->shared_perm, qapi_perm);
98
@@ -XXX,XX +XXX,XX @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
58
}
99
ret = qemu_lock_fd_test(fd, off, 1, true);
59
}
100
if (ret) {
60
101
char *perm_name = bdrv_perm_names(p);
102
- error_setg(errp,
103
- "Failed to get shared \"%s\" lock",
104
- perm_name);
105
+
106
+ raw_lock_error_setg_errno(errp, -ret,
107
+ "Failed to get shared \"%s\" lock",
108
+ perm_name);
109
g_free(perm_name);
110
return ret;
111
}
61
--
112
--
62
2.24.1
113
2.29.2
63
114
64
115
diff view generated by jsdifflib
1
From: PanNengyuan <pannengyuan@huawei.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This avoid a memory leak when qom-set is called to set throttle_group
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
4
limits, here is an easy way to reproduce:
4
Suggested-by: Maxim Levitsky <mlevitsk@redhat.com>
5
5
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
6
1. run qemu-iotests as follow and check the result with asan:
6
Message-Id: <20210112170540.2912-1-berto@igalia.com>
7
./check -qcow2 184
7
[mreitz: Add "# group:" line]
8
9
Following is the asan output backtrack:
10
Direct leak of 912 byte(s) in 3 object(s) allocated from:
11
#0 0xffff8d7ab3c3 in __interceptor_calloc (/lib64/libasan.so.4+0xd33c3)
12
#1 0xffff8d4c31cb in g_malloc0 (/lib64/libglib-2.0.so.0+0x571cb)
13
#2 0x190c857 in qobject_input_start_struct /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qapi/qobject-input-visitor.c:295
14
#3 0x19070df in visit_start_struct /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qapi/qapi-visit-core.c:49
15
#4 0x1948b87 in visit_type_ThrottleLimits qapi/qapi-visit-block-core.c:3759
16
#5 0x17e4aa3 in throttle_group_set_limits /mnt/sdc/qemu-master/qemu-4.2.0-rc0/block/throttle-groups.c:900
17
#6 0x1650eff in object_property_set /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/object.c:1272
18
#7 0x1658517 in object_property_set_qobject /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/qom-qobject.c:26
19
#8 0x15880bb in qmp_qom_set /mnt/sdc/qemu-master/qemu-4.2.0-rc0/qom/qom-qmp-cmds.c:74
20
#9 0x157e3e3 in qmp_marshal_qom_set qapi/qapi-commands-qom.c:154
21
22
Reported-by: Euler Robot <euler.robot@huawei.com>
23
Signed-off-by: PanNengyuan <pannengyuan@huawei.com>
24
Message-id: 1574835614-42028-1-git-send-email-pannengyuan@huawei.com
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
---
9
---
27
block/throttle-groups.c | 4 ++--
10
tests/qemu-iotests/313 | 104 +++++++++++++++++++++++++++++++++++++
28
1 file changed, 2 insertions(+), 2 deletions(-)
11
tests/qemu-iotests/313.out | 29 +++++++++++
12
tests/qemu-iotests/group | 1 +
13
3 files changed, 134 insertions(+)
14
create mode 100755 tests/qemu-iotests/313
15
create mode 100644 tests/qemu-iotests/313.out
29
16
30
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
17
diff --git a/tests/qemu-iotests/313 b/tests/qemu-iotests/313
18
new file mode 100755
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/tests/qemu-iotests/313
22
@@ -XXX,XX +XXX,XX @@
23
+#!/usr/bin/env bash
24
+# group: rw auto quick
25
+#
26
+# Test for the regression fixed in commit c8bf9a9169
27
+#
28
+# Copyright (C) 2020 Igalia, S.L.
29
+# Author: Alberto Garcia <berto@igalia.com>
30
+# Based on a test case by Maxim Levitsky <mlevitsk@redhat.com>
31
+#
32
+# This program is free software; you can redistribute it and/or modify
33
+# it under the terms of the GNU General Public License as published by
34
+# the Free Software Foundation; either version 2 of the License, or
35
+# (at your option) any later version.
36
+#
37
+# This program is distributed in the hope that it will be useful,
38
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
39
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40
+# GNU General Public License for more details.
41
+#
42
+# You should have received a copy of the GNU General Public License
43
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
44
+#
45
+
46
+# creator
47
+owner=berto@igalia.com
48
+
49
+seq=`basename $0`
50
+echo "QA output created by $seq"
51
+
52
+status=1 # failure is the default!
53
+
54
+_cleanup()
55
+{
56
+ _cleanup_test_img
57
+}
58
+trap "_cleanup; exit \$status" 0 1 2 3 15
59
+
60
+# get standard environment, filters and checks
61
+. ./common.rc
62
+. ./common.filter
63
+
64
+_supported_fmt qcow2
65
+_supported_proto file
66
+_supported_os Linux
67
+_unsupported_imgopts cluster_size refcount_bits extended_l2 compat=0.10 data_file
68
+
69
+# The cluster size must be at least the granularity of the mirror job (4KB)
70
+# Note that larger cluster sizes will produce very large images (several GBs)
71
+cluster_size=4096
72
+refcount_bits=64 # Make it equal to the L2 entry size for convenience
73
+options="cluster_size=${cluster_size},refcount_bits=${refcount_bits}"
74
+
75
+# Number of refcount entries per refcount blocks
76
+ref_entries=$(( ${cluster_size} * 8 / ${refcount_bits} ))
77
+
78
+# Number of data clusters needed to fill a refcount block
79
+# Equals ${ref_entries} minus two (one L2 table and one refcount block)
80
+data_clusters_per_refblock=$(( ${ref_entries} - 2 ))
81
+
82
+# Number of entries in the refcount cache
83
+ref_blocks=4
84
+
85
+# Write enough data clusters to fill the refcount cache and allocate
86
+# one more refcount block.
87
+# Subtract 3 clusters from the total: qcow2 header, refcount table, L1 table
88
+total_data_clusters=$(( ${data_clusters_per_refblock} * ${ref_blocks} + 1 - 3 ))
89
+
90
+# Total size to write in bytes
91
+total_size=$(( ${total_data_clusters} * ${cluster_size} ))
92
+
93
+echo
94
+echo '### Create the image'
95
+echo
96
+TEST_IMG_FILE=$TEST_IMG.base _make_test_img -o $options $total_size | _filter_img_create_size
97
+
98
+echo
99
+echo '### Write data to allocate more refcount blocks than the cache can hold'
100
+echo
101
+$QEMU_IO -c "write -P 1 0 $total_size" $TEST_IMG.base | _filter_qemu_io
102
+
103
+echo
104
+echo '### Create an overlay'
105
+echo
106
+_make_test_img -F $IMGFMT -b $TEST_IMG.base -o $options | _filter_img_create_size
107
+
108
+echo
109
+echo '### Fill the overlay with zeroes'
110
+echo
111
+$QEMU_IO -c "write -z 0 $total_size" $TEST_IMG | _filter_qemu_io
112
+
113
+echo
114
+echo '### Commit changes to the base image'
115
+echo
116
+$QEMU_IMG commit $TEST_IMG
117
+
118
+echo
119
+echo '### Check the base image'
120
+echo
121
+$QEMU_IMG check $TEST_IMG.base
122
+
123
+# success, all done
124
+echo "*** done"
125
+rm -f $seq.full
126
+status=0
127
diff --git a/tests/qemu-iotests/313.out b/tests/qemu-iotests/313.out
128
new file mode 100644
129
index XXXXXXX..XXXXXXX
130
--- /dev/null
131
+++ b/tests/qemu-iotests/313.out
132
@@ -XXX,XX +XXX,XX @@
133
+QA output created by 313
134
+
135
+### Create the image
136
+
137
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=SIZE
138
+
139
+### Write data to allocate more refcount blocks than the cache can hold
140
+
141
+wrote 8347648/8347648 bytes at offset 0
142
+7.961 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
143
+
144
+### Create an overlay
145
+
146
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
147
+
148
+### Fill the overlay with zeroes
149
+
150
+wrote 8347648/8347648 bytes at offset 0
151
+7.961 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
152
+
153
+### Commit changes to the base image
154
+
155
+Image committed.
156
+
157
+### Check the base image
158
+
159
+No errors were found on the image.
160
+Image end offset: 8396800
161
+*** done
162
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
31
index XXXXXXX..XXXXXXX 100644
163
index XXXXXXX..XXXXXXX 100644
32
--- a/block/throttle-groups.c
164
--- a/tests/qemu-iotests/group
33
+++ b/block/throttle-groups.c
165
+++ b/tests/qemu-iotests/group
34
@@ -XXX,XX +XXX,XX @@ static void throttle_group_set_limits(Object *obj, Visitor *v,
166
@@ -XXX,XX +XXX,XX @@
35
{
167
309 rw auto quick
36
ThrottleGroup *tg = THROTTLE_GROUP(obj);
168
310 rw quick
37
ThrottleConfig cfg;
169
312 rw quick
38
- ThrottleLimits arg = { 0 };
170
+313 rw auto quick
39
- ThrottleLimits *argp = &arg;
40
+ ThrottleLimits *argp;
41
Error *local_err = NULL;
42
43
visit_type_ThrottleLimits(v, name, &argp, &local_err);
44
@@ -XXX,XX +XXX,XX @@ static void throttle_group_set_limits(Object *obj, Visitor *v,
45
unlock:
46
qemu_mutex_unlock(&tg->lock);
47
ret:
48
+ qapi_free_ThrottleLimits(argp);
49
error_propagate(errp, local_err);
50
return;
51
}
52
--
171
--
53
2.24.1
172
2.29.2
54
173
55
174
diff view generated by jsdifflib
1
Commit 0afec75734331 removed the 'change' QMP command, so we can no
2
longer test it in 118.
3
4
Fixes: 0afec75734331a0b52fa3aa4235220eda8c7846f
5
('qmp: remove deprecated "change" command')
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <20210126104833.57026-1-mreitz@redhat.com>
3
Tested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
Reviewed-by: John Snow <jsnow@redhat.com>
5
Message-id: 20191108123455.39445-6-mreitz@redhat.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
9
---
8
tests/qemu-iotests/041 | 44 ++++++++++++++++++++++++++++++++++++++
10
tests/qemu-iotests/118 | 20 +-------------------
9
tests/qemu-iotests/041.out | 4 ++--
11
tests/qemu-iotests/118.out | 4 ++--
10
2 files changed, 46 insertions(+), 2 deletions(-)
12
2 files changed, 3 insertions(+), 21 deletions(-)
11
13
12
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
14
diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118
13
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/041
16
--- a/tests/qemu-iotests/118
15
+++ b/tests/qemu-iotests/041
17
+++ b/tests/qemu-iotests/118
16
@@ -XXX,XX +XXX,XX @@ class TestOrphanedSource(iotests.QMPTestCase):
18
@@ -XXX,XX +XXX,XX @@
17
target='dest-ro')
19
#!/usr/bin/env python3
18
self.assert_qmp(result, 'error/class', 'GenericError')
20
# group: rw
19
21
#
20
+ def test_failing_permission_in_complete(self):
22
-# Test case for the QMP 'change' command and all other associated
21
+ self.assert_no_active_block_jobs()
23
-# commands
22
+
24
+# Test case for media change monitor commands
23
+ # Unshare consistent-read on the target
25
#
24
+ # (The mirror job does not care)
26
# Copyright (C) 2015 Red Hat, Inc.
25
+ result = self.vm.qmp('blockdev-add',
27
#
26
+ driver='blkdebug',
28
@@ -XXX,XX +XXX,XX @@ class ChangeBaseClass(iotests.QMPTestCase):
27
+ node_name='dest-perm',
29
28
+ image='dest',
30
class GeneralChangeTestsBaseClass(ChangeBaseClass):
29
+ unshare_child_perms=['consistent-read'])
31
30
+ self.assert_qmp(result, 'return', {})
32
- def test_change(self):
31
+
33
- # 'change' requires a drive name, so skip the test for blockdev
32
+ result = self.vm.qmp('blockdev-mirror', job_id='job', device='src',
34
- if not self.use_drive:
33
+ sync='full', target='dest',
35
- return
34
+ filter_node_name='mirror-filter')
36
-
35
+ self.assert_qmp(result, 'return', {})
37
- result = self.vm.qmp('change', device='drive0', target=new_img,
36
+
38
- arg=iotests.imgfmt)
37
+ # Require consistent-read on the source
39
- self.assert_qmp(result, 'return', {})
38
+ # (We can only add this node once the job has started, or it
40
-
39
+ # will complain that it does not want to run on non-root nodes)
41
- self.wait_for_open()
40
+ result = self.vm.qmp('blockdev-add',
42
- self.wait_for_close()
41
+ driver='blkdebug',
43
-
42
+ node_name='src-perm',
44
- result = self.vm.qmp('query-block')
43
+ image='src',
45
- if self.has_real_tray:
44
+ take_child_perms=['consistent-read'])
46
- self.assert_qmp(result, 'return[0]/tray_open', False)
45
+ self.assert_qmp(result, 'return', {})
47
- self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
46
+
48
-
47
+ # While completing, mirror will attempt to replace src by
49
def test_blockdev_change_medium(self):
48
+ # dest, which must fail because src-perm requires
50
result = self.vm.qmp('blockdev-change-medium',
49
+ # consistent-read but dest-perm does not share it; thus
51
id=self.device_name, filename=new_img,
50
+ # aborting the job when it is supposed to complete
52
diff --git a/tests/qemu-iotests/118.out b/tests/qemu-iotests/118.out
51
+ self.complete_and_wait('job',
52
+ completion_error='Operation not permitted')
53
+
54
+ # Assert that all of our nodes are still there (except for the
55
+ # mirror filter, which should be gone despite the failure)
56
+ nodes = self.vm.qmp('query-named-block-nodes')['return']
57
+ nodes = [node['node-name'] for node in nodes]
58
+
59
+ for expect in ('src', 'src-perm', 'dest', 'dest-perm'):
60
+ self.assertTrue(expect in nodes, '%s disappeared' % expect)
61
+ self.assertFalse('mirror-filter' in nodes,
62
+ 'Mirror filter node did not disappear')
63
+
64
if __name__ == '__main__':
65
iotests.main(supported_fmts=['qcow2', 'qed'],
66
supported_protocols=['file'])
67
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
68
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
69
--- a/tests/qemu-iotests/041.out
54
--- a/tests/qemu-iotests/118.out
70
+++ b/tests/qemu-iotests/041.out
55
+++ b/tests/qemu-iotests/118.out
71
@@ -XXX,XX +XXX,XX @@
56
@@ -XXX,XX +XXX,XX @@
72
-..........................................................................................
57
-.......................................................................................................................................................................
73
+...........................................................................................
58
+...........................................................................................................................................................
74
----------------------------------------------------------------------
59
----------------------------------------------------------------------
75
-Ran 90 tests
60
-Ran 167 tests
76
+Ran 91 tests
61
+Ran 155 tests
77
62
78
OK
63
OK
79
--
64
--
80
2.24.1
65
2.29.2
81
66
82
67
diff view generated by jsdifflib
1
ccd3b3b8112 has deprecated short-hand boolean options (i.e., options
2
with values). All options without values are interpreted as boolean
3
options, so this includes the invalid option "snapshot.foo" used in
4
iotest 178.
5
6
So after ccd3b3b8112, 178 fails with:
7
8
+qemu-img: warning: short-form boolean option 'snapshot.foo' deprecated
9
+Please use snapshot.foo=on instead
10
11
Suppress that deprecation warning by passing some value to it (it does
12
not matter which, because the option is invalid anyway).
13
14
Fixes: ccd3b3b8112b670fdccf8a392b8419b173ffccb4
15
("qemu-option: warn for short-form boolean options")
1
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
17
Message-Id: <20210126123834.115915-1-mreitz@redhat.com>
3
Message-id: 20191107163708.833192-13-mreitz@redhat.com
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
18
---
6
tests/qemu-iotests/071 | 4 ++--
19
tests/qemu-iotests/178 | 2 +-
7
tests/qemu-iotests/174 | 2 +-
20
tests/qemu-iotests/178.out.qcow2 | 2 +-
8
tests/qemu-iotests/178 | 4 ++--
21
tests/qemu-iotests/178.out.raw | 2 +-
9
tests/qemu-iotests/197 | 4 ++--
22
3 files changed, 3 insertions(+), 3 deletions(-)
10
tests/qemu-iotests/215 | 4 ++--
11
5 files changed, 9 insertions(+), 9 deletions(-)
12
23
13
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/071
16
+++ b/tests/qemu-iotests/071
17
@@ -XXX,XX +XXX,XX @@ echo
18
echo "=== Testing blkverify through filename ==="
19
echo
20
21
-TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\
22
+TEST_IMG="$TEST_IMG.base" IMGFMT="raw" _make_test_img --no-opts $IMG_SIZE |\
23
_filter_imgfmt
24
_make_test_img $IMG_SIZE
25
$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \
26
@@ -XXX,XX +XXX,XX @@ echo
27
echo "=== Testing blkverify through file blockref ==="
28
echo
29
30
-TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\
31
+TEST_IMG="$TEST_IMG.base" IMGFMT="raw" _make_test_img --no-opts $IMG_SIZE |\
32
_filter_imgfmt
33
_make_test_img $IMG_SIZE
34
$QEMU_IO -c "open -o driver=raw,file.driver=blkverify,file.raw.filename=$TEST_IMG.base,file.test.driver=$IMGFMT,file.test.file.filename=$TEST_IMG" \
35
diff --git a/tests/qemu-iotests/174 b/tests/qemu-iotests/174
36
index XXXXXXX..XXXXXXX 100755
37
--- a/tests/qemu-iotests/174
38
+++ b/tests/qemu-iotests/174
39
@@ -XXX,XX +XXX,XX @@ _unsupported_fmt raw
40
41
42
size=256K
43
-IMGFMT=raw IMGKEYSECRET= IMGOPTS= _make_test_img $size | _filter_imgfmt
44
+IMGFMT=raw IMGKEYSECRET= _make_test_img --no-opts $size | _filter_imgfmt
45
46
echo
47
echo "== reading wrong format should fail =="
48
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
24
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
49
index XXXXXXX..XXXXXXX 100755
25
index XXXXXXX..XXXXXXX 100755
50
--- a/tests/qemu-iotests/178
26
--- a/tests/qemu-iotests/178
51
+++ b/tests/qemu-iotests/178
27
+++ b/tests/qemu-iotests/178
52
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG measure -O foo "$TEST_IMG" # unknown image file format
28
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG measure --image-opts # missing filename
53
29
$QEMU_IMG measure -f qcow2 # missing filename
54
make_test_img_with_fmt() {
30
$QEMU_IMG measure -l snap1 # missing filename
55
# Shadow global variables within this function
31
$QEMU_IMG measure -o , # invalid option list
56
- local IMGFMT="$1" IMGOPTS=""
32
-$QEMU_IMG measure -l snapshot.foo # invalid snapshot option
57
- _make_test_img "$2"
33
+$QEMU_IMG measure -l snapshot.foo=bar # invalid snapshot option
58
+ local IMGFMT="$1"
34
$QEMU_IMG measure --output foo # invalid output format
59
+ _make_test_img --no-opts "$2"
35
$QEMU_IMG measure --size -1 # invalid image size
60
}
36
$QEMU_IMG measure -O foo "$TEST_IMG" # unknown image file format
61
37
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
62
qemu_io_with_fmt() {
38
index XXXXXXX..XXXXXXX 100644
63
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
39
--- a/tests/qemu-iotests/178.out.qcow2
64
index XXXXXXX..XXXXXXX 100755
40
+++ b/tests/qemu-iotests/178.out.qcow2
65
--- a/tests/qemu-iotests/197
41
@@ -XXX,XX +XXX,XX @@ qemu-img: --image-opts, -f, and -l require a filename argument.
66
+++ b/tests/qemu-iotests/197
42
qemu-img: --image-opts, -f, and -l require a filename argument.
67
@@ -XXX,XX +XXX,XX @@ if [ "$IMGFMT" = "vpc" ]; then
43
qemu-img: Invalid option list: ,
68
fi
44
qemu-img: Invalid parameter 'snapshot.foo'
69
_make_test_img 4G
45
-qemu-img: Failed in parsing snapshot param 'snapshot.foo'
70
$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
46
+qemu-img: Failed in parsing snapshot param 'snapshot.foo=bar'
71
-IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
47
qemu-img: --output must be used with human or json as argument.
72
- _make_test_img -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
48
qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.
73
+IMGPROTO=file IMGFMT=qcow2 TEST_IMG_FILE="$TEST_WRAP" \
49
qemu-img: Unknown file format 'foo'
74
+ _make_test_img --no-opts -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
50
diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw
75
$QEMU_IO -f qcow2 -c "write -z -u 1M 64k" "$TEST_WRAP" | _filter_qemu_io
51
index XXXXXXX..XXXXXXX 100644
76
52
--- a/tests/qemu-iotests/178.out.raw
77
# Ensure that a read of two clusters, but where one is already allocated,
53
+++ b/tests/qemu-iotests/178.out.raw
78
diff --git a/tests/qemu-iotests/215 b/tests/qemu-iotests/215
54
@@ -XXX,XX +XXX,XX @@ qemu-img: --image-opts, -f, and -l require a filename argument.
79
index XXXXXXX..XXXXXXX 100755
55
qemu-img: --image-opts, -f, and -l require a filename argument.
80
--- a/tests/qemu-iotests/215
56
qemu-img: Invalid option list: ,
81
+++ b/tests/qemu-iotests/215
57
qemu-img: Invalid parameter 'snapshot.foo'
82
@@ -XXX,XX +XXX,XX @@ if [ "$IMGFMT" = "vpc" ]; then
58
-qemu-img: Failed in parsing snapshot param 'snapshot.foo'
83
fi
59
+qemu-img: Failed in parsing snapshot param 'snapshot.foo=bar'
84
_make_test_img 4G
60
qemu-img: --output must be used with human or json as argument.
85
$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
61
qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.
86
-IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
62
qemu-img: Unknown file format 'foo'
87
- _make_test_img -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
88
+IMGPROTO=file IMGFMT=qcow2 TEST_IMG_FILE="$TEST_WRAP" \
89
+ _make_test_img --no-opts -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
90
$QEMU_IO -f qcow2 -c "write -z -u 1M 64k" "$TEST_WRAP" | _filter_qemu_io
91
92
# Ensure that a read of two clusters, but where one is already allocated,
93
--
63
--
94
2.24.1
64
2.29.2
95
65
96
66
diff view generated by jsdifflib