1
The following changes since commit 98b2e3c9ab3abfe476a2b02f8f51813edb90e72d:
1
The following changes since commit eaefea537b476cb853e2edbdc68e969ec777e4bb:
2
2
3
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging (2019-10-08 16:08:35 +0100)
3
Merge remote-tracking branch 'remotes/mjt/tags/trivial-patches-fetch' into staging (2017-12-18 14:17:42 +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-2019-10-10
7
git://github.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 35f05b2e2ee59e077bf949057dc0959ddd6e5249:
9
for you to fetch changes up to 7a9dda0d7f9831c2432620dcfefdadbb7ae888dc:
10
10
11
iotests/162: Fix for newer Linux 5.3+ (2019-10-10 12:13:23 +0200)
11
qemu-iotests: add 203 savevm with IOThreads test (2017-12-19 10:25:09 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- Parallelized request handling for qcow2
15
16
- Backup job refactoring to use a filter node instead of before-write
16
v2:
17
notifiers
17
* Fixed incorrect virtio_blk_data_plane_create() local_err refactoring in
18
- Add discard accounting information to file-posix nodes
18
"hw/block: Use errp directly rather than local_err" that broke virtio-blk
19
- Allow trivial reopening of nbd nodes
19
over virtio-mmio [Peter]
20
- Some iotest fixes
21
20
22
----------------------------------------------------------------
21
----------------------------------------------------------------
23
Anton Nefedov (9):
24
qapi: group BlockDeviceStats fields
25
qapi: add unmap to BlockDeviceStats
26
block: add empty account cookie type
27
ide: account UNMAP (TRIM) operations
28
scsi: store unmap offset and nb_sectors in request struct
29
scsi: move unmap error checking to the complete callback
30
scsi: account unmap operations
31
file-posix: account discard operations
32
qapi: query-blockstat: add driver specific file-posix stats
33
22
34
Daniel P. Berrangé (1):
23
Mao Zhongyi (4):
35
tests: fix I/O test for hosts defaulting to LUKSv2
24
hw/block/nvme: Convert to realize
25
hw/block: Fix the return type
26
hw/block: Use errp directly rather than local_err
27
dev-storage: Fix the unusual function name
36
28
37
Max Reitz (4):
29
Mark Kanda (2):
38
iotests: Fix 125 for growth_mode = metadata
30
virtio-blk: make queue size configurable
39
iotests: Disable 125 on broken XFS versions
31
virtio-blk: reject configs with logical block size > physical block
40
iotests: Use stat -c %b in 125
32
size
41
iotests/162: Fix for newer Linux 5.3+
42
33
43
Maxim Levitsky (1):
34
Paolo Bonzini (1):
44
nbd: add empty .bdrv_reopen_prepare
35
block: avoid recursive AioContext acquire in bdrv_inactivate_all()
45
36
46
Vladimir Sementsov-Ogievskiy (21):
37
Stefan Hajnoczi (16):
47
qemu-iotests: ignore leaks on failure paths in 026
38
coroutine: simplify co_aio_sleep_ns() prototype
48
block: introduce aio task pool
39
qdev: drop unused #include "sysemu/iothread.h"
49
block/qcow2: refactor qcow2_co_preadv_part
40
blockdev: hold AioContext for bdrv_unref() in
50
block/qcow2: refactor qcow2_co_pwritev_part
41
external_snapshot_clean()
51
block/qcow2: introduce parallel subrequest handling in read and write
42
block: don't keep AioContext acquired after
52
block/backup: fix max_transfer handling for copy_range
43
external_snapshot_prepare()
53
block/backup: fix backup_cow_with_offload for last cluster
44
block: don't keep AioContext acquired after drive_backup_prepare()
54
block/backup: split shareable copying part from backup_do_cow
45
block: don't keep AioContext acquired after blockdev_backup_prepare()
55
block/backup: improve comment about image fleecing
46
block: don't keep AioContext acquired after
56
block/backup: introduce BlockCopyState
47
internal_snapshot_prepare()
57
block/backup: fix block-comment style
48
block: drop unused BlockDirtyBitmapState->aio_context field
58
block: move block_copy from block/backup.c to separate file
49
iothread: add iothread_by_id() API
59
block: teach bdrv_debug_breakpoint skip filters with backing
50
blockdev: add x-blockdev-set-iothread testing command
60
iotests: prepare 124 and 257 bitmap querying for backup-top filter
51
qemu-iotests: add 202 external snapshots IOThread test
61
iotests: 257: drop unused Drive.device field
52
docs: mark nested AioContext locking as a legacy API
62
iotests: 257: drop device_add
53
blockdev: add x-blockdev-set-iothread force boolean
63
block/backup: move in-flight requests handling from backup to
54
iotests: add VM.add_object()
64
block-copy
55
iothread: fix iothread_stop() race condition
65
block/backup: move write_flags calculation inside backup_job_create
56
qemu-iotests: add 203 savevm with IOThreads test
66
block/block-copy: split block_copy_set_callbacks function
67
block: introduce backup-top filter driver
68
block/backup: use backup-top instead of write notifiers
69
57
70
block/Makefile.objs | 4 +
58
docs/devel/multiple-iothreads.txt | 7 +-
71
qapi/block-core.json | 89 +++-
59
qapi/block-core.json | 40 ++++++
72
block/backup-top.h | 41 ++
60
hw/block/dataplane/virtio-blk.h | 2 +-
73
block/qcow2.h | 3 +
61
include/hw/block/block.h | 4 +-
74
include/block/accounting.h | 2 +
62
include/hw/virtio/virtio-blk.h | 1 +
75
include/block/aio_task.h | 54 +++
63
include/qemu/coroutine.h | 6 +-
76
include/block/block-copy.h | 93 ++++
64
include/sysemu/iothread.h | 4 +-
77
include/block/block.h | 1 +
65
block.c | 14 ++-
78
include/block/block_int.h | 2 +
66
block/null.c | 3 +-
79
block.c | 43 +-
67
block/sheepdog.c | 3 +-
80
block/accounting.c | 6 +
68
blockdev.c | 259 +++++++++++++++++++++++++++-----------
81
block/aio_task.c | 124 +++++
69
hw/block/block.c | 15 ++-
82
block/backup-top.c | 276 +++++++++++
70
hw/block/dataplane/virtio-blk.c | 12 +-
83
block/backup.c | 443 ++++--------------
71
hw/block/fdc.c | 17 +--
84
block/block-copy.c | 345 ++++++++++++++
72
hw/block/nvme.c | 23 ++--
85
block/file-posix.c | 54 ++-
73
hw/block/virtio-blk.c | 30 +++--
86
block/nbd.c | 15 +
74
hw/core/qdev-properties-system.c | 1 -
87
block/qapi.c | 11 +
75
hw/ide/qdev.c | 12 +-
88
block/qcow2.c | 466 ++++++++++++-------
76
hw/scsi/scsi-disk.c | 13 +-
89
block/replication.c | 2 +-
77
hw/usb/dev-storage.c | 29 ++---
90
blockdev.c | 1 +
78
iothread.c | 27 +++-
91
hw/ide/core.c | 12 +
79
util/qemu-coroutine-sleep.c | 4 +-
92
hw/scsi/scsi-disk.c | 34 +-
80
tests/qemu-iotests/202 | 95 ++++++++++++++
93
block/trace-events | 15 +-
81
tests/qemu-iotests/202.out | 11 ++
94
tests/qemu-iotests/026 | 6 +-
82
tests/qemu-iotests/203 | 59 +++++++++
95
tests/qemu-iotests/026.out | 80 +---
83
tests/qemu-iotests/203.out | 6 +
96
tests/qemu-iotests/026.out.nocache | 80 +---
84
tests/qemu-iotests/group | 2 +
97
tests/qemu-iotests/056 | 8 +-
85
tests/qemu-iotests/iotests.py | 5 +
98
tests/qemu-iotests/124 | 83 ++--
86
28 files changed, 531 insertions(+), 173 deletions(-)
99
tests/qemu-iotests/125 | 45 +-
87
create mode 100755 tests/qemu-iotests/202
100
tests/qemu-iotests/141.out | 2 +-
88
create mode 100644 tests/qemu-iotests/202.out
101
tests/qemu-iotests/149 | 2 +-
89
create mode 100755 tests/qemu-iotests/203
102
tests/qemu-iotests/149.out | 44 +-
90
create mode 100644 tests/qemu-iotests/203.out
103
tests/qemu-iotests/162 | 2 +-
104
tests/qemu-iotests/162.out | 2 +-
105
tests/qemu-iotests/227.out | 18 +
106
tests/qemu-iotests/257 | 91 ++--
107
tests/qemu-iotests/257.out | 714 ++++++++++++-----------------
108
tests/qemu-iotests/common.rc | 17 +
109
tests/qemu-iotests/iotests.py | 27 ++
110
40 files changed, 2108 insertions(+), 1249 deletions(-)
111
create mode 100644 block/backup-top.h
112
create mode 100644 include/block/aio_task.h
113
create mode 100644 include/block/block-copy.h
114
create mode 100644 block/aio_task.c
115
create mode 100644 block/backup-top.c
116
create mode 100644 block/block-copy.c
117
91
118
--
92
--
119
2.21.0
93
2.14.3
120
94
121
95
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Upcoming asynchronous handling of sub-parts of qcow2 requests will
4
change number of leaked clusters and even make it racy. As a
5
preparation, ignore leaks on failure parts in 026.
6
7
It's not trivial to just grep or substitute qemu-img output for such
8
thing. Instead do better: 3 is a error code of qemu-img check, if only
9
leaks are found. Catch this case and print success output.
10
11
Suggested-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Message-id: 20190916175324.18478-2-vsementsov@virtuozzo.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
tests/qemu-iotests/026 | 6 +--
17
tests/qemu-iotests/026.out | 80 ++++++++----------------------
18
tests/qemu-iotests/026.out.nocache | 80 ++++++++----------------------
19
tests/qemu-iotests/common.rc | 17 +++++++
20
4 files changed, 60 insertions(+), 123 deletions(-)
21
22
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/026
25
+++ b/tests/qemu-iotests/026
26
@@ -XXX,XX +XXX,XX @@ if [ "$event" == "l2_load" ]; then
27
$QEMU_IO -c "read $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io
28
fi
29
30
-_check_test_img 2>&1 | grep -v "refcount=1 reference=0"
31
+_check_test_img_ignore_leaks 2>&1 | grep -v "refcount=1 reference=0"
32
33
done
34
done
35
@@ -XXX,XX +XXX,XX @@ echo
36
echo "Event: $event; errno: $errno; imm: $imm; once: $once; write $vmstate"
37
$QEMU_IO -c "write $vmstate 0 64M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
38
39
-_check_test_img 2>&1 | grep -v "refcount=1 reference=0"
40
+_check_test_img_ignore_leaks 2>&1 | grep -v "refcount=1 reference=0"
41
42
done
43
done
44
@@ -XXX,XX +XXX,XX @@ echo
45
echo "Event: $event; errno: $errno; imm: $imm; once: $once"
46
$QEMU_IO -c "write -b 0 64k" "$BLKDBG_TEST_IMG" | _filter_qemu_io
47
48
-_check_test_img 2>&1 | grep -v "refcount=1 reference=0"
49
+_check_test_img_ignore_leaks 2>&1 | grep -v "refcount=1 reference=0"
50
51
done
52
done
53
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
54
index XXXXXXX..XXXXXXX 100644
55
--- a/tests/qemu-iotests/026.out
56
+++ b/tests/qemu-iotests/026.out
57
@@ -XXX,XX +XXX,XX @@ Event: l1_update; errno: 5; imm: off; once: off; write
58
qemu-io: Failed to flush the L2 table cache: Input/output error
59
qemu-io: Failed to flush the refcount block cache: Input/output error
60
write failed: Input/output error
61
-
62
-1 leaked clusters were found on the image.
63
-This means waste of disk space, but no harm to data.
64
+No errors were found on the image.
65
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
66
67
Event: l1_update; errno: 5; imm: off; once: off; write -b
68
qemu-io: Failed to flush the L2 table cache: Input/output error
69
qemu-io: Failed to flush the refcount block cache: Input/output error
70
write failed: Input/output error
71
-
72
-1 leaked clusters were found on the image.
73
-This means waste of disk space, but no harm to data.
74
+No errors were found on the image.
75
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
76
77
Event: l1_update; errno: 28; imm: off; once: on; write
78
@@ -XXX,XX +XXX,XX @@ Event: l1_update; errno: 28; imm: off; once: off; write
79
qemu-io: Failed to flush the L2 table cache: No space left on device
80
qemu-io: Failed to flush the refcount block cache: No space left on device
81
write failed: No space left on device
82
-
83
-1 leaked clusters were found on the image.
84
-This means waste of disk space, but no harm to data.
85
+No errors were found on the image.
86
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
87
88
Event: l1_update; errno: 28; imm: off; once: off; write -b
89
qemu-io: Failed to flush the L2 table cache: No space left on device
90
qemu-io: Failed to flush the refcount block cache: No space left on device
91
write failed: No space left on device
92
-
93
-1 leaked clusters were found on the image.
94
-This means waste of disk space, but no harm to data.
95
+No errors were found on the image.
96
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
97
98
Event: l2_load; errno: 5; imm: off; once: on; write
99
@@ -XXX,XX +XXX,XX @@ Event: l2_update; errno: 5; imm: off; once: off; write
100
qemu-io: Failed to flush the L2 table cache: Input/output error
101
qemu-io: Failed to flush the refcount block cache: Input/output error
102
write failed: Input/output error
103
-
104
-127 leaked clusters were found on the image.
105
-This means waste of disk space, but no harm to data.
106
+No errors were found on the image.
107
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
108
109
Event: l2_update; errno: 5; imm: off; once: off; write -b
110
qemu-io: Failed to flush the L2 table cache: Input/output error
111
qemu-io: Failed to flush the refcount block cache: Input/output error
112
write failed: Input/output error
113
-
114
-127 leaked clusters were found on the image.
115
-This means waste of disk space, but no harm to data.
116
+No errors were found on the image.
117
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
118
119
Event: l2_update; errno: 28; imm: off; once: on; write
120
@@ -XXX,XX +XXX,XX @@ Event: l2_update; errno: 28; imm: off; once: off; write
121
qemu-io: Failed to flush the L2 table cache: No space left on device
122
qemu-io: Failed to flush the refcount block cache: No space left on device
123
write failed: No space left on device
124
-
125
-127 leaked clusters were found on the image.
126
-This means waste of disk space, but no harm to data.
127
+No errors were found on the image.
128
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
129
130
Event: l2_update; errno: 28; imm: off; once: off; write -b
131
qemu-io: Failed to flush the L2 table cache: No space left on device
132
qemu-io: Failed to flush the refcount block cache: No space left on device
133
write failed: No space left on device
134
-
135
-127 leaked clusters were found on the image.
136
-This means waste of disk space, but no harm to data.
137
+No errors were found on the image.
138
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
139
140
Event: l2_alloc_write; errno: 5; imm: off; once: on; write
141
@@ -XXX,XX +XXX,XX @@ Event: l2_alloc_write; errno: 5; imm: off; once: off; write -b
142
qemu-io: Failed to flush the L2 table cache: Input/output error
143
qemu-io: Failed to flush the refcount block cache: Input/output error
144
write failed: Input/output error
145
-
146
-1 leaked clusters were found on the image.
147
-This means waste of disk space, but no harm to data.
148
+No errors were found on the image.
149
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
150
151
Event: l2_alloc_write; errno: 28; imm: off; once: on; write
152
@@ -XXX,XX +XXX,XX @@ Event: l2_alloc_write; errno: 28; imm: off; once: off; write -b
153
qemu-io: Failed to flush the L2 table cache: No space left on device
154
qemu-io: Failed to flush the refcount block cache: No space left on device
155
write failed: No space left on device
156
-
157
-1 leaked clusters were found on the image.
158
-This means waste of disk space, but no harm to data.
159
+No errors were found on the image.
160
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
161
162
Event: write_aio; errno: 5; imm: off; once: on; write
163
@@ -XXX,XX +XXX,XX @@ Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write
164
qemu-io: Failed to flush the L2 table cache: No space left on device
165
qemu-io: Failed to flush the refcount block cache: No space left on device
166
write failed: No space left on device
167
-
168
-55 leaked clusters were found on the image.
169
-This means waste of disk space, but no harm to data.
170
+No errors were found on the image.
171
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
172
173
Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write -b
174
qemu-io: Failed to flush the L2 table cache: No space left on device
175
qemu-io: Failed to flush the refcount block cache: No space left on device
176
write failed: No space left on device
177
-
178
-251 leaked clusters were found on the image.
179
-This means waste of disk space, but no harm to data.
180
+No errors were found on the image.
181
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
182
183
Event: refblock_alloc_write; errno: 28; imm: off; once: on; write
184
@@ -XXX,XX +XXX,XX @@ Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write
185
qemu-io: Failed to flush the L2 table cache: No space left on device
186
qemu-io: Failed to flush the refcount block cache: No space left on device
187
write failed: No space left on device
188
-
189
-10 leaked clusters were found on the image.
190
-This means waste of disk space, but no harm to data.
191
+No errors were found on the image.
192
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
193
194
Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b
195
qemu-io: Failed to flush the L2 table cache: No space left on device
196
qemu-io: Failed to flush the refcount block cache: No space left on device
197
write failed: No space left on device
198
-
199
-23 leaked clusters were found on the image.
200
-This means waste of disk space, but no harm to data.
201
+No errors were found on the image.
202
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
203
204
Event: refblock_alloc_write_table; errno: 28; imm: off; once: on; write
205
@@ -XXX,XX +XXX,XX @@ Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write
206
qemu-io: Failed to flush the L2 table cache: No space left on device
207
qemu-io: Failed to flush the refcount block cache: No space left on device
208
write failed: No space left on device
209
-
210
-10 leaked clusters were found on the image.
211
-This means waste of disk space, but no harm to data.
212
+No errors were found on the image.
213
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
214
215
Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b
216
qemu-io: Failed to flush the L2 table cache: No space left on device
217
qemu-io: Failed to flush the refcount block cache: No space left on device
218
write failed: No space left on device
219
-
220
-23 leaked clusters were found on the image.
221
-This means waste of disk space, but no harm to data.
222
+No errors were found on the image.
223
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
224
225
Event: refblock_alloc_switch_table; errno: 28; imm: off; once: on; write
226
@@ -XXX,XX +XXX,XX @@ Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write
227
qemu-io: Failed to flush the L2 table cache: No space left on device
228
qemu-io: Failed to flush the refcount block cache: No space left on device
229
write failed: No space left on device
230
-
231
-10 leaked clusters were found on the image.
232
-This means waste of disk space, but no harm to data.
233
+No errors were found on the image.
234
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
235
236
Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write -b
237
qemu-io: Failed to flush the L2 table cache: No space left on device
238
qemu-io: Failed to flush the refcount block cache: No space left on device
239
write failed: No space left on device
240
-
241
-23 leaked clusters were found on the image.
242
-This means waste of disk space, but no harm to data.
243
+No errors were found on the image.
244
245
=== L1 growth tests ===
246
247
@@ -XXX,XX +XXX,XX @@ Event: l1_grow_activate_table; errno: 5; imm: off; once: off
248
qemu-io: Failed to flush the L2 table cache: Input/output error
249
qemu-io: Failed to flush the refcount block cache: Input/output error
250
write failed: Input/output error
251
-
252
-96 leaked clusters were found on the image.
253
-This means waste of disk space, but no harm to data.
254
+No errors were found on the image.
255
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
256
257
Event: l1_grow_activate_table; errno: 28; imm: off; once: on
258
@@ -XXX,XX +XXX,XX @@ Event: l1_grow_activate_table; errno: 28; imm: off; once: off
259
qemu-io: Failed to flush the L2 table cache: No space left on device
260
qemu-io: Failed to flush the refcount block cache: No space left on device
261
write failed: No space left on device
262
-
263
-96 leaked clusters were found on the image.
264
-This means waste of disk space, but no harm to data.
265
+No errors were found on the image.
266
267
=== Avoid cluster leaks after temporary failure ===
268
269
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
270
index XXXXXXX..XXXXXXX 100644
271
--- a/tests/qemu-iotests/026.out.nocache
272
+++ b/tests/qemu-iotests/026.out.nocache
273
@@ -XXX,XX +XXX,XX @@ Event: l1_update; errno: 5; imm: off; once: off; write
274
qemu-io: Failed to flush the L2 table cache: Input/output error
275
qemu-io: Failed to flush the refcount block cache: Input/output error
276
write failed: Input/output error
277
-
278
-1 leaked clusters were found on the image.
279
-This means waste of disk space, but no harm to data.
280
+No errors were found on the image.
281
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
282
283
Event: l1_update; errno: 5; imm: off; once: off; write -b
284
qemu-io: Failed to flush the L2 table cache: Input/output error
285
qemu-io: Failed to flush the refcount block cache: Input/output error
286
write failed: Input/output error
287
-
288
-1 leaked clusters were found on the image.
289
-This means waste of disk space, but no harm to data.
290
+No errors were found on the image.
291
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
292
293
Event: l1_update; errno: 28; imm: off; once: on; write
294
@@ -XXX,XX +XXX,XX @@ Event: l1_update; errno: 28; imm: off; once: off; write
295
qemu-io: Failed to flush the L2 table cache: No space left on device
296
qemu-io: Failed to flush the refcount block cache: No space left on device
297
write failed: No space left on device
298
-
299
-1 leaked clusters were found on the image.
300
-This means waste of disk space, but no harm to data.
301
+No errors were found on the image.
302
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
303
304
Event: l1_update; errno: 28; imm: off; once: off; write -b
305
qemu-io: Failed to flush the L2 table cache: No space left on device
306
qemu-io: Failed to flush the refcount block cache: No space left on device
307
write failed: No space left on device
308
-
309
-1 leaked clusters were found on the image.
310
-This means waste of disk space, but no harm to data.
311
+No errors were found on the image.
312
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
313
314
Event: l2_load; errno: 5; imm: off; once: on; write
315
@@ -XXX,XX +XXX,XX @@ qemu-io: Failed to flush the L2 table cache: Input/output error
316
qemu-io: Failed to flush the refcount block cache: Input/output error
317
wrote 131072/131072 bytes at offset 0
318
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
319
-
320
-127 leaked clusters were found on the image.
321
-This means waste of disk space, but no harm to data.
322
+No errors were found on the image.
323
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
324
325
Event: l2_update; errno: 5; imm: off; once: off; write -b
326
@@ -XXX,XX +XXX,XX @@ qemu-io: Failed to flush the L2 table cache: Input/output error
327
qemu-io: Failed to flush the refcount block cache: Input/output error
328
wrote 131072/131072 bytes at offset 0
329
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
330
-
331
-127 leaked clusters were found on the image.
332
-This means waste of disk space, but no harm to data.
333
+No errors were found on the image.
334
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
335
336
Event: l2_update; errno: 28; imm: off; once: on; write
337
@@ -XXX,XX +XXX,XX @@ qemu-io: Failed to flush the L2 table cache: No space left on device
338
qemu-io: Failed to flush the refcount block cache: No space left on device
339
wrote 131072/131072 bytes at offset 0
340
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
-
342
-127 leaked clusters were found on the image.
343
-This means waste of disk space, but no harm to data.
344
+No errors were found on the image.
345
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
346
347
Event: l2_update; errno: 28; imm: off; once: off; write -b
348
@@ -XXX,XX +XXX,XX @@ qemu-io: Failed to flush the L2 table cache: No space left on device
349
qemu-io: Failed to flush the refcount block cache: No space left on device
350
wrote 131072/131072 bytes at offset 0
351
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
352
-
353
-127 leaked clusters were found on the image.
354
-This means waste of disk space, but no harm to data.
355
+No errors were found on the image.
356
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
357
358
Event: l2_alloc_write; errno: 5; imm: off; once: on; write
359
@@ -XXX,XX +XXX,XX @@ Event: l2_alloc_write; errno: 5; imm: off; once: off; write -b
360
qemu-io: Failed to flush the L2 table cache: Input/output error
361
qemu-io: Failed to flush the refcount block cache: Input/output error
362
write failed: Input/output error
363
-
364
-1 leaked clusters were found on the image.
365
-This means waste of disk space, but no harm to data.
366
+No errors were found on the image.
367
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
368
369
Event: l2_alloc_write; errno: 28; imm: off; once: on; write
370
@@ -XXX,XX +XXX,XX @@ Event: l2_alloc_write; errno: 28; imm: off; once: off; write -b
371
qemu-io: Failed to flush the L2 table cache: No space left on device
372
qemu-io: Failed to flush the refcount block cache: No space left on device
373
write failed: No space left on device
374
-
375
-1 leaked clusters were found on the image.
376
-This means waste of disk space, but no harm to data.
377
+No errors were found on the image.
378
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
379
380
Event: write_aio; errno: 5; imm: off; once: on; write
381
@@ -XXX,XX +XXX,XX @@ Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write
382
qemu-io: Failed to flush the L2 table cache: No space left on device
383
qemu-io: Failed to flush the refcount block cache: No space left on device
384
write failed: No space left on device
385
-
386
-55 leaked clusters were found on the image.
387
-This means waste of disk space, but no harm to data.
388
+No errors were found on the image.
389
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
390
391
Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write -b
392
qemu-io: Failed to flush the L2 table cache: No space left on device
393
qemu-io: Failed to flush the refcount block cache: No space left on device
394
write failed: No space left on device
395
-
396
-251 leaked clusters were found on the image.
397
-This means waste of disk space, but no harm to data.
398
+No errors were found on the image.
399
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
400
401
Event: refblock_alloc_write; errno: 28; imm: off; once: on; write
402
@@ -XXX,XX +XXX,XX @@ Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write
403
qemu-io: Failed to flush the L2 table cache: No space left on device
404
qemu-io: Failed to flush the refcount block cache: No space left on device
405
write failed: No space left on device
406
-
407
-10 leaked clusters were found on the image.
408
-This means waste of disk space, but no harm to data.
409
+No errors were found on the image.
410
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
411
412
Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b
413
qemu-io: Failed to flush the L2 table cache: No space left on device
414
qemu-io: Failed to flush the refcount block cache: No space left on device
415
write failed: No space left on device
416
-
417
-23 leaked clusters were found on the image.
418
-This means waste of disk space, but no harm to data.
419
+No errors were found on the image.
420
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
421
422
Event: refblock_alloc_write_table; errno: 28; imm: off; once: on; write
423
@@ -XXX,XX +XXX,XX @@ Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write
424
qemu-io: Failed to flush the L2 table cache: No space left on device
425
qemu-io: Failed to flush the refcount block cache: No space left on device
426
write failed: No space left on device
427
-
428
-10 leaked clusters were found on the image.
429
-This means waste of disk space, but no harm to data.
430
+No errors were found on the image.
431
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
432
433
Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b
434
qemu-io: Failed to flush the L2 table cache: No space left on device
435
qemu-io: Failed to flush the refcount block cache: No space left on device
436
write failed: No space left on device
437
-
438
-23 leaked clusters were found on the image.
439
-This means waste of disk space, but no harm to data.
440
+No errors were found on the image.
441
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
442
443
Event: refblock_alloc_switch_table; errno: 28; imm: off; once: on; write
444
@@ -XXX,XX +XXX,XX @@ Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write
445
qemu-io: Failed to flush the L2 table cache: No space left on device
446
qemu-io: Failed to flush the refcount block cache: No space left on device
447
write failed: No space left on device
448
-
449
-10 leaked clusters were found on the image.
450
-This means waste of disk space, but no harm to data.
451
+No errors were found on the image.
452
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
453
454
Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write -b
455
qemu-io: Failed to flush the L2 table cache: No space left on device
456
qemu-io: Failed to flush the refcount block cache: No space left on device
457
write failed: No space left on device
458
-
459
-23 leaked clusters were found on the image.
460
-This means waste of disk space, but no harm to data.
461
+No errors were found on the image.
462
463
=== L1 growth tests ===
464
465
@@ -XXX,XX +XXX,XX @@ Event: l1_grow_activate_table; errno: 5; imm: off; once: off
466
qemu-io: Failed to flush the L2 table cache: Input/output error
467
qemu-io: Failed to flush the refcount block cache: Input/output error
468
write failed: Input/output error
469
-
470
-96 leaked clusters were found on the image.
471
-This means waste of disk space, but no harm to data.
472
+No errors were found on the image.
473
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
474
475
Event: l1_grow_activate_table; errno: 28; imm: off; once: on
476
@@ -XXX,XX +XXX,XX @@ Event: l1_grow_activate_table; errno: 28; imm: off; once: off
477
qemu-io: Failed to flush the L2 table cache: No space left on device
478
qemu-io: Failed to flush the refcount block cache: No space left on device
479
write failed: No space left on device
480
-
481
-96 leaked clusters were found on the image.
482
-This means waste of disk space, but no harm to data.
483
+No errors were found on the image.
484
485
=== Avoid cluster leaks after temporary failure ===
486
487
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
488
index XXXXXXX..XXXXXXX 100644
489
--- a/tests/qemu-iotests/common.rc
490
+++ b/tests/qemu-iotests/common.rc
491
@@ -XXX,XX +XXX,XX @@ _check_test_img()
492
$QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1
493
fi
494
) | _filter_testdir | _filter_qemu_img_check
495
+
496
+ # return real qemu_img check status, to analyze in
497
+ # _check_test_img_ignore_leaks
498
+ return ${PIPESTATUS[0]}
499
+}
500
+
501
+_check_test_img_ignore_leaks()
502
+{
503
+ out=$(_check_test_img "$@")
504
+ status=$?
505
+ if [ $status = 3 ]; then
506
+ # This must correspond to success output in dump_human_image_check()
507
+ echo "No errors were found on the image."
508
+ return 0
509
+ fi
510
+ echo "$out"
511
+ return $status
512
}
513
514
_img_info()
515
--
516
2.21.0
517
518
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The AioContext pointer argument to co_aio_sleep_ns() is only used for
2
the sleep timer. It does not affect where the caller coroutine is
3
resumed.
2
4
3
Split block_copy_set_callbacks out of block_copy_state_new. It's needed
5
Due to changes to coroutine and AIO APIs it is now possible to drop the
4
for further commit: block-copy will use BdrvChildren of backup-top
6
AioContext pointer argument. This is safe to do since no caller has
5
filter, so it will be created from backup-top filter creation function.
7
specific requirements for which AioContext the timer must run in.
6
But callbacks will still belong to backup job and will be set in
7
separate.
8
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
This patch drops the AioContext pointer argument and renames the
10
Message-id: 20191001131409.14202-4-vsementsov@virtuozzo.com
10
function to simplify the API.
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reported-by: Paolo Bonzini <pbonzini@redhat.com>
13
Reported-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Message-id: 20171109102652.6360-1-stefanha@redhat.com
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
18
---
14
include/block/block-copy.h | 13 +++++++++----
19
include/qemu/coroutine.h | 6 +-----
15
block/backup.c | 6 ++++--
20
block/null.c | 3 +--
16
block/block-copy.c | 24 +++++++++++++++---------
21
block/sheepdog.c | 3 +--
17
3 files changed, 28 insertions(+), 15 deletions(-)
22
util/qemu-coroutine-sleep.c | 4 ++--
23
4 files changed, 5 insertions(+), 11 deletions(-)
18
24
19
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
25
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
20
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/block-copy.h
27
--- a/include/qemu/coroutine.h
22
+++ b/include/block/block-copy.h
28
+++ b/include/qemu/coroutine.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
29
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_unlock(CoRwlock *lock);
24
void *progress_opaque;
30
25
} BlockCopyState;
31
/**
26
32
* Yield the coroutine for a given duration
27
-BlockCopyState *block_copy_state_new(
33
- *
28
- BlockDriverState *source, BlockDriverState *target,
34
- * Behaves similarly to co_sleep_ns(), but the sleeping coroutine will be
29
- int64_t cluster_size, BdrvRequestFlags write_flags,
35
- * resumed when using aio_poll().
30
+BlockCopyState *block_copy_state_new(BlockDriverState *source,
36
*/
31
+ BlockDriverState *target,
37
-void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
32
+ int64_t cluster_size,
38
- int64_t ns);
33
+ BdrvRequestFlags write_flags,
39
+void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns);
34
+ Error **errp);
40
35
+
41
/**
36
+void block_copy_set_callbacks(
42
* Yield until a file descriptor becomes readable
37
+ BlockCopyState *s,
43
diff --git a/block/null.c b/block/null.c
38
ProgressBytesCallbackFunc progress_bytes_callback,
39
ProgressResetCallbackFunc progress_reset_callback,
40
- void *progress_opaque, Error **errp);
41
+ void *progress_opaque);
42
43
void block_copy_state_free(BlockCopyState *s);
44
45
diff --git a/block/backup.c b/block/backup.c
46
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
47
--- a/block/backup.c
45
--- a/block/null.c
48
+++ b/block/backup.c
46
+++ b/block/null.c
49
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
47
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int null_co_common(BlockDriverState *bs)
50
job->bitmap_mode = bitmap_mode;
48
BDRVNullState *s = bs->opaque;
51
49
52
job->bcs = block_copy_state_new(bs, target, cluster_size, write_flags,
50
if (s->latency_ns) {
53
- backup_progress_bytes_callback,
51
- co_aio_sleep_ns(bdrv_get_aio_context(bs), QEMU_CLOCK_REALTIME,
54
- backup_progress_reset_callback, job, errp);
52
- s->latency_ns);
55
+ errp);
53
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, s->latency_ns);
56
if (!job->bcs) {
57
goto error;
58
}
54
}
59
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
55
return 0;
60
job->cluster_size = cluster_size;
56
}
61
job->len = len;
57
diff --git a/block/sheepdog.c b/block/sheepdog.c
62
63
+ block_copy_set_callbacks(job->bcs, backup_progress_bytes_callback,
64
+ backup_progress_reset_callback, job);
65
+
66
/* Required permissions are already taken by block-copy-state target */
67
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
68
&error_abort);
69
diff --git a/block/block-copy.c b/block/block-copy.c
70
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
71
--- a/block/block-copy.c
59
--- a/block/sheepdog.c
72
+++ b/block/block-copy.c
60
+++ b/block/sheepdog.c
73
@@ -XXX,XX +XXX,XX @@ void block_copy_state_free(BlockCopyState *s)
61
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
74
g_free(s);
62
if (s->fd < 0) {
63
DPRINTF("Wait for connection to be established\n");
64
error_report_err(local_err);
65
- co_aio_sleep_ns(bdrv_get_aio_context(s->bs), QEMU_CLOCK_REALTIME,
66
- 1000000000ULL);
67
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000000ULL);
68
}
69
};
70
71
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/util/qemu-coroutine-sleep.c
74
+++ b/util/qemu-coroutine-sleep.c
75
@@ -XXX,XX +XXX,XX @@ static void co_sleep_cb(void *opaque)
76
aio_co_wake(sleep_cb->co);
75
}
77
}
76
78
77
-BlockCopyState *block_copy_state_new(
79
-void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
78
- BlockDriverState *source, BlockDriverState *target,
80
- int64_t ns)
79
- int64_t cluster_size, BdrvRequestFlags write_flags,
81
+void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
80
- ProgressBytesCallbackFunc progress_bytes_callback,
81
- ProgressResetCallbackFunc progress_reset_callback,
82
- void *progress_opaque, Error **errp)
83
+BlockCopyState *block_copy_state_new(BlockDriverState *source,
84
+ BlockDriverState *target,
85
+ int64_t cluster_size,
86
+ BdrvRequestFlags write_flags, Error **errp)
87
{
82
{
88
BlockCopyState *s;
83
+ AioContext *ctx = qemu_get_current_aio_context();
89
int ret;
84
CoSleepCB sleep_cb = {
90
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(
85
.co = qemu_coroutine_self(),
91
.cluster_size = cluster_size,
92
.len = bdrv_dirty_bitmap_size(copy_bitmap),
93
.write_flags = write_flags,
94
- .progress_bytes_callback = progress_bytes_callback,
95
- .progress_reset_callback = progress_reset_callback,
96
- .progress_opaque = progress_opaque,
97
};
86
};
98
99
s->copy_range_size = QEMU_ALIGN_DOWN(MIN(blk_get_max_transfer(s->source),
100
@@ -XXX,XX +XXX,XX @@ fail:
101
return NULL;
102
}
103
104
+void block_copy_set_callbacks(
105
+ BlockCopyState *s,
106
+ ProgressBytesCallbackFunc progress_bytes_callback,
107
+ ProgressResetCallbackFunc progress_reset_callback,
108
+ void *progress_opaque)
109
+{
110
+ s->progress_bytes_callback = progress_bytes_callback;
111
+ s->progress_reset_callback = progress_reset_callback;
112
+ s->progress_opaque = progress_opaque;
113
+}
114
+
115
/*
116
* Copy range to target with a bounce buffer and return the bytes copied. If
117
* error occurred, return a negative error number
118
--
87
--
119
2.21.0
88
2.14.3
120
89
121
90
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
This is logic-less refactoring, which simplifies further patch, as
3
Convert nvme_init() to realize and rename it to nvme_realize().
4
we'll need write_flags for backup-top filter creation and backup-top
5
should be created before block job creation.
6
4
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Cc: John Snow <jsnow@redhat.com>
8
Message-id: 20191001131409.14202-3-vsementsov@virtuozzo.com
6
Cc: Keith Busch <keith.busch@intel.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Cc: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Cc: Max Reitz <mreitz@redhat.com>
9
Cc: Markus Armbruster <armbru@redhat.com>
10
11
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
12
Message-id: 2882e72d795e04cbe2120f569d551aef2467ac60.1511317952.git.maozy.fnst@cn.fujitsu.com
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
14
---
12
block/backup.c | 30 +++++++++++++++---------------
15
hw/block/nvme.c | 18 ++++++++++--------
13
1 file changed, 15 insertions(+), 15 deletions(-)
16
1 file changed, 10 insertions(+), 8 deletions(-)
14
17
15
diff --git a/block/backup.c b/block/backup.c
18
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/block/backup.c
20
--- a/hw/block/nvme.c
18
+++ b/block/backup.c
21
+++ b/hw/block/nvme.c
19
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
22
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvme_cmb_ops = {
20
goto error;
23
},
24
};
25
26
-static int nvme_init(PCIDevice *pci_dev)
27
+static void nvme_realize(PCIDevice *pci_dev, Error **errp)
28
{
29
NvmeCtrl *n = NVME(pci_dev);
30
NvmeIdCtrl *id = &n->id_ctrl;
31
@@ -XXX,XX +XXX,XX @@ static int nvme_init(PCIDevice *pci_dev)
32
Error *local_err = NULL;
33
34
if (!n->conf.blk) {
35
- return -1;
36
+ error_setg(errp, "drive property not set");
37
+ return;
21
}
38
}
22
39
23
- /* job->len is fixed, so we can't allow resize */
40
bs_size = blk_getlength(n->conf.blk);
24
- job = block_job_create(job_id, &backup_job_driver, txn, bs, 0, BLK_PERM_ALL,
41
if (bs_size < 0) {
25
- speed, creation_flags, cb, opaque, errp);
42
- return -1;
26
- if (!job) {
43
+ error_setg(errp, "could not get backing file size");
27
- goto error;
44
+ return;
28
- }
29
-
30
- job->source_bs = bs;
31
- job->on_source_error = on_source_error;
32
- job->on_target_error = on_target_error;
33
- job->sync_mode = sync_mode;
34
- job->sync_bitmap = sync_bitmap;
35
- job->bitmap_mode = bitmap_mode;
36
-
37
/*
38
* If source is in backing chain of target assume that target is going to be
39
* used for "image fleecing", i.e. it should represent a kind of snapshot of
40
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
41
write_flags = (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
42
(compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
43
44
+ /* job->len is fixed, so we can't allow resize */
45
+ job = block_job_create(job_id, &backup_job_driver, txn, bs, 0, BLK_PERM_ALL,
46
+ speed, creation_flags, cb, opaque, errp);
47
+ if (!job) {
48
+ goto error;
49
+ }
50
+
51
+ job->source_bs = bs;
52
+ job->on_source_error = on_source_error;
53
+ job->on_target_error = on_target_error;
54
+ job->sync_mode = sync_mode;
55
+ job->sync_bitmap = sync_bitmap;
56
+ job->bitmap_mode = bitmap_mode;
57
+
58
job->bcs = block_copy_state_new(bs, target, cluster_size, write_flags,
59
backup_progress_bytes_callback,
60
backup_progress_reset_callback, job, errp);
61
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
62
}
45
}
63
46
64
job->cluster_size = cluster_size;
47
blkconf_serial(&n->conf, &n->serial);
65
+ job->len = len;
48
if (!n->serial) {
66
49
- return -1;
67
/* Required permissions are already taken by block-copy-state target */
50
+ error_setg(errp, "serial property not set");
68
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
51
+ return;
69
&error_abort);
52
}
70
- job->len = len;
53
blkconf_blocksizes(&n->conf);
71
54
blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
72
return &job->common;
55
false, &local_err);
73
56
if (local_err) {
57
- error_report_err(local_err);
58
- return -1;
59
+ error_propagate(errp, local_err);
60
+ return;
61
}
62
63
pci_conf = pci_dev->config;
64
@@ -XXX,XX +XXX,XX @@ static int nvme_init(PCIDevice *pci_dev)
65
cpu_to_le64(n->ns_size >>
66
id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas)].ds);
67
}
68
- return 0;
69
}
70
71
static void nvme_exit(PCIDevice *pci_dev)
72
@@ -XXX,XX +XXX,XX @@ static void nvme_class_init(ObjectClass *oc, void *data)
73
DeviceClass *dc = DEVICE_CLASS(oc);
74
PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
75
76
- pc->init = nvme_init;
77
+ pc->realize = nvme_realize;
78
pc->exit = nvme_exit;
79
pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
80
pc->vendor_id = PCI_VENDOR_ID_INTEL;
74
--
81
--
75
2.21.0
82
2.14.3
76
83
77
84
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
Split copying logic which will be shared with backup-top filter.
3
When the function no success value to transmit, it usually make the
4
function return void. It has turned out not to be a success, because
5
it means that the extra local_err variable and error_propagate() will
6
be needed. It leads to cumbersome code, therefore, transmit success/
7
failure in the return value is worth.
4
8
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
So fix the return type of blkconf_apply_backend_options(),
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
blkconf_geometry() and virtio_blk_data_plane_create() to avoid it.
7
Message-id: 20190920142056.12778-4-vsementsov@virtuozzo.com
11
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Cc: John Snow <jsnow@redhat.com>
13
Cc: Kevin Wolf <kwolf@redhat.com>
14
Cc: Max Reitz <mreitz@redhat.com>
15
Cc: Stefan Hajnoczi <stefanha@redhat.com>
16
17
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Message-id: ac0edc1fc70c4457e5cec94405eb7d1f89f9c2c1.1511317952.git.maozy.fnst@cn.fujitsu.com
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
21
---
10
block/backup.c | 47 ++++++++++++++++++++++++++++++++---------------
22
hw/block/dataplane/virtio-blk.h | 2 +-
11
1 file changed, 32 insertions(+), 15 deletions(-)
23
include/hw/block/block.h | 4 ++--
24
hw/block/block.c | 15 +++++++++------
25
hw/block/dataplane/virtio-blk.c | 12 +++++++-----
26
4 files changed, 19 insertions(+), 14 deletions(-)
12
27
13
diff --git a/block/backup.c b/block/backup.c
28
diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h
14
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
15
--- a/block/backup.c
30
--- a/hw/block/dataplane/virtio-blk.h
16
+++ b/block/backup.c
31
+++ b/hw/block/dataplane/virtio-blk.h
17
@@ -XXX,XX +XXX,XX @@ static int64_t backup_bitmap_reset_unallocated(BackupBlockJob *s,
32
@@ -XXX,XX +XXX,XX @@
18
return ret;
33
34
typedef struct VirtIOBlockDataPlane VirtIOBlockDataPlane;
35
36
-void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
37
+bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
38
VirtIOBlockDataPlane **dataplane,
39
Error **errp);
40
void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s);
41
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/hw/block/block.h
44
+++ b/include/hw/block/block.h
45
@@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
46
/* Configuration helpers */
47
48
void blkconf_serial(BlockConf *conf, char **serial);
49
-void blkconf_geometry(BlockConf *conf, int *trans,
50
+bool blkconf_geometry(BlockConf *conf, int *trans,
51
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
52
Error **errp);
53
void blkconf_blocksizes(BlockConf *conf);
54
-void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
55
+bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
56
bool resizable, Error **errp);
57
58
/* Hard disk geometry */
59
diff --git a/hw/block/block.c b/hw/block/block.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/block/block.c
62
+++ b/hw/block/block.c
63
@@ -XXX,XX +XXX,XX @@ void blkconf_blocksizes(BlockConf *conf)
64
}
19
}
65
}
20
66
21
-static int coroutine_fn backup_do_cow(BackupBlockJob *job,
67
-void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
22
- int64_t offset, uint64_t bytes,
68
+bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
23
- bool *error_is_read,
69
bool resizable, Error **errp)
24
- bool is_write_notifier)
25
+static int coroutine_fn backup_do_copy(BackupBlockJob *job,
26
+ int64_t start, uint64_t bytes,
27
+ bool *error_is_read,
28
+ bool is_write_notifier)
29
{
70
{
30
- CowRequest cow_request;
71
BlockBackend *blk = conf->blk;
31
int ret = 0;
72
@@ -XXX,XX +XXX,XX @@ void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
32
- int64_t start, end; /* bytes */
73
33
+ int64_t end = bytes + start; /* bytes */
74
ret = blk_set_perm(blk, perm, shared_perm, errp);
34
void *bounce_buffer = NULL;
75
if (ret < 0) {
35
int64_t status_bytes;
76
- return;
36
77
+ return false;
37
- qemu_co_rwlock_rdlock(&job->flush_rwlock);
38
-
39
- start = QEMU_ALIGN_DOWN(offset, job->cluster_size);
40
- end = QEMU_ALIGN_UP(bytes + offset, job->cluster_size);
41
-
42
- trace_backup_do_cow_enter(job, start, offset, bytes);
43
-
44
- wait_for_overlapping_requests(job, start, end);
45
- cow_request_begin(&cow_request, job, start, end);
46
+ assert(QEMU_IS_ALIGNED(start, job->cluster_size));
47
+ assert(QEMU_IS_ALIGNED(end, job->cluster_size));
48
49
while (start < end) {
50
int64_t dirty_end;
51
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
52
qemu_vfree(bounce_buffer);
53
}
78
}
54
79
55
+ return ret;
80
switch (conf->wce) {
56
+}
81
@@ -XXX,XX +XXX,XX @@ void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
82
83
blk_set_enable_write_cache(blk, wce);
84
blk_set_on_error(blk, rerror, werror);
57
+
85
+
58
+static int coroutine_fn backup_do_cow(BackupBlockJob *job,
86
+ return true;
59
+ int64_t offset, uint64_t bytes,
87
}
60
+ bool *error_is_read,
88
61
+ bool is_write_notifier)
89
-void blkconf_geometry(BlockConf *conf, int *ptrans,
62
+{
90
+bool blkconf_geometry(BlockConf *conf, int *ptrans,
63
+ CowRequest cow_request;
91
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
64
+ int ret = 0;
92
Error **errp)
65
+ int64_t start, end; /* bytes */
93
{
94
@@ -XXX,XX +XXX,XX @@ void blkconf_geometry(BlockConf *conf, int *ptrans,
95
if (conf->cyls || conf->heads || conf->secs) {
96
if (conf->cyls < 1 || conf->cyls > cyls_max) {
97
error_setg(errp, "cyls must be between 1 and %u", cyls_max);
98
- return;
99
+ return false;
100
}
101
if (conf->heads < 1 || conf->heads > heads_max) {
102
error_setg(errp, "heads must be between 1 and %u", heads_max);
103
- return;
104
+ return false;
105
}
106
if (conf->secs < 1 || conf->secs > secs_max) {
107
error_setg(errp, "secs must be between 1 and %u", secs_max);
108
- return;
109
+ return false;
110
}
111
}
112
+ return true;
113
}
114
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/hw/block/dataplane/virtio-blk.c
117
+++ b/hw/block/dataplane/virtio-blk.c
118
@@ -XXX,XX +XXX,XX @@ static void notify_guest_bh(void *opaque)
119
}
120
121
/* Context: QEMU global mutex held */
122
-void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
123
+bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
124
VirtIOBlockDataPlane **dataplane,
125
Error **errp)
126
{
127
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
128
error_setg(errp,
129
"device is incompatible with iothread "
130
"(transport does not support notifiers)");
131
- return;
132
+ return false;
133
}
134
if (!virtio_device_ioeventfd_enabled(vdev)) {
135
error_setg(errp, "ioeventfd is required for iothread");
136
- return;
137
+ return false;
138
}
139
140
/* If dataplane is (re-)enabled while the guest is running there could
141
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
142
*/
143
if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
144
error_prepend(errp, "cannot start virtio-blk dataplane: ");
145
- return;
146
+ return false;
147
}
148
}
149
/* Don't try if transport does not support notifiers. */
150
if (!virtio_device_ioeventfd_enabled(vdev)) {
151
- return;
152
+ return false;
153
}
154
155
s = g_new0(VirtIOBlockDataPlane, 1);
156
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
157
s->batch_notify_vqs = bitmap_new(conf->num_queues);
158
159
*dataplane = s;
66
+
160
+
67
+ qemu_co_rwlock_rdlock(&job->flush_rwlock);
161
+ return true;
68
+
162
}
69
+ start = QEMU_ALIGN_DOWN(offset, job->cluster_size);
163
70
+ end = QEMU_ALIGN_UP(bytes + offset, job->cluster_size);
164
/* Context: QEMU global mutex held */
71
+
72
+ trace_backup_do_cow_enter(job, start, offset, bytes);
73
+
74
+ wait_for_overlapping_requests(job, start, end);
75
+ cow_request_begin(&cow_request, job, start, end);
76
+
77
+ ret = backup_do_copy(job, start, end - start, error_is_read,
78
+ is_write_notifier);
79
+
80
cow_request_end(&cow_request);
81
82
trace_backup_do_cow_return(job, offset, bytes, ret);
83
--
165
--
84
2.21.0
166
2.14.3
85
167
86
168
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
it allows to report it in the error handler
3
[Drop virtio_blk_data_plane_create() change that misinterprets return
4
4
value when the virtio transport does not support dataplane.
5
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
5
--Stefan]
6
Message-id: 20190923121737.83281-6-anton.nefedov@virtuozzo.com
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Cc: John Snow <jsnow@redhat.com>
8
Cc: Kevin Wolf <kwolf@redhat.com>
9
Cc: Max Reitz <mreitz@redhat.com>
10
Cc: Keith Busch <keith.busch@intel.com>
11
Cc: Stefan Hajnoczi <stefanha@redhat.com>
12
Cc: "Michael S. Tsirkin" <mst@redhat.com>
13
Cc: Paolo Bonzini <pbonzini@redhat.com>
14
Cc: Gerd Hoffmann <kraxel@redhat.com>
15
Cc: Markus Armbruster <armbru@redhat.com>
16
17
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Message-id: e77848d3735ba590f23ffbf8094379c646c33d79.1511317952.git.maozy.fnst@cn.fujitsu.com
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
21
---
9
hw/scsi/scsi-disk.c | 14 +++++++-------
22
hw/block/fdc.c | 17 ++++++-----------
10
1 file changed, 7 insertions(+), 7 deletions(-)
23
hw/block/nvme.c | 7 ++-----
11
24
hw/block/virtio-blk.c | 13 +++++--------
25
hw/ide/qdev.c | 12 ++++--------
26
hw/scsi/scsi-disk.c | 13 ++++---------
27
hw/usb/dev-storage.c | 9 +++------
28
6 files changed, 24 insertions(+), 47 deletions(-)
29
30
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/block/fdc.c
33
+++ b/hw/block/fdc.c
34
@@ -XXX,XX +XXX,XX @@ static void fd_revalidate(FDrive *drv)
35
static void fd_change_cb(void *opaque, bool load, Error **errp)
36
{
37
FDrive *drive = opaque;
38
- Error *local_err = NULL;
39
40
if (!load) {
41
blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort);
42
} else {
43
- blkconf_apply_backend_options(drive->conf,
44
- blk_is_read_only(drive->blk), false,
45
- &local_err);
46
- if (local_err) {
47
- error_propagate(errp, local_err);
48
+ if (!blkconf_apply_backend_options(drive->conf,
49
+ blk_is_read_only(drive->blk), false,
50
+ errp)) {
51
return;
52
}
53
}
54
@@ -XXX,XX +XXX,XX @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
55
FloppyDrive *dev = FLOPPY_DRIVE(qdev);
56
FloppyBus *bus = FLOPPY_BUS(qdev->parent_bus);
57
FDrive *drive;
58
- Error *local_err = NULL;
59
int ret;
60
61
if (dev->unit == -1) {
62
@@ -XXX,XX +XXX,XX @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
63
dev->conf.rerror = BLOCKDEV_ON_ERROR_AUTO;
64
dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO;
65
66
- blkconf_apply_backend_options(&dev->conf, blk_is_read_only(dev->conf.blk),
67
- false, &local_err);
68
- if (local_err) {
69
- error_propagate(errp, local_err);
70
+ if (!blkconf_apply_backend_options(&dev->conf,
71
+ blk_is_read_only(dev->conf.blk),
72
+ false, errp)) {
73
return;
74
}
75
76
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/block/nvme.c
79
+++ b/hw/block/nvme.c
80
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
81
int i;
82
int64_t bs_size;
83
uint8_t *pci_conf;
84
- Error *local_err = NULL;
85
86
if (!n->conf.blk) {
87
error_setg(errp, "drive property not set");
88
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
89
return;
90
}
91
blkconf_blocksizes(&n->conf);
92
- blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
93
- false, &local_err);
94
- if (local_err) {
95
- error_propagate(errp, local_err);
96
+ if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
97
+ false, errp)) {
98
return;
99
}
100
101
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/block/virtio-blk.c
104
+++ b/hw/block/virtio-blk.c
105
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
106
}
107
108
blkconf_serial(&conf->conf, &conf->serial);
109
- blkconf_apply_backend_options(&conf->conf,
110
- blk_is_read_only(conf->conf.blk), true,
111
- &err);
112
- if (err) {
113
- error_propagate(errp, err);
114
+ if (!blkconf_apply_backend_options(&conf->conf,
115
+ blk_is_read_only(conf->conf.blk), true,
116
+ errp)) {
117
return;
118
}
119
s->original_wce = blk_enable_write_cache(conf->conf.blk);
120
- blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err);
121
- if (err) {
122
- error_propagate(errp, err);
123
+ if (!blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, errp)) {
124
return;
125
}
126
+
127
blkconf_blocksizes(&conf->conf);
128
129
virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
130
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/ide/qdev.c
133
+++ b/hw/ide/qdev.c
134
@@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
135
{
136
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
137
IDEState *s = bus->ifs + dev->unit;
138
- Error *err = NULL;
139
int ret;
140
141
if (!dev->conf.blk) {
142
@@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
143
144
blkconf_serial(&dev->conf, &dev->serial);
145
if (kind != IDE_CD) {
146
- blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, &err);
147
- if (err) {
148
- error_propagate(errp, err);
149
+ if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255,
150
+ errp)) {
151
return;
152
}
153
}
154
- blkconf_apply_backend_options(&dev->conf, kind == IDE_CD, kind != IDE_CD,
155
- &err);
156
- if (err) {
157
- error_propagate(errp, err);
158
+ if (!blkconf_apply_backend_options(&dev->conf, kind == IDE_CD,
159
+ kind != IDE_CD, errp)) {
160
return;
161
}
162
12
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
163
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
13
index XXXXXXX..XXXXXXX 100644
164
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/scsi/scsi-disk.c
165
--- a/hw/scsi/scsi-disk.c
15
+++ b/hw/scsi/scsi-disk.c
166
+++ b/hw/scsi/scsi-disk.c
16
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
167
@@ -XXX,XX +XXX,XX @@ static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
168
static void scsi_realize(SCSIDevice *dev, Error **errp)
17
{
169
{
18
SCSIDiskReq *r = data->r;
170
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
19
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
171
- Error *err = NULL;
20
- uint64_t sector_num;
172
21
- uint32_t nb_sectors;
173
if (!s->qdev.conf.blk) {
22
174
error_setg(errp, "drive property not set");
23
assert(r->req.aiocb == NULL);
175
@@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
24
if (scsi_disk_req_check_error(r, ret, false)) {
176
}
25
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
177
26
}
178
if (dev->type == TYPE_DISK) {
27
179
- blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, &err);
28
if (data->count > 0) {
180
- if (err) {
29
- sector_num = ldq_be_p(&data->inbuf[0]);
181
- error_propagate(errp, err);
30
- nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
182
+ if (!blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, errp)) {
31
- if (!check_lba_range(s, sector_num, nb_sectors)) {
183
return;
32
+ r->sector = ldq_be_p(&data->inbuf[0])
33
+ * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
34
+ r->sector_count = (ldl_be_p(&data->inbuf[8]) & 0xffffffffULL)
35
+ * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
36
+ if (!check_lba_range(s, r->sector, r->sector_count)) {
37
scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
38
goto done;
39
}
184
}
40
185
}
41
r->req.aiocb = blk_aio_pdiscard(s->qdev.conf.blk,
186
- blkconf_apply_backend_options(&dev->conf,
42
- sector_num * s->qdev.blocksize,
187
- blk_is_read_only(s->qdev.conf.blk),
43
- nb_sectors * s->qdev.blocksize,
188
- dev->type == TYPE_DISK, &err);
44
+ r->sector * BDRV_SECTOR_SIZE,
189
- if (err) {
45
+ r->sector_count * BDRV_SECTOR_SIZE,
190
- error_propagate(errp, err);
46
scsi_unmap_complete, data);
191
+ if (!blkconf_apply_backend_options(&dev->conf,
47
data->count--;
192
+ blk_is_read_only(s->qdev.conf.blk),
48
data->inbuf += 16;
193
+ dev->type == TYPE_DISK, errp)) {
194
return;
195
}
196
197
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/usb/dev-storage.c
200
+++ b/hw/usb/dev-storage.c
201
@@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
202
MSDState *s = USB_STORAGE_DEV(dev);
203
BlockBackend *blk = s->conf.blk;
204
SCSIDevice *scsi_dev;
205
- Error *err = NULL;
206
207
if (!blk) {
208
error_setg(errp, "drive property not set");
209
@@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
210
211
blkconf_serial(&s->conf, &dev->serial);
212
blkconf_blocksizes(&s->conf);
213
- blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true, &err);
214
- if (err) {
215
- error_propagate(errp, err);
216
+ if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
217
+ errp)) {
218
return;
219
}
220
221
@@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
222
&usb_msd_scsi_info_storage, NULL);
223
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
224
s->conf.bootindex, dev->serial,
225
- &err);
226
+ errp);
227
blk_unref(blk);
228
if (!scsi_dev) {
229
- error_propagate(errp, err);
230
return;
231
}
232
usb_msd_handle_reset(dev);
49
--
233
--
50
2.21.0
234
2.14.3
51
235
52
236
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
It improves performance for fragmented qcow2 images.
3
The function name of usb_msd_{realize,unrealize}_*,
4
usb_msd_class_initfn_* are unusual. Rename it to
5
usb_msd_*_{realize,unrealize}, usb_msd_class_*_initfn.
4
6
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Cc: Gerd Hoffmann <kraxel@redhat.com>
6
Message-id: 20190916175324.18478-6-vsementsov@virtuozzo.com
8
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 11e6003433abce35f3f4970e1acc71ee92dbcf51.1511317952.git.maozy.fnst@cn.fujitsu.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
13
---
9
block/qcow2.h | 3 ++
14
hw/usb/dev-storage.c | 20 ++++++++++----------
10
block/qcow2.c | 125 ++++++++++++++++++++++++++++++++++++++++-----
15
1 file changed, 10 insertions(+), 10 deletions(-)
11
block/trace-events | 1 +
12
3 files changed, 117 insertions(+), 12 deletions(-)
13
16
14
diff --git a/block/qcow2.h b/block/qcow2.h
17
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow2.h
19
--- a/hw/usb/dev-storage.c
17
+++ b/block/qcow2.h
20
+++ b/hw/usb/dev-storage.c
18
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void usb_msd_unrealize_storage(USBDevice *dev, Error **errp)
19
#define QCOW2_MAX_BITMAPS 65535
22
object_unref(OBJECT(&s->bus));
20
#define QCOW2_MAX_BITMAP_DIRECTORY_SIZE (1024 * QCOW2_MAX_BITMAPS)
21
22
+/* Maximum of parallel sub-request per guest request */
23
+#define QCOW2_MAX_WORKERS 8
24
+
25
/* indicate that the refcount of the referenced cluster is exactly one. */
26
#define QCOW_OFLAG_COPIED (1ULL << 63)
27
/* indicate that the cluster is compressed (they never have the copied flag) */
28
diff --git a/block/qcow2.c b/block/qcow2.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/qcow2.c
31
+++ b/block/qcow2.c
32
@@ -XXX,XX +XXX,XX @@
33
#include "qapi/qobject-input-visitor.h"
34
#include "qapi/qapi-visit-block-core.h"
35
#include "crypto.h"
36
+#include "block/aio_task.h"
37
38
/*
39
Differences with QCOW:
40
@@ -XXX,XX +XXX,XX @@ fail:
41
return ret;
42
}
23
}
43
24
44
+typedef struct Qcow2AioTask {
25
-static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
45
+ AioTask task;
26
+static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
46
+
27
{
47
+ BlockDriverState *bs;
28
MSDState *s = USB_STORAGE_DEV(dev);
48
+ QCow2ClusterType cluster_type; /* only for read */
29
BlockBackend *blk = s->conf.blk;
49
+ uint64_t file_cluster_offset;
30
@@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
50
+ uint64_t offset;
31
s->scsi_dev = scsi_dev;
51
+ uint64_t bytes;
52
+ QEMUIOVector *qiov;
53
+ uint64_t qiov_offset;
54
+ QCowL2Meta *l2meta; /* only for write */
55
+} Qcow2AioTask;
56
+
57
+static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task);
58
+static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
59
+ AioTaskPool *pool,
60
+ AioTaskFunc func,
61
+ QCow2ClusterType cluster_type,
62
+ uint64_t file_cluster_offset,
63
+ uint64_t offset,
64
+ uint64_t bytes,
65
+ QEMUIOVector *qiov,
66
+ size_t qiov_offset,
67
+ QCowL2Meta *l2meta)
68
+{
69
+ Qcow2AioTask local_task;
70
+ Qcow2AioTask *task = pool ? g_new(Qcow2AioTask, 1) : &local_task;
71
+
72
+ *task = (Qcow2AioTask) {
73
+ .task.func = func,
74
+ .bs = bs,
75
+ .cluster_type = cluster_type,
76
+ .qiov = qiov,
77
+ .file_cluster_offset = file_cluster_offset,
78
+ .offset = offset,
79
+ .bytes = bytes,
80
+ .qiov_offset = qiov_offset,
81
+ .l2meta = l2meta,
82
+ };
83
+
84
+ trace_qcow2_add_task(qemu_coroutine_self(), bs, pool,
85
+ func == qcow2_co_preadv_task_entry ? "read" : "write",
86
+ cluster_type, file_cluster_offset, offset, bytes,
87
+ qiov, qiov_offset);
88
+
89
+ if (!pool) {
90
+ return func(&task->task);
91
+ }
92
+
93
+ aio_task_pool_start_task(pool, &task->task);
94
+
95
+ return 0;
96
+}
97
+
98
static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
99
QCow2ClusterType cluster_type,
100
uint64_t file_cluster_offset,
101
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
102
g_assert_not_reached();
103
}
32
}
104
33
105
+static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
34
-static void usb_msd_unrealize_bot(USBDevice *dev, Error **errp)
106
+{
35
+static void usb_msd_bot_unrealize(USBDevice *dev, Error **errp)
107
+ Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
108
+
109
+ assert(!t->l2meta);
110
+
111
+ return qcow2_co_preadv_task(t->bs, t->cluster_type, t->file_cluster_offset,
112
+ t->offset, t->bytes, t->qiov, t->qiov_offset);
113
+}
114
+
115
static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
116
uint64_t offset, uint64_t bytes,
117
QEMUIOVector *qiov,
118
size_t qiov_offset, int flags)
119
{
36
{
120
BDRVQcow2State *s = bs->opaque;
37
MSDState *s = USB_STORAGE_DEV(dev);
121
- int ret;
38
122
+ int ret = 0;
39
object_unref(OBJECT(&s->bus));
123
unsigned int cur_bytes; /* number of bytes in current iteration */
124
uint64_t cluster_offset = 0;
125
+ AioTaskPool *aio = NULL;
126
127
- while (bytes != 0) {
128
-
129
+ while (bytes != 0 && aio_task_pool_status(aio) == 0) {
130
/* prepare next request */
131
cur_bytes = MIN(bytes, INT_MAX);
132
if (s->crypto) {
133
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
134
ret = qcow2_get_cluster_offset(bs, offset, &cur_bytes, &cluster_offset);
135
qemu_co_mutex_unlock(&s->lock);
136
if (ret < 0) {
137
- return ret;
138
+ goto out;
139
}
140
141
if (ret == QCOW2_CLUSTER_ZERO_PLAIN ||
142
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
143
{
144
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
145
} else {
146
- ret = qcow2_co_preadv_task(bs, ret,
147
- cluster_offset, offset, cur_bytes,
148
- qiov, qiov_offset);
149
+ if (!aio && cur_bytes != bytes) {
150
+ aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
151
+ }
152
+ ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, ret,
153
+ cluster_offset, offset, cur_bytes,
154
+ qiov, qiov_offset, NULL);
155
if (ret < 0) {
156
- return ret;
157
+ goto out;
158
}
159
}
160
161
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
162
qiov_offset += cur_bytes;
163
}
164
165
- return 0;
166
+out:
167
+ if (aio) {
168
+ aio_task_pool_wait_all(aio);
169
+ if (ret == 0) {
170
+ ret = aio_task_pool_status(aio);
171
+ }
172
+ g_free(aio);
173
+ }
174
+
175
+ return ret;
176
}
40
}
177
41
178
/* Check if it's possible to merge a write request with the writing of
42
-static void usb_msd_realize_bot(USBDevice *dev, Error **errp)
179
@@ -XXX,XX +XXX,XX @@ out_locked:
43
+static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
180
return ret;
44
{
45
MSDState *s = USB_STORAGE_DEV(dev);
46
DeviceState *d = DEVICE(dev);
47
@@ -XXX,XX +XXX,XX @@ static void usb_msd_class_initfn_common(ObjectClass *klass, void *data)
48
dc->vmsd = &vmstate_usb_msd;
181
}
49
}
182
50
183
+static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task)
51
-static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data)
184
+{
52
+static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data)
185
+ Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
53
{
186
+
54
DeviceClass *dc = DEVICE_CLASS(klass);
187
+ assert(!t->cluster_type);
55
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
188
+
56
189
+ return qcow2_co_pwritev_task(t->bs, t->file_cluster_offset,
57
- uc->realize = usb_msd_realize_storage;
190
+ t->offset, t->bytes, t->qiov, t->qiov_offset,
58
+ uc->realize = usb_msd_storage_realize;
191
+ t->l2meta);
59
uc->unrealize = usb_msd_unrealize_storage;
192
+}
60
dc->props = msd_properties;
193
+
61
}
194
static coroutine_fn int qcow2_co_pwritev_part(
62
@@ -XXX,XX +XXX,XX @@ static void usb_msd_instance_init(Object *obj)
195
BlockDriverState *bs, uint64_t offset, uint64_t bytes,
63
object_property_set_int(obj, -1, "bootindex", NULL);
196
QEMUIOVector *qiov, size_t qiov_offset, int flags)
64
}
197
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
65
198
unsigned int cur_bytes; /* number of sectors in current iteration */
66
-static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data)
199
uint64_t cluster_offset;
67
+static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data)
200
QCowL2Meta *l2meta = NULL;
68
{
201
+ AioTaskPool *aio = NULL;
69
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
202
70
203
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
71
- uc->realize = usb_msd_realize_bot;
204
72
- uc->unrealize = usb_msd_unrealize_bot;
205
- while (bytes != 0) {
73
+ uc->realize = usb_msd_bot_realize;
206
+ while (bytes != 0 && aio_task_pool_status(aio) == 0) {
74
+ uc->unrealize = usb_msd_bot_unrealize;
207
75
uc->attached_settable = true;
208
l2meta = NULL;
76
}
209
77
210
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
78
static const TypeInfo msd_info = {
211
79
.name = "usb-storage",
212
qemu_co_mutex_unlock(&s->lock);
80
.parent = TYPE_USB_STORAGE,
213
81
- .class_init = usb_msd_class_initfn_storage,
214
- ret = qcow2_co_pwritev_task(bs, cluster_offset, offset, cur_bytes,
82
+ .class_init = usb_msd_class_storage_initfn,
215
- qiov, qiov_offset, l2meta);
83
.instance_init = usb_msd_instance_init,
216
+ if (!aio && cur_bytes != bytes) {
84
};
217
+ aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
85
218
+ }
86
static const TypeInfo bot_info = {
219
+ ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0,
87
.name = "usb-bot",
220
+ cluster_offset, offset, cur_bytes,
88
.parent = TYPE_USB_STORAGE,
221
+ qiov, qiov_offset, l2meta);
89
- .class_init = usb_msd_class_initfn_bot,
222
l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */
90
+ .class_init = usb_msd_class_bot_initfn,
223
if (ret < 0) {
91
};
224
goto fail_nometa;
92
225
@@ -XXX,XX +XXX,XX @@ out_locked:
93
static void usb_msd_register_types(void)
226
qemu_co_mutex_unlock(&s->lock);
227
228
fail_nometa:
229
+ if (aio) {
230
+ aio_task_pool_wait_all(aio);
231
+ if (ret == 0) {
232
+ ret = aio_task_pool_status(aio);
233
+ }
234
+ g_free(aio);
235
+ }
236
+
237
trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);
238
239
return ret;
240
diff --git a/block/trace-events b/block/trace-events
241
index XXXXXXX..XXXXXXX 100644
242
--- a/block/trace-events
243
+++ b/block/trace-events
244
@@ -XXX,XX +XXX,XX @@ file_paio_submit(void *acb, void *opaque, int64_t offset, int count, int type) "
245
file_copy_file_range(void *bs, int src, int64_t src_off, int dst, int64_t dst_off, int64_t bytes, int flags, int64_t ret) "bs %p src_fd %d offset %"PRIu64" dst_fd %d offset %"PRIu64" bytes %"PRIu64" flags %d ret %"PRId64
246
247
# qcow2.c
248
+qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t file_cluster_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu"
249
qcow2_writev_start_req(void *co, int64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d"
250
qcow2_writev_done_req(void *co, int ret) "co %p ret %d"
251
qcow2_writev_start_part(void *co) "co %p"
252
--
94
--
253
2.21.0
95
2.14.3
254
96
255
97
diff view generated by jsdifflib
1
Linux 5.3 has made 0.0.0.0/8 a working IPv4 subnet. As such, "42" is
1
Commit 1351d1ec89eabebc9fdff20451a62c413d7accc1 ("qdev: drop iothread
2
now a valid host, and the connection to it will (hopefully) time out
2
property type") forgot to remove this include.
3
over a long period rather than quickly return with EINVAL.
4
3
5
So let us use a negative integer for testing that NBD will not crash
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
when it receives integer hosts. This way, the connection will again
5
Message-id: 20171205133954.31006-1-stefanha@redhat.com
7
fail quickly and reliably.
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
8
hw/core/qdev-properties-system.c | 1 -
9
1 file changed, 1 deletion(-)
8
10
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
10
Message-id: 20191002174052.5773-1-mreitz@redhat.com
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
tests/qemu-iotests/162 | 2 +-
15
tests/qemu-iotests/162.out | 2 +-
16
2 files changed, 2 insertions(+), 2 deletions(-)
17
18
diff --git a/tests/qemu-iotests/162 b/tests/qemu-iotests/162
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/162
21
+++ b/tests/qemu-iotests/162
22
@@ -XXX,XX +XXX,XX @@ echo '=== NBD ==='
23
# NBD expects all of its arguments to be strings
24
25
# So this should not crash
26
-$QEMU_IMG info 'json:{"driver": "nbd", "host": 42}'
27
+$QEMU_IMG info 'json:{"driver": "nbd", "host": -1}'
28
29
# And this should not treat @port as if it had not been specified
30
# (We need to set up a server here, because the error message for "Connection
31
diff --git a/tests/qemu-iotests/162.out b/tests/qemu-iotests/162.out
32
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/qemu-iotests/162.out
13
--- a/hw/core/qdev-properties-system.c
34
+++ b/tests/qemu-iotests/162.out
14
+++ b/hw/core/qdev-properties-system.c
35
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@
36
QA output created by 162
16
#include "qapi/visitor.h"
37
17
#include "chardev/char-fe.h"
38
=== NBD ===
18
#include "sysemu/tpm_backend.h"
39
-qemu-img: Could not open 'json:{"driver": "nbd", "host": 42}': Failed to connect socket: Invalid argument
19
-#include "sysemu/iothread.h"
40
+qemu-img: Could not open 'json:{"driver": "nbd", "host": -1}': address resolution failed for -1:10809: Name or service not known
20
41
image: nbd://localhost:PORT
21
static void get_pointer(Object *obj, Visitor *v, Property *prop,
42
image: nbd+unix://?socket=42
22
char *(*print)(void *ptr),
43
44
--
23
--
45
2.21.0
24
2.14.3
46
25
47
26
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
bdrv_unref() requires the AioContext lock because bdrv_flush() uses
2
BDRV_POLL_WHILE(), which assumes the AioContext is currently held. If
3
BDRV_POLL_WHILE() runs without AioContext held the
4
pthread_mutex_unlock() call in aio_context_release() fails.
2
5
3
This will help to account the operation in the following commit.
6
This patch moves bdrv_unref() into the AioContext locked region to solve
7
the following pthread_mutex_unlock() failure:
4
8
5
The difference is that we don't call scsi_disk_req_check_error() before
9
#0 0x00007f566181969b in raise () at /lib64/libc.so.6
6
the 1st discard iteration anymore. That function also checks if
10
#1 0x00007f566181b3b1 in abort () at /lib64/libc.so.6
7
the request is cancelled, however it shouldn't get canceled until it
11
#2 0x00005592cd590458 in error_exit (err=<optimized out>, msg=msg@entry=0x5592cdaf6d60 <__func__.23977> "qemu_mutex_unlock") at util/qemu-thread-posix.c:36
8
yields in blk_aio() functions anyway.
12
#3 0x00005592cd96e738 in qemu_mutex_unlock (mutex=mutex@entry=0x5592ce9505e0) at util/qemu-thread-posix.c:96
9
Same approach is already used for emulate_write_same.
13
#4 0x00005592cd969b69 in aio_context_release (ctx=ctx@entry=0x5592ce950580) at util/async.c:507
14
#5 0x00005592cd8ead78 in bdrv_flush (bs=bs@entry=0x5592cfa87210) at block/io.c:2478
15
#6 0x00005592cd89df30 in bdrv_close (bs=0x5592cfa87210) at block.c:3207
16
#7 0x00005592cd89df30 in bdrv_delete (bs=0x5592cfa87210) at block.c:3395
17
#8 0x00005592cd89df30 in bdrv_unref (bs=0x5592cfa87210) at block.c:4418
18
#9 0x00005592cd6b7f86 in qmp_transaction (dev_list=<optimized out>, has_props=<optimized out>, props=<optimized out>, errp=errp@entry=0x7ffe4a1fc9d8) at blockdev.c:2308
10
19
11
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
21
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Alberto Garcia <berto@igalia.com>
22
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Message-id: 20190923121737.83281-7-anton.nefedov@virtuozzo.com
23
Message-id: 20171206144550.22295-2-stefanha@redhat.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
25
---
17
hw/scsi/scsi-disk.c | 10 ++++++----
26
blockdev.c | 2 +-
18
1 file changed, 6 insertions(+), 4 deletions(-)
27
1 file changed, 1 insertion(+), 1 deletion(-)
19
28
20
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
29
diff --git a/blockdev.c b/blockdev.c
21
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/scsi/scsi-disk.c
31
--- a/blockdev.c
23
+++ b/hw/scsi/scsi-disk.c
32
+++ b/blockdev.c
24
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
33
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common)
25
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
34
DO_UPCAST(ExternalSnapshotState, common, common);
26
35
if (state->aio_context) {
27
assert(r->req.aiocb == NULL);
36
bdrv_drained_end(state->old_bs);
28
- if (scsi_disk_req_check_error(r, ret, false)) {
37
- aio_context_release(state->aio_context);
29
- goto done;
38
bdrv_unref(state->new_bs);
30
- }
39
+ aio_context_release(state->aio_context);
31
40
}
32
if (data->count > 0) {
33
r->sector = ldq_be_p(&data->inbuf[0])
34
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete(void *opaque, int ret)
35
r->req.aiocb = NULL;
36
37
aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
38
- scsi_unmap_complete_noio(data, ret);
39
+ if (scsi_disk_req_check_error(r, ret, false)) {
40
+ scsi_req_unref(&r->req);
41
+ g_free(data);
42
+ } else {
43
+ scsi_unmap_complete_noio(data, ret);
44
+ }
45
aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
46
}
41
}
47
42
48
--
43
--
49
2.21.0
44
2.14.3
50
45
51
46
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
It is not necessary to hold AioContext across transactions anymore since
2
2
bdrv_drained_begin/end() is used to keep the nodes quiesced. In fact,
3
Backup-top filter caches write operations and does copy-before-write
3
using the AioContext lock for this purpose was always buggy.
4
operations.
4
5
5
This patch reduces the scope of AioContext locked regions. This is not
6
The driver will be used in backup instead of write-notifiers.
6
just a cleanup but also fixes hangs that occur in BDRV_POLL_WHILE()
7
7
because it is unware of recursive locking and does not release the
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
AioContext the necessary number of times to allow progress to be made.
9
Message-id: 20191001131409.14202-5-vsementsov@virtuozzo.com
9
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Message-id: 20171206144550.22295-3-stefanha@redhat.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
15
---
13
block/Makefile.objs | 1 +
16
blockdev.c | 71 ++++++++++++++++++++++++++++++++++++++++++--------------------
14
block/backup-top.h | 41 +++++++
17
1 file changed, 48 insertions(+), 23 deletions(-)
15
block/backup-top.c | 281 ++++++++++++++++++++++++++++++++++++++++++++
18
16
3 files changed, 323 insertions(+)
19
diff --git a/blockdev.c b/blockdev.c
17
create mode 100644 block/backup-top.h
18
create mode 100644 block/backup-top.c
19
20
diff --git a/block/Makefile.objs b/block/Makefile.objs
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/block/Makefile.objs
21
--- a/blockdev.c
23
+++ b/block/Makefile.objs
22
+++ b/blockdev.c
24
@@ -XXX,XX +XXX,XX @@ block-obj-y += block-copy.o
23
@@ -XXX,XX +XXX,XX @@ typedef struct ExternalSnapshotState {
25
block-obj-y += crypto.o
24
BlkActionState common;
26
25
BlockDriverState *old_bs;
27
block-obj-y += aio_task.o
26
BlockDriverState *new_bs;
28
+block-obj-y += backup-top.o
27
- AioContext *aio_context;
29
28
bool overlay_appended;
30
common-obj-y += stream.o
29
} ExternalSnapshotState;
31
30
32
diff --git a/block/backup-top.h b/block/backup-top.h
31
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
33
new file mode 100644
32
ExternalSnapshotState *state =
34
index XXXXXXX..XXXXXXX
33
DO_UPCAST(ExternalSnapshotState, common, common);
35
--- /dev/null
34
TransactionAction *action = common->action;
36
+++ b/block/backup-top.h
35
+ AioContext *aio_context;
37
@@ -XXX,XX +XXX,XX @@
36
38
+/*
37
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
39
+ * backup-top filter driver
38
* purpose but a different set of parameters */
40
+ *
39
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
41
+ * The driver performs Copy-Before-Write (CBW) operation: it is injected above
40
return;
42
+ * some node, and before each write it copies _old_ data to the target node.
41
}
43
+ *
42
44
+ * Copyright (c) 2018-2019 Virtuozzo International GmbH.
43
- /* Acquire AioContext now so any threads operating on old_bs stop */
45
+ *
44
- state->aio_context = bdrv_get_aio_context(state->old_bs);
46
+ * Author:
45
- aio_context_acquire(state->aio_context);
47
+ * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
46
+ aio_context = bdrv_get_aio_context(state->old_bs);
48
+ *
47
+ aio_context_acquire(aio_context);
49
+ * This program is free software; you can redistribute it and/or modify
48
+
50
+ * it under the terms of the GNU General Public License as published by
49
+ /* Paired with .clean() */
51
+ * the Free Software Foundation; either version 2 of the License, or
50
bdrv_drained_begin(state->old_bs);
52
+ * (at your option) any later version.
51
53
+ *
52
if (!bdrv_is_inserted(state->old_bs)) {
54
+ * This program is distributed in the hope that it will be useful,
53
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
54
- return;
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55
+ goto out;
57
+ * GNU General Public License for more details.
56
}
58
+ *
57
59
+ * You should have received a copy of the GNU General Public License
58
if (bdrv_op_is_blocked(state->old_bs,
60
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
59
BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) {
61
+ */
60
- return;
62
+
61
+ goto out;
63
+#ifndef BACKUP_TOP_H
62
}
64
+#define BACKUP_TOP_H
63
65
+
64
if (!bdrv_is_read_only(state->old_bs)) {
66
+#include "block/block_int.h"
65
if (bdrv_flush(state->old_bs)) {
67
+#include "block/block-copy.h"
66
error_setg(errp, QERR_IO_ERROR);
68
+
67
- return;
69
+BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
68
+ goto out;
70
+ BlockDriverState *target,
69
}
71
+ const char *filter_node_name,
70
}
72
+ uint64_t cluster_size,
71
73
+ BdrvRequestFlags write_flags,
72
if (!bdrv_is_first_non_filter(state->old_bs)) {
74
+ BlockCopyState **bcs,
73
error_setg(errp, QERR_FEATURE_DISABLED, "snapshot");
75
+ Error **errp);
74
- return;
76
+void bdrv_backup_top_drop(BlockDriverState *bs);
75
+ goto out;
77
+
76
}
78
+#endif /* BACKUP_TOP_H */
77
79
diff --git a/block/backup-top.c b/block/backup-top.c
78
if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
80
new file mode 100644
79
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
81
index XXXXXXX..XXXXXXX
80
82
--- /dev/null
81
if (node_name && !snapshot_node_name) {
83
+++ b/block/backup-top.c
82
error_setg(errp, "New snapshot node name missing");
84
@@ -XXX,XX +XXX,XX @@
83
- return;
85
+/*
84
+ goto out;
86
+ * backup-top filter driver
85
}
87
+ *
86
88
+ * The driver performs Copy-Before-Write (CBW) operation: it is injected above
87
if (snapshot_node_name &&
89
+ * some node, and before each write it copies _old_ data to the target node.
88
bdrv_lookup_bs(snapshot_node_name, snapshot_node_name, NULL)) {
90
+ *
89
error_setg(errp, "New snapshot node name already in use");
91
+ * Copyright (c) 2018-2019 Virtuozzo International GmbH.
90
- return;
92
+ *
91
+ goto out;
93
+ * Author:
92
}
94
+ * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
93
95
+ *
94
flags = state->old_bs->open_flags;
96
+ * This program is free software; you can redistribute it and/or modify
95
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
97
+ * it under the terms of the GNU General Public License as published by
96
int64_t size = bdrv_getlength(state->old_bs);
98
+ * the Free Software Foundation; either version 2 of the License, or
97
if (size < 0) {
99
+ * (at your option) any later version.
98
error_setg_errno(errp, -size, "bdrv_getlength failed");
100
+ *
99
- return;
101
+ * This program is distributed in the hope that it will be useful,
100
+ goto out;
102
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
101
}
103
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
102
bdrv_img_create(new_image_file, format,
104
+ * GNU General Public License for more details.
103
state->old_bs->filename,
105
+ *
104
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
106
+ * You should have received a copy of the GNU General Public License
105
NULL, size, flags, false, &local_err);
107
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
106
if (local_err) {
108
+ */
107
error_propagate(errp, local_err);
109
+
108
- return;
110
+#include "qemu/osdep.h"
109
+ goto out;
111
+
110
}
112
+#include "sysemu/block-backend.h"
111
}
113
+#include "qemu/cutils.h"
112
114
+#include "qapi/error.h"
113
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
115
+#include "block/block_int.h"
114
errp);
116
+#include "block/qdict.h"
115
/* We will manually add the backing_hd field to the bs later */
117
+#include "block/block-copy.h"
116
if (!state->new_bs) {
118
+
117
- return;
119
+#include "block/backup-top.h"
118
+ goto out;
120
+
119
}
121
+typedef struct BDRVBackupTopState {
120
122
+ BlockCopyState *bcs;
121
if (bdrv_has_blk(state->new_bs)) {
123
+ BdrvChild *target;
122
error_setg(errp, "The snapshot is already in use");
124
+ bool active;
123
- return;
125
+} BDRVBackupTopState;
124
+ goto out;
126
+
125
}
127
+static coroutine_fn int backup_top_co_preadv(
126
128
+ BlockDriverState *bs, uint64_t offset, uint64_t bytes,
127
if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
129
+ QEMUIOVector *qiov, int flags)
128
errp)) {
130
+{
129
- return;
131
+ return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
130
+ goto out;
132
+}
131
}
133
+
132
134
+static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
133
if (state->new_bs->backing != NULL) {
135
+ uint64_t bytes)
134
error_setg(errp, "The snapshot already has a backing image");
136
+{
135
- return;
137
+ /*
136
+ goto out;
138
+ * Here we'd like to use block_copy(), but block-copy need to be moved to
137
}
139
+ * use BdrvChildren to correctly use it in backup-top filter. It's a TODO.
138
140
+ */
139
if (!state->new_bs->drv->supports_backing) {
141
+
140
error_setg(errp, "The snapshot does not support backing images");
142
+ abort();
141
- return;
143
+}
142
+ goto out;
144
+
143
}
145
+static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
144
146
+ int64_t offset, int bytes)
145
- bdrv_set_aio_context(state->new_bs, state->aio_context);
147
+{
146
+ bdrv_set_aio_context(state->new_bs, aio_context);
148
+ int ret = backup_top_cbw(bs, offset, bytes);
147
149
+ if (ret < 0) {
148
/* This removes our old bs and adds the new bs. This is an operation that
150
+ return ret;
149
* can fail, so we need to do it in .prepare; undoing it for abort is
151
+ }
150
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
152
+
151
bdrv_append(state->new_bs, state->old_bs, &local_err);
153
+ return bdrv_co_pdiscard(bs->backing, offset, bytes);
152
if (local_err) {
154
+}
153
error_propagate(errp, local_err);
155
+
154
- return;
156
+static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs,
155
+ goto out;
157
+ int64_t offset, int bytes, BdrvRequestFlags flags)
156
}
158
+{
157
state->overlay_appended = true;
159
+ int ret = backup_top_cbw(bs, offset, bytes);
158
+
160
+ if (ret < 0) {
159
+out:
161
+ return ret;
160
+ aio_context_release(aio_context);
162
+ }
161
}
163
+
162
164
+ return bdrv_co_pwrite_zeroes(bs->backing, offset, bytes, flags);
163
static void external_snapshot_commit(BlkActionState *common)
165
+}
164
{
166
+
165
ExternalSnapshotState *state =
167
+static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs,
166
DO_UPCAST(ExternalSnapshotState, common, common);
168
+ uint64_t offset,
167
+ AioContext *aio_context;
169
+ uint64_t bytes,
168
+
170
+ QEMUIOVector *qiov, int flags)
169
+ aio_context = bdrv_get_aio_context(state->old_bs);
171
+{
170
+ aio_context_acquire(aio_context);
172
+ if (!(flags & BDRV_REQ_WRITE_UNCHANGED)) {
171
173
+ int ret = backup_top_cbw(bs, offset, bytes);
172
/* We don't need (or want) to use the transactional
174
+ if (ret < 0) {
173
* bdrv_reopen_multiple() across all the entries at once, because we
175
+ return ret;
174
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_commit(BlkActionState *common)
176
+ }
175
bdrv_reopen(state->old_bs, state->old_bs->open_flags & ~BDRV_O_RDWR,
177
+ }
176
NULL);
178
+
177
}
179
+ return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);
178
+
180
+}
179
+ aio_context_release(aio_context);
181
+
180
}
182
+static int coroutine_fn backup_top_co_flush(BlockDriverState *bs)
181
183
+{
182
static void external_snapshot_abort(BlkActionState *common)
184
+ if (!bs->backing) {
183
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common)
185
+ return 0;
184
DO_UPCAST(ExternalSnapshotState, common, common);
186
+ }
185
if (state->new_bs) {
187
+
186
if (state->overlay_appended) {
188
+ return bdrv_co_flush(bs->backing->bs);
187
+ AioContext *aio_context;
189
+}
188
+
190
+
189
+ aio_context = bdrv_get_aio_context(state->old_bs);
191
+static void backup_top_refresh_filename(BlockDriverState *bs)
190
+ aio_context_acquire(aio_context);
192
+{
191
+
193
+ if (bs->backing == NULL) {
192
bdrv_ref(state->old_bs); /* we can't let bdrv_set_backind_hd()
194
+ /*
193
close state->old_bs; we need it */
195
+ * we can be here after failed bdrv_attach_child in
194
bdrv_set_backing_hd(state->new_bs, NULL, &error_abort);
196
+ * bdrv_set_backing_hd
195
bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
197
+ */
196
bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
197
+
198
+ aio_context_release(aio_context);
199
}
200
}
201
}
202
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common)
203
{
204
ExternalSnapshotState *state =
205
DO_UPCAST(ExternalSnapshotState, common, common);
206
- if (state->aio_context) {
207
- bdrv_drained_end(state->old_bs);
208
- bdrv_unref(state->new_bs);
209
- aio_context_release(state->aio_context);
210
+ AioContext *aio_context;
211
+
212
+ if (!state->old_bs) {
198
+ return;
213
+ return;
199
+ }
214
}
200
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
215
+
201
+ bs->backing->bs->filename);
216
+ aio_context = bdrv_get_aio_context(state->old_bs);
202
+}
203
+
204
+static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
205
+ const BdrvChildRole *role,
206
+ BlockReopenQueue *reopen_queue,
207
+ uint64_t perm, uint64_t shared,
208
+ uint64_t *nperm, uint64_t *nshared)
209
+{
210
+ BDRVBackupTopState *s = bs->opaque;
211
+
212
+ if (!s->active) {
213
+ /*
214
+ * The filter node may be in process of bdrv_append(), which firstly do
215
+ * bdrv_set_backing_hd() and then bdrv_replace_node(). This means that
216
+ * we can't unshare BLK_PERM_WRITE during bdrv_append() operation. So,
217
+ * let's require nothing during bdrv_append() and refresh permissions
218
+ * after it (see bdrv_backup_top_append()).
219
+ */
220
+ *nperm = 0;
221
+ *nshared = BLK_PERM_ALL;
222
+ return;
223
+ }
224
+
225
+ if (role == &child_file) {
226
+ /*
227
+ * Target child
228
+ *
229
+ * Share write to target (child_file), to not interfere
230
+ * with guest writes to its disk which may be in target backing chain.
231
+ */
232
+ *nshared = BLK_PERM_ALL;
233
+ *nperm = BLK_PERM_WRITE;
234
+ } else {
235
+ /* Source child */
236
+ bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
237
+ nperm, nshared);
238
+
239
+ if (perm & BLK_PERM_WRITE) {
240
+ *nperm = *nperm | BLK_PERM_CONSISTENT_READ;
241
+ }
242
+ *nshared &= ~BLK_PERM_WRITE;
243
+ }
244
+}
245
+
246
+BlockDriver bdrv_backup_top_filter = {
247
+ .format_name = "backup-top",
248
+ .instance_size = sizeof(BDRVBackupTopState),
249
+
250
+ .bdrv_co_preadv = backup_top_co_preadv,
251
+ .bdrv_co_pwritev = backup_top_co_pwritev,
252
+ .bdrv_co_pwrite_zeroes = backup_top_co_pwrite_zeroes,
253
+ .bdrv_co_pdiscard = backup_top_co_pdiscard,
254
+ .bdrv_co_flush = backup_top_co_flush,
255
+
256
+ .bdrv_co_block_status = bdrv_co_block_status_from_backing,
257
+
258
+ .bdrv_refresh_filename = backup_top_refresh_filename,
259
+
260
+ .bdrv_child_perm = backup_top_child_perm,
261
+
262
+ .is_filter = true,
263
+};
264
+
265
+BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
266
+ BlockDriverState *target,
267
+ const char *filter_node_name,
268
+ uint64_t cluster_size,
269
+ BdrvRequestFlags write_flags,
270
+ BlockCopyState **bcs,
271
+ Error **errp)
272
+{
273
+ Error *local_err = NULL;
274
+ BDRVBackupTopState *state;
275
+ BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter,
276
+ filter_node_name,
277
+ BDRV_O_RDWR, errp);
278
+
279
+ if (!top) {
280
+ return NULL;
281
+ }
282
+
283
+ top->total_sectors = source->total_sectors;
284
+ top->opaque = state = g_new0(BDRVBackupTopState, 1);
285
+
286
+ bdrv_ref(target);
287
+ state->target = bdrv_attach_child(top, target, "target", &child_file, errp);
288
+ if (!state->target) {
289
+ bdrv_unref(target);
290
+ bdrv_unref(top);
291
+ return NULL;
292
+ }
293
+
294
+ bdrv_drained_begin(source);
295
+
296
+ bdrv_ref(top);
297
+ bdrv_append(top, source, &local_err);
298
+ if (local_err) {
299
+ error_prepend(&local_err, "Cannot append backup-top filter: ");
300
+ goto append_failed;
301
+ }
302
+
303
+ /*
304
+ * bdrv_append() finished successfully, now we can require permissions
305
+ * we want.
306
+ */
307
+ state->active = true;
308
+ bdrv_child_refresh_perms(top, top->backing, &local_err);
309
+ if (local_err) {
310
+ error_prepend(&local_err,
311
+ "Cannot set permissions for backup-top filter: ");
312
+ goto failed_after_append;
313
+ }
314
+
315
+ /*
316
+ * TODO: Create block-copy-state here (which will utilize @cluster_size and
317
+ * @write_flags parameters which are unused now). For this, block-copy
318
+ * should be refactored to use BdrvChildren.
319
+ */
320
+ state->bcs = NULL;
321
+ if (!state->bcs) {
322
+ error_setg(&local_err, "Cannot create block-copy-state");
323
+ goto failed_after_append;
324
+ }
325
+ *bcs = state->bcs;
326
+
327
+ bdrv_drained_end(source);
328
+
329
+ return top;
330
+
331
+failed_after_append:
332
+ state->active = false;
333
+ bdrv_backup_top_drop(top);
334
+
335
+append_failed:
336
+ bdrv_drained_end(source);
337
+ bdrv_unref_child(top, state->target);
338
+ bdrv_unref(top);
339
+ error_propagate(errp, local_err);
340
+
341
+ return NULL;
342
+}
343
+
344
+void bdrv_backup_top_drop(BlockDriverState *bs)
345
+{
346
+ BDRVBackupTopState *s = bs->opaque;
347
+ AioContext *aio_context = bdrv_get_aio_context(bs);
348
+
349
+ block_copy_state_free(s->bcs);
350
+
351
+ aio_context_acquire(aio_context);
217
+ aio_context_acquire(aio_context);
352
+
218
+
353
+ bdrv_drained_begin(bs);
219
+ bdrv_drained_end(state->old_bs);
354
+
220
+ bdrv_unref(state->new_bs);
355
+ s->active = false;
356
+ bdrv_child_refresh_perms(bs, bs->backing, &error_abort);
357
+ bdrv_replace_node(bs, backing_bs(bs), &error_abort);
358
+ bdrv_set_backing_hd(bs, NULL, &error_abort);
359
+
360
+ bdrv_drained_end(bs);
361
+
362
+ bdrv_unref(bs);
363
+
221
+
364
+ aio_context_release(aio_context);
222
+ aio_context_release(aio_context);
365
+}
223
}
224
225
typedef struct DriveBackupState {
366
--
226
--
367
2.21.0
227
2.14.3
368
228
369
229
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Message-id: 20171206144550.22295-4-stefanha@redhat.com
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
blockdev.c | 42 ++++++++++++++++++++++++++++++++++--------
8
1 file changed, 34 insertions(+), 8 deletions(-)
2
9
3
Further patch will run partial requests of iterations of
10
diff --git a/blockdev.c b/blockdev.c
4
qcow2_co_preadv in parallel for performance reasons. To prepare for
5
this, separate part which may be parallelized into separate function
6
(qcow2_co_preadv_task).
7
8
While being here, also separate encrypted clusters reading to own
9
function, like it is done for compressed reading.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20190916175324.18478-4-vsementsov@virtuozzo.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2.c | 209 +++++++++++++++++++++++++++-----------------------
17
1 file changed, 113 insertions(+), 96 deletions(-)
18
19
diff --git a/block/qcow2.c b/block/qcow2.c
20
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
12
--- a/blockdev.c
22
+++ b/block/qcow2.c
13
+++ b/blockdev.c
23
@@ -XXX,XX +XXX,XX @@ out:
14
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common)
24
return ret;
15
typedef struct DriveBackupState {
16
BlkActionState common;
17
BlockDriverState *bs;
18
- AioContext *aio_context;
19
BlockJob *job;
20
} DriveBackupState;
21
22
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
23
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
24
BlockDriverState *bs;
25
DriveBackup *backup;
26
+ AioContext *aio_context;
27
Error *local_err = NULL;
28
29
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
30
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
31
return;
32
}
33
34
- /* AioContext is released in .clean() */
35
- state->aio_context = bdrv_get_aio_context(bs);
36
- aio_context_acquire(state->aio_context);
37
+ aio_context = bdrv_get_aio_context(bs);
38
+ aio_context_acquire(aio_context);
39
+
40
+ /* Paired with .clean() */
41
bdrv_drained_begin(bs);
42
+
43
state->bs = bs;
44
45
state->job = do_drive_backup(backup, common->block_job_txn, &local_err);
46
if (local_err) {
47
error_propagate(errp, local_err);
48
- return;
49
+ goto out;
50
}
51
+
52
+out:
53
+ aio_context_release(aio_context);
25
}
54
}
26
55
27
+static coroutine_fn int
56
static void drive_backup_commit(BlkActionState *common)
28
+qcow2_co_preadv_encrypted(BlockDriverState *bs,
57
{
29
+ uint64_t file_cluster_offset,
58
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
30
+ uint64_t offset,
59
+ AioContext *aio_context;
31
+ uint64_t bytes,
32
+ QEMUIOVector *qiov,
33
+ uint64_t qiov_offset)
34
+{
35
+ int ret;
36
+ BDRVQcow2State *s = bs->opaque;
37
+ uint8_t *buf;
38
+
60
+
39
+ assert(bs->encrypted && s->crypto);
61
+ aio_context = bdrv_get_aio_context(state->bs);
40
+ assert(bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
62
+ aio_context_acquire(aio_context);
41
+
63
+
42
+ /*
64
assert(state->job);
43
+ * For encrypted images, read everything into a temporary
65
block_job_start(state->job);
44
+ * contiguous buffer on which the AES functions can work.
45
+ * Also, decryption in a separate buffer is better as it
46
+ * prevents the guest from learning information about the
47
+ * encrypted nature of the virtual disk.
48
+ */
49
+
66
+
50
+ buf = qemu_try_blockalign(s->data_file->bs, bytes);
67
+ aio_context_release(aio_context);
51
+ if (buf == NULL) {
68
}
52
+ return -ENOMEM;
69
53
+ }
70
static void drive_backup_abort(BlkActionState *common)
71
@@ -XXX,XX +XXX,XX @@ static void drive_backup_abort(BlkActionState *common)
72
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
73
74
if (state->job) {
75
+ AioContext *aio_context;
54
+
76
+
55
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
77
+ aio_context = bdrv_get_aio_context(state->bs);
56
+ ret = bdrv_co_pread(s->data_file,
78
+ aio_context_acquire(aio_context);
57
+ file_cluster_offset + offset_into_cluster(s, offset),
58
+ bytes, buf, 0);
59
+ if (ret < 0) {
60
+ goto fail;
61
+ }
62
+
79
+
63
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
80
block_job_cancel_sync(state->job);
64
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
65
+ if (qcow2_co_decrypt(bs,
66
+ file_cluster_offset + offset_into_cluster(s, offset),
67
+ offset, buf, bytes) < 0)
68
+ {
69
+ ret = -EIO;
70
+ goto fail;
71
+ }
72
+ qemu_iovec_from_buf(qiov, qiov_offset, buf, bytes);
73
+
81
+
74
+fail:
82
+ aio_context_release(aio_context);
75
+ qemu_vfree(buf);
83
}
84
}
85
86
static void drive_backup_clean(BlkActionState *common)
87
{
88
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
89
+ AioContext *aio_context;
90
91
- if (state->aio_context) {
92
- bdrv_drained_end(state->bs);
93
- aio_context_release(state->aio_context);
94
+ if (!state->bs) {
95
+ return;
96
}
76
+
97
+
77
+ return ret;
98
+ aio_context = bdrv_get_aio_context(state->bs);
78
+}
99
+ aio_context_acquire(aio_context);
79
+
100
+
80
+static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
101
+ bdrv_drained_end(state->bs);
81
+ QCow2ClusterType cluster_type,
82
+ uint64_t file_cluster_offset,
83
+ uint64_t offset, uint64_t bytes,
84
+ QEMUIOVector *qiov,
85
+ size_t qiov_offset)
86
+{
87
+ BDRVQcow2State *s = bs->opaque;
88
+ int offset_in_cluster = offset_into_cluster(s, offset);
89
+
102
+
90
+ switch (cluster_type) {
103
+ aio_context_release(aio_context);
91
+ case QCOW2_CLUSTER_ZERO_PLAIN:
92
+ case QCOW2_CLUSTER_ZERO_ALLOC:
93
+ /* Both zero types are handled in qcow2_co_preadv_part */
94
+ g_assert_not_reached();
95
+
96
+ case QCOW2_CLUSTER_UNALLOCATED:
97
+ assert(bs->backing); /* otherwise handled in qcow2_co_preadv_part */
98
+
99
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
100
+ return bdrv_co_preadv_part(bs->backing, offset, bytes,
101
+ qiov, qiov_offset, 0);
102
+
103
+ case QCOW2_CLUSTER_COMPRESSED:
104
+ return qcow2_co_preadv_compressed(bs, file_cluster_offset,
105
+ offset, bytes, qiov, qiov_offset);
106
+
107
+ case QCOW2_CLUSTER_NORMAL:
108
+ if ((file_cluster_offset & 511) != 0) {
109
+ return -EIO;
110
+ }
111
+
112
+ if (bs->encrypted) {
113
+ return qcow2_co_preadv_encrypted(bs, file_cluster_offset,
114
+ offset, bytes, qiov, qiov_offset);
115
+ }
116
+
117
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
118
+ return bdrv_co_preadv_part(s->data_file,
119
+ file_cluster_offset + offset_in_cluster,
120
+ bytes, qiov, qiov_offset, 0);
121
+
122
+ default:
123
+ g_assert_not_reached();
124
+ }
125
+
126
+ g_assert_not_reached();
127
+}
128
+
129
static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
130
uint64_t offset, uint64_t bytes,
131
QEMUIOVector *qiov,
132
size_t qiov_offset, int flags)
133
{
134
BDRVQcow2State *s = bs->opaque;
135
- int offset_in_cluster;
136
int ret;
137
unsigned int cur_bytes; /* number of bytes in current iteration */
138
uint64_t cluster_offset = 0;
139
- uint8_t *cluster_data = NULL;
140
141
while (bytes != 0) {
142
143
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
144
ret = qcow2_get_cluster_offset(bs, offset, &cur_bytes, &cluster_offset);
145
qemu_co_mutex_unlock(&s->lock);
146
if (ret < 0) {
147
- goto fail;
148
+ return ret;
149
}
150
151
- offset_in_cluster = offset_into_cluster(s, offset);
152
-
153
- switch (ret) {
154
- case QCOW2_CLUSTER_UNALLOCATED:
155
-
156
- if (bs->backing) {
157
- BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
158
- ret = bdrv_co_preadv_part(bs->backing, offset, cur_bytes,
159
- qiov, qiov_offset, 0);
160
- if (ret < 0) {
161
- goto fail;
162
- }
163
- } else {
164
- /* Note: in this case, no need to wait */
165
- qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
166
- }
167
- break;
168
-
169
- case QCOW2_CLUSTER_ZERO_PLAIN:
170
- case QCOW2_CLUSTER_ZERO_ALLOC:
171
+ if (ret == QCOW2_CLUSTER_ZERO_PLAIN ||
172
+ ret == QCOW2_CLUSTER_ZERO_ALLOC ||
173
+ (ret == QCOW2_CLUSTER_UNALLOCATED && !bs->backing))
174
+ {
175
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
176
- break;
177
-
178
- case QCOW2_CLUSTER_COMPRESSED:
179
- ret = qcow2_co_preadv_compressed(bs, cluster_offset,
180
- offset, cur_bytes,
181
- qiov, qiov_offset);
182
+ } else {
183
+ ret = qcow2_co_preadv_task(bs, ret,
184
+ cluster_offset, offset, cur_bytes,
185
+ qiov, qiov_offset);
186
if (ret < 0) {
187
- goto fail;
188
- }
189
-
190
- break;
191
-
192
- case QCOW2_CLUSTER_NORMAL:
193
- if ((cluster_offset & 511) != 0) {
194
- ret = -EIO;
195
- goto fail;
196
- }
197
-
198
- if (bs->encrypted) {
199
- assert(s->crypto);
200
-
201
- /*
202
- * For encrypted images, read everything into a temporary
203
- * contiguous buffer on which the AES functions can work.
204
- */
205
- if (!cluster_data) {
206
- cluster_data =
207
- qemu_try_blockalign(s->data_file->bs,
208
- QCOW_MAX_CRYPT_CLUSTERS
209
- * s->cluster_size);
210
- if (cluster_data == NULL) {
211
- ret = -ENOMEM;
212
- goto fail;
213
- }
214
- }
215
-
216
- assert(cur_bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
217
-
218
- BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
219
- ret = bdrv_co_pread(s->data_file,
220
- cluster_offset + offset_in_cluster,
221
- cur_bytes, cluster_data, 0);
222
- if (ret < 0) {
223
- goto fail;
224
- }
225
-
226
- assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
227
- assert(QEMU_IS_ALIGNED(cur_bytes, BDRV_SECTOR_SIZE));
228
- if (qcow2_co_decrypt(bs, cluster_offset + offset_in_cluster,
229
- offset,
230
- cluster_data, cur_bytes) < 0) {
231
- ret = -EIO;
232
- goto fail;
233
- }
234
- qemu_iovec_from_buf(qiov, qiov_offset, cluster_data, cur_bytes);
235
- } else {
236
- BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
237
- ret = bdrv_co_preadv_part(s->data_file,
238
- cluster_offset + offset_in_cluster,
239
- cur_bytes, qiov, qiov_offset, 0);
240
- if (ret < 0) {
241
- goto fail;
242
- }
243
+ return ret;
244
}
245
- break;
246
-
247
- default:
248
- g_assert_not_reached();
249
- ret = -EIO;
250
- goto fail;
251
}
252
253
bytes -= cur_bytes;
254
offset += cur_bytes;
255
qiov_offset += cur_bytes;
256
}
257
- ret = 0;
258
-
259
-fail:
260
- qemu_vfree(cluster_data);
261
262
- return ret;
263
+ return 0;
264
}
104
}
265
105
266
/* Check if it's possible to merge a write request with the writing of
106
typedef struct BlockdevBackupState {
267
--
107
--
268
2.21.0
108
2.14.3
269
109
270
110
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Message-id: 20171206144550.22295-5-stefanha@redhat.com
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
blockdev.c | 44 ++++++++++++++++++++++++++++++++++----------
8
1 file changed, 34 insertions(+), 10 deletions(-)
2
9
3
We need to fix comment style around block-copy functions before further
10
diff --git a/blockdev.c b/blockdev.c
4
moving them to separate file to satisfy checkpatch. But do more: fix
5
all comments style. Also, seems like doubled first asterisk is not
6
forbidden, but drop it too for consistency.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 20190920142056.12778-7-vsementsov@virtuozzo.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/backup.c | 32 +++++++++++++++++++++-----------
14
1 file changed, 21 insertions(+), 11 deletions(-)
15
16
diff --git a/block/backup.c b/block/backup.c
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/block/backup.c
12
--- a/blockdev.c
19
+++ b/block/backup.c
13
+++ b/blockdev.c
20
@@ -XXX,XX +XXX,XX @@ fail:
14
@@ -XXX,XX +XXX,XX @@ typedef struct BlockdevBackupState {
21
return NULL;
15
BlkActionState common;
16
BlockDriverState *bs;
17
BlockJob *job;
18
- AioContext *aio_context;
19
} BlockdevBackupState;
20
21
static BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
22
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
23
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
24
BlockdevBackup *backup;
25
BlockDriverState *bs, *target;
26
+ AioContext *aio_context;
27
Error *local_err = NULL;
28
29
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
30
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
31
return;
32
}
33
34
- /* AioContext is released in .clean() */
35
- state->aio_context = bdrv_get_aio_context(bs);
36
- if (state->aio_context != bdrv_get_aio_context(target)) {
37
- state->aio_context = NULL;
38
+ aio_context = bdrv_get_aio_context(bs);
39
+ if (aio_context != bdrv_get_aio_context(target)) {
40
error_setg(errp, "Backup between two IO threads is not implemented");
41
return;
42
}
43
- aio_context_acquire(state->aio_context);
44
+ aio_context_acquire(aio_context);
45
state->bs = bs;
46
+
47
+ /* Paired with .clean() */
48
bdrv_drained_begin(state->bs);
49
50
state->job = do_blockdev_backup(backup, common->block_job_txn, &local_err);
51
if (local_err) {
52
error_propagate(errp, local_err);
53
- return;
54
+ goto out;
55
}
56
+
57
+out:
58
+ aio_context_release(aio_context);
22
}
59
}
23
60
24
-/* Copy range to target with a bounce buffer and return the bytes copied. If
61
static void blockdev_backup_commit(BlkActionState *common)
25
- * error occurred, return a negative error number */
62
{
26
+/*
63
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
27
+ * Copy range to target with a bounce buffer and return the bytes copied. If
64
+ AioContext *aio_context;
28
+ * error occurred, return a negative error number
65
+
29
+ */
66
+ aio_context = bdrv_get_aio_context(state->bs);
30
static int coroutine_fn block_copy_with_bounce_buffer(BlockCopyState *s,
67
+ aio_context_acquire(aio_context);
31
int64_t start,
68
+
32
int64_t end,
69
assert(state->job);
33
@@ -XXX,XX +XXX,XX @@ fail:
70
block_job_start(state->job);
34
71
+
72
+ aio_context_release(aio_context);
35
}
73
}
36
74
37
-/* Copy range to target and return the bytes copied. If error occurred, return a
75
static void blockdev_backup_abort(BlkActionState *common)
38
- * negative error number. */
76
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_abort(BlkActionState *common)
39
+/*
77
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
40
+ * Copy range to target and return the bytes copied. If error occurred, return a
78
41
+ * negative error number.
79
if (state->job) {
42
+ */
80
+ AioContext *aio_context;
43
static int coroutine_fn block_copy_with_offload(BlockCopyState *s,
81
+
44
int64_t start,
82
+ aio_context = bdrv_get_aio_context(state->bs);
45
int64_t end,
83
+ aio_context_acquire(aio_context);
46
@@ -XXX,XX +XXX,XX @@ static int block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
84
+
85
block_job_cancel_sync(state->job);
86
+
87
+ aio_context_release(aio_context);
47
}
88
}
48
}
89
}
49
90
50
-/**
91
static void blockdev_backup_clean(BlkActionState *common)
51
+/*
92
{
52
* Reset bits in copy_bitmap starting at offset if they represent unallocated
93
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
53
* data in the image. May reset subsequent contiguous bits.
94
+ AioContext *aio_context;
54
* @return 0 when the cluster at @offset was unallocated,
95
55
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job)
96
- if (state->aio_context) {
56
return true;
97
- bdrv_drained_end(state->bs);
98
- aio_context_release(state->aio_context);
99
+ if (!state->bs) {
100
+ return;
57
}
101
}
58
102
+
59
- /* We need to yield even for delay_ns = 0 so that bdrv_drain_all() can
103
+ aio_context = bdrv_get_aio_context(state->bs);
60
- * return. Without a yield, the VM would not reboot. */
104
+ aio_context_acquire(aio_context);
61
+ /*
105
+
62
+ * We need to yield even for delay_ns = 0 so that bdrv_drain_all() can
106
+ bdrv_drained_end(state->bs);
63
+ * return. Without a yield, the VM would not reboot.
107
+
64
+ */
108
+ aio_context_release(aio_context);
65
delay_ns = block_job_ratelimit_get_delay(&job->common, job->bytes_read);
109
}
66
job->bytes_read = 0;
110
67
job_sleep_ns(&job->common.job, delay_ns);
111
typedef struct BlockDirtyBitmapState {
68
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
69
}
70
71
if (s->sync_mode == MIRROR_SYNC_MODE_NONE) {
72
- /* All bits are set in copy_bitmap to allow any cluster to be copied.
73
- * This does not actually require them to be copied. */
74
+ /*
75
+ * All bits are set in copy_bitmap to allow any cluster to be copied.
76
+ * This does not actually require them to be copied.
77
+ */
78
while (!job_is_cancelled(job)) {
79
- /* Yield until the job is cancelled. We just let our before_write
80
- * notify callback service CoW requests. */
81
+ /*
82
+ * Yield until the job is cancelled. We just let our before_write
83
+ * notify callback service CoW requests.
84
+ */
85
job_yield(job);
86
}
87
} else {
88
--
112
--
89
2.21.0
113
2.14.3
90
114
91
115
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Message-id: 20171206144550.22295-6-stefanha@redhat.com
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
blockdev.c | 47 +++++++++++++++++++++++++++++++----------------
8
1 file changed, 31 insertions(+), 16 deletions(-)
2
9
3
Split copying code part from backup to "block-copy", including separate
10
diff --git a/blockdev.c b/blockdev.c
4
state structure and function renaming. This is needed to share it with
5
backup-top filter driver in further commits.
6
7
Notes:
8
9
1. As BlockCopyState keeps own BlockBackend objects, remaining
10
job->common.blk users only use it to get bs by blk_bs() call, so clear
11
job->commen.blk permissions set in block_job_create and add
12
job->source_bs to be used instead of blk_bs(job->common.blk), to keep
13
it more clear which bs we use when introduce backup-top filter in
14
further commit.
15
16
2. Rename s/initializing_bitmap/skip_unallocated/ to sound a bit better
17
as interface to BlockCopyState
18
19
3. Split is not very clean: there left some duplicated fields, backup
20
code uses some BlockCopyState fields directly, let's postpone it for
21
further improvements and keep this comment simpler for review.
22
23
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
24
Message-id: 20190920142056.12778-6-vsementsov@virtuozzo.com
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
---
27
block/backup.c | 370 ++++++++++++++++++++++++++++-----------------
28
block/trace-events | 12 +-
29
2 files changed, 239 insertions(+), 143 deletions(-)
30
31
diff --git a/block/backup.c b/block/backup.c
32
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
33
--- a/block/backup.c
12
--- a/blockdev.c
34
+++ b/block/backup.c
13
+++ b/blockdev.c
35
@@ -XXX,XX +XXX,XX @@ typedef struct CowRequest {
14
@@ -XXX,XX +XXX,XX @@ struct BlkActionState {
36
CoQueue wait_queue; /* coroutines blocked on this request */
15
typedef struct InternalSnapshotState {
37
} CowRequest;
16
BlkActionState common;
38
17
BlockDriverState *bs;
39
+typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
18
- AioContext *aio_context;
40
+typedef void (*ProgressResetCallbackFunc)(void *opaque);
19
QEMUSnapshotInfo sn;
41
+typedef struct BlockCopyState {
20
bool created;
42
+ BlockBackend *source;
21
} InternalSnapshotState;
43
+ BlockBackend *target;
22
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
44
+ BdrvDirtyBitmap *copy_bitmap;
23
qemu_timeval tv;
45
+ int64_t cluster_size;
24
BlockdevSnapshotInternal *internal;
46
+ bool use_copy_range;
25
InternalSnapshotState *state;
47
+ int64_t copy_range_size;
26
+ AioContext *aio_context;
48
+ uint64_t len;
27
int ret1;
49
+
28
50
+ BdrvRequestFlags write_flags;
29
g_assert(common->action->type ==
51
+
30
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
52
+ /*
53
+ * skip_unallocated:
54
+ *
55
+ * Used by sync=top jobs, which first scan the source node for unallocated
56
+ * areas and clear them in the copy_bitmap. During this process, the bitmap
57
+ * is thus not fully initialized: It may still have bits set for areas that
58
+ * are unallocated and should actually not be copied.
59
+ *
60
+ * This is indicated by skip_unallocated.
61
+ *
62
+ * In this case, block_copy() will query the source’s allocation status,
63
+ * skip unallocated regions, clear them in the copy_bitmap, and invoke
64
+ * block_copy_reset_unallocated() every time it does.
65
+ */
66
+ bool skip_unallocated;
67
+
68
+ /* progress_bytes_callback: called when some copying progress is done. */
69
+ ProgressBytesCallbackFunc progress_bytes_callback;
70
+
71
+ /*
72
+ * progress_reset_callback: called when some bytes reset from copy_bitmap
73
+ * (see @skip_unallocated above). The callee is assumed to recalculate how
74
+ * many bytes remain based on the dirty bit count of copy_bitmap.
75
+ */
76
+ ProgressResetCallbackFunc progress_reset_callback;
77
+ void *progress_opaque;
78
+} BlockCopyState;
79
+
80
typedef struct BackupBlockJob {
81
BlockJob common;
82
- BlockBackend *target;
83
+ BlockDriverState *source_bs;
84
85
BdrvDirtyBitmap *sync_bitmap;
86
- BdrvDirtyBitmap *copy_bitmap;
87
88
MirrorSyncMode sync_mode;
89
BitmapSyncMode bitmap_mode;
90
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
91
NotifierWithReturn before_write;
92
QLIST_HEAD(, CowRequest) inflight_reqs;
93
94
- bool use_copy_range;
95
- int64_t copy_range_size;
96
-
97
- BdrvRequestFlags write_flags;
98
- bool initializing_bitmap;
99
+ BlockCopyState *bcs;
100
} BackupBlockJob;
101
102
static const BlockJobDriver backup_job_driver;
103
@@ -XXX,XX +XXX,XX @@ static void cow_request_end(CowRequest *req)
104
qemu_co_queue_restart_all(&req->wait_queue);
105
}
106
107
+static void block_copy_state_free(BlockCopyState *s)
108
+{
109
+ if (!s) {
110
+ return;
111
+ }
112
+
113
+ bdrv_release_dirty_bitmap(blk_bs(s->source), s->copy_bitmap);
114
+ blk_unref(s->source);
115
+ blk_unref(s->target);
116
+ g_free(s);
117
+}
118
+
119
+static BlockCopyState *block_copy_state_new(
120
+ BlockDriverState *source, BlockDriverState *target,
121
+ int64_t cluster_size, BdrvRequestFlags write_flags,
122
+ ProgressBytesCallbackFunc progress_bytes_callback,
123
+ ProgressResetCallbackFunc progress_reset_callback,
124
+ void *progress_opaque, Error **errp)
125
+{
126
+ BlockCopyState *s;
127
+ int ret;
128
+ uint64_t no_resize = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
129
+ BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD;
130
+ BdrvDirtyBitmap *copy_bitmap;
131
+
132
+ copy_bitmap = bdrv_create_dirty_bitmap(source, cluster_size, NULL, errp);
133
+ if (!copy_bitmap) {
134
+ return NULL;
135
+ }
136
+ bdrv_disable_dirty_bitmap(copy_bitmap);
137
+
138
+ s = g_new(BlockCopyState, 1);
139
+ *s = (BlockCopyState) {
140
+ .source = blk_new(bdrv_get_aio_context(source),
141
+ BLK_PERM_CONSISTENT_READ, no_resize),
142
+ .target = blk_new(bdrv_get_aio_context(target),
143
+ BLK_PERM_WRITE, no_resize),
144
+ .copy_bitmap = copy_bitmap,
145
+ .cluster_size = cluster_size,
146
+ .len = bdrv_dirty_bitmap_size(copy_bitmap),
147
+ .write_flags = write_flags,
148
+ .progress_bytes_callback = progress_bytes_callback,
149
+ .progress_reset_callback = progress_reset_callback,
150
+ .progress_opaque = progress_opaque,
151
+ };
152
+
153
+ s->copy_range_size = QEMU_ALIGN_DOWN(MIN(blk_get_max_transfer(s->source),
154
+ blk_get_max_transfer(s->target)),
155
+ s->cluster_size);
156
+ /*
157
+ * Set use_copy_range, consider the following:
158
+ * 1. Compression is not supported for copy_range.
159
+ * 2. copy_range does not respect max_transfer (it's a TODO), so we factor
160
+ * that in here. If max_transfer is smaller than the job->cluster_size,
161
+ * we do not use copy_range (in that case it's zero after aligning down
162
+ * above).
163
+ */
164
+ s->use_copy_range =
165
+ !(write_flags & BDRV_REQ_WRITE_COMPRESSED) && s->copy_range_size > 0;
166
+
167
+ /*
168
+ * We just allow aio context change on our block backends. block_copy() user
169
+ * (now it's only backup) is responsible for source and target being in same
170
+ * aio context.
171
+ */
172
+ blk_set_disable_request_queuing(s->source, true);
173
+ blk_set_allow_aio_context_change(s->source, true);
174
+ blk_set_disable_request_queuing(s->target, true);
175
+ blk_set_allow_aio_context_change(s->target, true);
176
+
177
+ ret = blk_insert_bs(s->source, source, errp);
178
+ if (ret < 0) {
179
+ goto fail;
180
+ }
181
+
182
+ ret = blk_insert_bs(s->target, target, errp);
183
+ if (ret < 0) {
184
+ goto fail;
185
+ }
186
+
187
+ return s;
188
+
189
+fail:
190
+ block_copy_state_free(s);
191
+
192
+ return NULL;
193
+}
194
+
195
/* Copy range to target with a bounce buffer and return the bytes copied. If
196
* error occurred, return a negative error number */
197
-static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
198
+static int coroutine_fn block_copy_with_bounce_buffer(BlockCopyState *s,
199
int64_t start,
200
int64_t end,
201
bool is_write_notifier,
202
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
203
void **bounce_buffer)
204
{
205
int ret;
206
- BlockBackend *blk = job->common.blk;
207
int nbytes;
208
int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
209
210
- assert(QEMU_IS_ALIGNED(start, job->cluster_size));
211
- bdrv_reset_dirty_bitmap(job->copy_bitmap, start, job->cluster_size);
212
- nbytes = MIN(job->cluster_size, job->len - start);
213
+ assert(QEMU_IS_ALIGNED(start, s->cluster_size));
214
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, start, s->cluster_size);
215
+ nbytes = MIN(s->cluster_size, s->len - start);
216
if (!*bounce_buffer) {
217
- *bounce_buffer = blk_blockalign(blk, job->cluster_size);
218
+ *bounce_buffer = blk_blockalign(s->source, s->cluster_size);
219
}
220
221
- ret = blk_co_pread(blk, start, nbytes, *bounce_buffer, read_flags);
222
+ ret = blk_co_pread(s->source, start, nbytes, *bounce_buffer, read_flags);
223
if (ret < 0) {
224
- trace_backup_do_cow_read_fail(job, start, ret);
225
+ trace_block_copy_with_bounce_buffer_read_fail(s, start, ret);
226
if (error_is_read) {
227
*error_is_read = true;
228
}
229
goto fail;
230
}
231
232
- ret = blk_co_pwrite(job->target, start, nbytes, *bounce_buffer,
233
- job->write_flags);
234
+ ret = blk_co_pwrite(s->target, start, nbytes, *bounce_buffer,
235
+ s->write_flags);
236
if (ret < 0) {
237
- trace_backup_do_cow_write_fail(job, start, ret);
238
+ trace_block_copy_with_bounce_buffer_write_fail(s, start, ret);
239
if (error_is_read) {
240
*error_is_read = false;
241
}
242
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
243
244
return nbytes;
245
fail:
246
- bdrv_set_dirty_bitmap(job->copy_bitmap, start, job->cluster_size);
247
+ bdrv_set_dirty_bitmap(s->copy_bitmap, start, s->cluster_size);
248
return ret;
249
250
}
251
252
/* Copy range to target and return the bytes copied. If error occurred, return a
253
* negative error number. */
254
-static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job,
255
+static int coroutine_fn block_copy_with_offload(BlockCopyState *s,
256
int64_t start,
257
int64_t end,
258
bool is_write_notifier)
259
{
260
int ret;
261
int nr_clusters;
262
- BlockBackend *blk = job->common.blk;
263
int nbytes;
264
int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
265
266
- assert(QEMU_IS_ALIGNED(job->copy_range_size, job->cluster_size));
267
- assert(QEMU_IS_ALIGNED(start, job->cluster_size));
268
- nbytes = MIN(job->copy_range_size, MIN(end, job->len) - start);
269
- nr_clusters = DIV_ROUND_UP(nbytes, job->cluster_size);
270
- bdrv_reset_dirty_bitmap(job->copy_bitmap, start,
271
- job->cluster_size * nr_clusters);
272
- ret = blk_co_copy_range(blk, start, job->target, start, nbytes,
273
- read_flags, job->write_flags);
274
+ assert(QEMU_IS_ALIGNED(s->copy_range_size, s->cluster_size));
275
+ assert(QEMU_IS_ALIGNED(start, s->cluster_size));
276
+ nbytes = MIN(s->copy_range_size, MIN(end, s->len) - start);
277
+ nr_clusters = DIV_ROUND_UP(nbytes, s->cluster_size);
278
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, start,
279
+ s->cluster_size * nr_clusters);
280
+ ret = blk_co_copy_range(s->source, start, s->target, start, nbytes,
281
+ read_flags, s->write_flags);
282
if (ret < 0) {
283
- trace_backup_do_cow_copy_range_fail(job, start, ret);
284
- bdrv_set_dirty_bitmap(job->copy_bitmap, start,
285
- job->cluster_size * nr_clusters);
286
+ trace_block_copy_with_offload_fail(s, start, ret);
287
+ bdrv_set_dirty_bitmap(s->copy_bitmap, start,
288
+ s->cluster_size * nr_clusters);
289
return ret;
290
}
291
292
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job,
293
* Check if the cluster starting at offset is allocated or not.
294
* return via pnum the number of contiguous clusters sharing this allocation.
295
*/
296
-static int backup_is_cluster_allocated(BackupBlockJob *s, int64_t offset,
297
- int64_t *pnum)
298
+static int block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
299
+ int64_t *pnum)
300
{
301
- BlockDriverState *bs = blk_bs(s->common.blk);
302
+ BlockDriverState *bs = blk_bs(s->source);
303
int64_t count, total_count = 0;
304
int64_t bytes = s->len - offset;
305
int ret;
306
@@ -XXX,XX +XXX,XX @@ static int backup_is_cluster_allocated(BackupBlockJob *s, int64_t offset,
307
* @return 0 when the cluster at @offset was unallocated,
308
* 1 otherwise, and -ret on error.
309
*/
310
-static int64_t backup_bitmap_reset_unallocated(BackupBlockJob *s,
311
- int64_t offset, int64_t *count)
312
+static int64_t block_copy_reset_unallocated(BlockCopyState *s,
313
+ int64_t offset, int64_t *count)
314
{
315
int ret;
316
- int64_t clusters, bytes, estimate;
317
+ int64_t clusters, bytes;
318
319
- ret = backup_is_cluster_allocated(s, offset, &clusters);
320
+ ret = block_copy_is_cluster_allocated(s, offset, &clusters);
321
if (ret < 0) {
322
return ret;
323
}
324
@@ -XXX,XX +XXX,XX @@ static int64_t backup_bitmap_reset_unallocated(BackupBlockJob *s,
325
326
if (!ret) {
327
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
328
- estimate = bdrv_get_dirty_count(s->copy_bitmap);
329
- job_progress_set_remaining(&s->common.job, estimate);
330
+ s->progress_reset_callback(s->progress_opaque);
331
}
332
333
*count = bytes;
334
return ret;
335
}
336
337
-static int coroutine_fn backup_do_copy(BackupBlockJob *job,
338
- int64_t start, uint64_t bytes,
339
- bool *error_is_read,
340
- bool is_write_notifier)
341
+static int coroutine_fn block_copy(BlockCopyState *s,
342
+ int64_t start, uint64_t bytes,
343
+ bool *error_is_read,
344
+ bool is_write_notifier)
345
{
346
int ret = 0;
347
int64_t end = bytes + start; /* bytes */
348
void *bounce_buffer = NULL;
349
int64_t status_bytes;
350
351
- assert(QEMU_IS_ALIGNED(start, job->cluster_size));
352
- assert(QEMU_IS_ALIGNED(end, job->cluster_size));
353
+ /*
354
+ * block_copy() user is responsible for keeping source and target in same
355
+ * aio context
356
+ */
357
+ assert(blk_get_aio_context(s->source) == blk_get_aio_context(s->target));
358
+
359
+ assert(QEMU_IS_ALIGNED(start, s->cluster_size));
360
+ assert(QEMU_IS_ALIGNED(end, s->cluster_size));
361
362
while (start < end) {
363
int64_t dirty_end;
364
365
- if (!bdrv_dirty_bitmap_get(job->copy_bitmap, start)) {
366
- trace_backup_do_cow_skip(job, start);
367
- start += job->cluster_size;
368
+ if (!bdrv_dirty_bitmap_get(s->copy_bitmap, start)) {
369
+ trace_block_copy_skip(s, start);
370
+ start += s->cluster_size;
371
continue; /* already copied */
372
}
373
374
- dirty_end = bdrv_dirty_bitmap_next_zero(job->copy_bitmap, start,
375
+ dirty_end = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, start,
376
(end - start));
377
if (dirty_end < 0) {
378
dirty_end = end;
379
}
380
381
- if (job->initializing_bitmap) {
382
- ret = backup_bitmap_reset_unallocated(job, start, &status_bytes);
383
+ if (s->skip_unallocated) {
384
+ ret = block_copy_reset_unallocated(s, start, &status_bytes);
385
if (ret == 0) {
386
- trace_backup_do_cow_skip_range(job, start, status_bytes);
387
+ trace_block_copy_skip_range(s, start, status_bytes);
388
start += status_bytes;
389
continue;
390
}
391
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_copy(BackupBlockJob *job,
392
dirty_end = MIN(dirty_end, start + status_bytes);
393
}
394
395
- trace_backup_do_cow_process(job, start);
396
+ trace_block_copy_process(s, start);
397
398
- if (job->use_copy_range) {
399
- ret = backup_cow_with_offload(job, start, dirty_end,
400
+ if (s->use_copy_range) {
401
+ ret = block_copy_with_offload(s, start, dirty_end,
402
is_write_notifier);
403
if (ret < 0) {
404
- job->use_copy_range = false;
405
+ s->use_copy_range = false;
406
}
407
}
408
- if (!job->use_copy_range) {
409
- ret = backup_cow_with_bounce_buffer(job, start, dirty_end,
410
+ if (!s->use_copy_range) {
411
+ ret = block_copy_with_bounce_buffer(s, start, dirty_end,
412
is_write_notifier,
413
error_is_read, &bounce_buffer);
414
}
415
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_copy(BackupBlockJob *job,
416
break;
417
}
418
419
- /* Publish progress, guest I/O counts as progress too. Note that the
420
- * offset field is an opaque progress value, it is not a disk offset.
421
- */
422
start += ret;
423
- job->bytes_read += ret;
424
- job_progress_update(&job->common.job, ret);
425
+ s->progress_bytes_callback(ret, s->progress_opaque);
426
ret = 0;
427
}
428
429
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_copy(BackupBlockJob *job,
430
return ret;
431
}
432
433
+static void backup_progress_bytes_callback(int64_t bytes, void *opaque)
434
+{
435
+ BackupBlockJob *s = opaque;
436
+
437
+ s->bytes_read += bytes;
438
+ job_progress_update(&s->common.job, bytes);
439
+}
440
+
441
+static void backup_progress_reset_callback(void *opaque)
442
+{
443
+ BackupBlockJob *s = opaque;
444
+ uint64_t estimate = bdrv_get_dirty_count(s->bcs->copy_bitmap);
445
+
446
+ job_progress_set_remaining(&s->common.job, estimate);
447
+}
448
+
449
static int coroutine_fn backup_do_cow(BackupBlockJob *job,
450
int64_t offset, uint64_t bytes,
451
bool *error_is_read,
452
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
453
wait_for_overlapping_requests(job, start, end);
454
cow_request_begin(&cow_request, job, start, end);
455
456
- ret = backup_do_copy(job, start, end - start, error_is_read,
457
- is_write_notifier);
458
+ ret = block_copy(job->bcs, start, end - start, error_is_read,
459
+ is_write_notifier);
460
461
cow_request_end(&cow_request);
462
463
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_before_write_notify(
464
BackupBlockJob *job = container_of(notifier, BackupBlockJob, before_write);
465
BdrvTrackedRequest *req = opaque;
466
467
- assert(req->bs == blk_bs(job->common.blk));
468
+ assert(req->bs == job->source_bs);
469
assert(QEMU_IS_ALIGNED(req->offset, BDRV_SECTOR_SIZE));
470
assert(QEMU_IS_ALIGNED(req->bytes, BDRV_SECTOR_SIZE));
471
472
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_before_write_notify(
473
static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
474
{
475
BdrvDirtyBitmap *bm;
476
- BlockDriverState *bs = blk_bs(job->common.blk);
477
bool sync = (((ret == 0) || (job->bitmap_mode == BITMAP_SYNC_MODE_ALWAYS)) \
478
&& (job->bitmap_mode != BITMAP_SYNC_MODE_NEVER));
479
480
@@ -XXX,XX +XXX,XX @@ static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
481
* We succeeded, or we always intended to sync the bitmap.
482
* Delete this bitmap and install the child.
483
*/
484
- bm = bdrv_dirty_bitmap_abdicate(bs, job->sync_bitmap, NULL);
485
+ bm = bdrv_dirty_bitmap_abdicate(job->source_bs, job->sync_bitmap, NULL);
486
} else {
487
/*
488
* We failed, or we never intended to sync the bitmap anyway.
489
* Merge the successor back into the parent, keeping all data.
490
*/
491
- bm = bdrv_reclaim_dirty_bitmap(bs, job->sync_bitmap, NULL);
492
+ bm = bdrv_reclaim_dirty_bitmap(job->source_bs, job->sync_bitmap, NULL);
493
}
494
495
assert(bm);
496
497
if (ret < 0 && job->bitmap_mode == BITMAP_SYNC_MODE_ALWAYS) {
498
/* If we failed and synced, merge in the bits we didn't copy: */
499
- bdrv_dirty_bitmap_merge_internal(bm, job->copy_bitmap,
500
+ bdrv_dirty_bitmap_merge_internal(bm, job->bcs->copy_bitmap,
501
NULL, true);
502
}
503
}
504
@@ -XXX,XX +XXX,XX @@ static void backup_abort(Job *job)
505
static void backup_clean(Job *job)
506
{
507
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
508
- BlockDriverState *bs = blk_bs(s->common.blk);
509
510
- if (s->copy_bitmap) {
511
- bdrv_release_dirty_bitmap(bs, s->copy_bitmap);
512
- s->copy_bitmap = NULL;
513
- }
514
-
515
- assert(s->target);
516
- blk_unref(s->target);
517
- s->target = NULL;
518
+ block_copy_state_free(s->bcs);
519
}
520
521
void backup_do_checkpoint(BlockJob *job, Error **errp)
522
@@ -XXX,XX +XXX,XX @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
523
return;
31
return;
524
}
32
}
525
33
526
- bdrv_set_dirty_bitmap(backup_job->copy_bitmap, 0, backup_job->len);
34
- /* AioContext is released in .clean() */
527
+ bdrv_set_dirty_bitmap(backup_job->bcs->copy_bitmap, 0, backup_job->len);
35
- state->aio_context = bdrv_get_aio_context(bs);
36
- aio_context_acquire(state->aio_context);
37
+ aio_context = bdrv_get_aio_context(bs);
38
+ aio_context_acquire(aio_context);
39
40
state->bs = bs;
41
+
42
+ /* Paired with .clean() */
43
bdrv_drained_begin(bs);
44
45
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, errp)) {
46
- return;
47
+ goto out;
48
}
49
50
if (bdrv_is_read_only(bs)) {
51
error_setg(errp, "Device '%s' is read only", device);
52
- return;
53
+ goto out;
54
}
55
56
if (!bdrv_can_snapshot(bs)) {
57
error_setg(errp, "Block format '%s' used by device '%s' "
58
"does not support internal snapshots",
59
bs->drv->format_name, device);
60
- return;
61
+ goto out;
62
}
63
64
if (!strlen(name)) {
65
error_setg(errp, "Name is empty");
66
- return;
67
+ goto out;
68
}
69
70
/* check whether a snapshot with name exist */
71
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
72
&local_err);
73
if (local_err) {
74
error_propagate(errp, local_err);
75
- return;
76
+ goto out;
77
} else if (ret) {
78
error_setg(errp,
79
"Snapshot with name '%s' already exists on device '%s'",
80
name, device);
81
- return;
82
+ goto out;
83
}
84
85
/* 3. take the snapshot */
86
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
87
error_setg_errno(errp, -ret1,
88
"Failed to create snapshot '%s' on device '%s'",
89
name, device);
90
- return;
91
+ goto out;
92
}
93
94
/* 4. succeed, mark a snapshot is created */
95
state->created = true;
96
+
97
+out:
98
+ aio_context_release(aio_context);
528
}
99
}
529
100
530
static BlockErrorAction backup_error_action(BackupBlockJob *job,
101
static void internal_snapshot_abort(BlkActionState *common)
531
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_loop(BackupBlockJob *job)
102
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(BlkActionState *common)
532
BdrvDirtyBitmapIter *bdbi;
103
DO_UPCAST(InternalSnapshotState, common, common);
533
int ret = 0;
104
BlockDriverState *bs = state->bs;
534
105
QEMUSnapshotInfo *sn = &state->sn;
535
- bdbi = bdrv_dirty_iter_new(job->copy_bitmap);
106
+ AioContext *aio_context;
536
+ bdbi = bdrv_dirty_iter_new(job->bcs->copy_bitmap);
107
Error *local_error = NULL;
537
while ((offset = bdrv_dirty_iter_next(bdbi)) != -1) {
108
538
do {
109
if (!state->created) {
539
if (yield_and_check(job)) {
110
return;
540
@@ -XXX,XX +XXX,XX @@ static void backup_init_copy_bitmap(BackupBlockJob *job)
541
uint64_t estimate;
542
543
if (job->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
544
- ret = bdrv_dirty_bitmap_merge_internal(job->copy_bitmap,
545
+ ret = bdrv_dirty_bitmap_merge_internal(job->bcs->copy_bitmap,
546
job->sync_bitmap,
547
NULL, true);
548
assert(ret);
549
@@ -XXX,XX +XXX,XX @@ static void backup_init_copy_bitmap(BackupBlockJob *job)
550
* We can't hog the coroutine to initialize this thoroughly.
551
* Set a flag and resume work when we are able to yield safely.
552
*/
553
- job->initializing_bitmap = true;
554
+ job->bcs->skip_unallocated = true;
555
}
556
- bdrv_set_dirty_bitmap(job->copy_bitmap, 0, job->len);
557
+ bdrv_set_dirty_bitmap(job->bcs->copy_bitmap, 0, job->len);
558
}
111
}
559
112
560
- estimate = bdrv_get_dirty_count(job->copy_bitmap);
113
+ aio_context = bdrv_get_aio_context(state->bs);
561
+ estimate = bdrv_get_dirty_count(job->bcs->copy_bitmap);
114
+ aio_context_acquire(aio_context);
562
job_progress_set_remaining(&job->common.job, estimate);
115
+
116
if (bdrv_snapshot_delete(bs, sn->id_str, sn->name, &local_error) < 0) {
117
error_reportf_err(local_error,
118
"Failed to delete snapshot with id '%s' and "
119
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(BlkActionState *common)
120
sn->id_str, sn->name,
121
bdrv_get_device_name(bs));
122
}
123
+
124
+ aio_context_release(aio_context);
563
}
125
}
564
126
565
static int coroutine_fn backup_run(Job *job, Error **errp)
127
static void internal_snapshot_clean(BlkActionState *common)
566
{
128
{
567
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
129
InternalSnapshotState *state = DO_UPCAST(InternalSnapshotState,
568
- BlockDriverState *bs = blk_bs(s->common.blk);
130
common, common);
569
int ret = 0;
131
+ AioContext *aio_context;
570
132
571
QLIST_INIT(&s->inflight_reqs);
133
- if (state->aio_context) {
572
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
134
- if (state->bs) {
573
backup_init_copy_bitmap(s);
135
- bdrv_drained_end(state->bs);
574
136
- }
575
s->before_write.notify = backup_before_write_notify;
137
- aio_context_release(state->aio_context);
576
- bdrv_add_before_write_notifier(bs, &s->before_write);
138
+ if (!state->bs) {
577
+ bdrv_add_before_write_notifier(s->source_bs, &s->before_write);
139
+ return;
578
579
if (s->sync_mode == MIRROR_SYNC_MODE_TOP) {
580
int64_t offset = 0;
581
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
582
goto out;
583
}
584
585
- ret = backup_bitmap_reset_unallocated(s, offset, &count);
586
+ ret = block_copy_reset_unallocated(s->bcs, offset, &count);
587
if (ret < 0) {
588
goto out;
589
}
590
591
offset += count;
592
}
593
- s->initializing_bitmap = false;
594
+ s->bcs->skip_unallocated = false;
595
}
140
}
596
597
if (s->sync_mode == MIRROR_SYNC_MODE_NONE) {
598
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
599
{
600
int64_t len;
601
BackupBlockJob *job = NULL;
602
- int ret;
603
int64_t cluster_size;
604
- BdrvDirtyBitmap *copy_bitmap = NULL;
605
+ BdrvRequestFlags write_flags;
606
607
assert(bs);
608
assert(target);
609
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
610
goto error;
611
}
612
613
- copy_bitmap = bdrv_create_dirty_bitmap(bs, cluster_size, NULL, errp);
614
- if (!copy_bitmap) {
615
- goto error;
616
- }
617
- bdrv_disable_dirty_bitmap(copy_bitmap);
618
-
619
/* job->len is fixed, so we can't allow resize */
620
- job = block_job_create(job_id, &backup_job_driver, txn, bs,
621
- BLK_PERM_CONSISTENT_READ,
622
- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
623
- BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD,
624
+ job = block_job_create(job_id, &backup_job_driver, txn, bs, 0, BLK_PERM_ALL,
625
speed, creation_flags, cb, opaque, errp);
626
if (!job) {
627
goto error;
628
}
629
630
- /* The target must match the source in size, so no resize here either */
631
- job->target = blk_new(job->common.job.aio_context,
632
- BLK_PERM_WRITE,
633
- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
634
- BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD);
635
- ret = blk_insert_bs(job->target, target, errp);
636
- if (ret < 0) {
637
- goto error;
638
- }
639
- blk_set_disable_request_queuing(job->target, true);
640
-
641
+ job->source_bs = bs;
642
job->on_source_error = on_source_error;
643
job->on_target_error = on_target_error;
644
job->sync_mode = sync_mode;
645
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
646
* For more information see commit f8d59dfb40bb and test
647
* tests/qemu-iotests/222
648
*/
649
- job->write_flags =
650
- (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
651
- (compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
652
+ write_flags = (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
653
+ (compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
654
+
141
+
655
+ job->bcs = block_copy_state_new(bs, target, cluster_size, write_flags,
142
+ aio_context = bdrv_get_aio_context(state->bs);
656
+ backup_progress_bytes_callback,
143
+ aio_context_acquire(aio_context);
657
+ backup_progress_reset_callback, job, errp);
144
+
658
+ if (!job->bcs) {
145
+ bdrv_drained_end(state->bs);
659
+ goto error;
146
+
660
+ }
147
+ aio_context_release(aio_context);
661
148
}
662
job->cluster_size = cluster_size;
149
663
- job->copy_bitmap = copy_bitmap;
150
/* external snapshot private data */
664
- copy_bitmap = NULL;
665
- job->copy_range_size = MIN_NON_ZERO(blk_get_max_transfer(job->common.blk),
666
- blk_get_max_transfer(job->target));
667
- job->copy_range_size = QEMU_ALIGN_DOWN(job->copy_range_size,
668
- job->cluster_size);
669
- /*
670
- * Set use_copy_range, consider the following:
671
- * 1. Compression is not supported for copy_range.
672
- * 2. copy_range does not respect max_transfer (it's a TODO), so we factor
673
- * that in here. If max_transfer is smaller than the job->cluster_size,
674
- * we do not use copy_range (in that case it's zero after aligning down
675
- * above).
676
- */
677
- job->use_copy_range = !compress && job->copy_range_size > 0;
678
679
- /* Required permissions are already taken with target's blk_new() */
680
+ /* Required permissions are already taken by block-copy-state target */
681
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
682
&error_abort);
683
job->len = len;
684
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
685
return &job->common;
686
687
error:
688
- if (copy_bitmap) {
689
- assert(!job || !job->copy_bitmap);
690
- bdrv_release_dirty_bitmap(bs, copy_bitmap);
691
- }
692
if (sync_bitmap) {
693
bdrv_reclaim_dirty_bitmap(bs, sync_bitmap, NULL);
694
}
695
diff --git a/block/trace-events b/block/trace-events
696
index XXXXXXX..XXXXXXX 100644
697
--- a/block/trace-events
698
+++ b/block/trace-events
699
@@ -XXX,XX +XXX,XX @@ mirror_yield_in_flight(void *s, int64_t offset, int in_flight) "s %p offset %" P
700
# backup.c
701
backup_do_cow_enter(void *job, int64_t start, int64_t offset, uint64_t bytes) "job %p start %" PRId64 " offset %" PRId64 " bytes %" PRIu64
702
backup_do_cow_return(void *job, int64_t offset, uint64_t bytes, int ret) "job %p offset %" PRId64 " bytes %" PRIu64 " ret %d"
703
-backup_do_cow_skip(void *job, int64_t start) "job %p start %"PRId64
704
-backup_do_cow_skip_range(void *job, int64_t start, uint64_t bytes) "job %p start %"PRId64" bytes %"PRId64
705
-backup_do_cow_process(void *job, int64_t start) "job %p start %"PRId64
706
-backup_do_cow_read_fail(void *job, int64_t start, int ret) "job %p start %"PRId64" ret %d"
707
-backup_do_cow_write_fail(void *job, int64_t start, int ret) "job %p start %"PRId64" ret %d"
708
-backup_do_cow_copy_range_fail(void *job, int64_t start, int ret) "job %p start %"PRId64" ret %d"
709
+block_copy_skip(void *bcs, int64_t start) "bcs %p start %"PRId64
710
+block_copy_skip_range(void *bcs, int64_t start, uint64_t bytes) "bcs %p start %"PRId64" bytes %"PRId64
711
+block_copy_process(void *bcs, int64_t start) "bcs %p start %"PRId64
712
+block_copy_with_bounce_buffer_read_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d"
713
+block_copy_with_bounce_buffer_write_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d"
714
+block_copy_with_offload_fail(void *bcs, int64_t start, int ret) "bcs %p start %"PRId64" ret %d"
715
716
# ../blockdev.c
717
qmp_block_job_cancel(void *job) "job %p"
718
--
151
--
719
2.21.0
152
2.14.3
720
153
721
154
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The dirty bitmap actions in qmp_transaction have not used AioContext
2
since the dirty bitmap locking discipline was introduced in commit
3
2119882c7eb7e2c612b24fc0c8d86f5887d6f1c3 ("block: introduce
4
dirty_bitmap_mutex"). Remove the unused field.
2
5
3
Drop write notifiers and use filter node instead.
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Message-id: 20171206144550.22295-7-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
blockdev.c | 13 -------------
13
1 file changed, 13 deletions(-)
4
14
5
= Changes =
6
7
1. Add filter-node-name argument for backup qmp api. We have to do it
8
in this commit, as 257 needs to be fixed.
9
10
2. There are no more write notifiers here, so is_write_notifier
11
parameter is dropped from block-copy paths.
12
13
3. To sync with in-flight requests at job finish we now have drained
14
removing of the filter, we don't need rw-lock.
15
16
4. Block-copy is now using BdrvChildren instead of BlockBackends
17
18
5. As backup-top owns these children, we also move block-copy state
19
into backup-top's ownership.
20
21
= Iotest changes =
22
23
56: op-blocker doesn't shoot now, as we set it on source, but then
24
check on filter, when trying to start second backup.
25
To keep the test we instead can catch another collision: both jobs will
26
get 'drive0' job-id, as job-id parameter is unspecified. To prevent
27
interleaving with file-posix locks (as they are dependent on config)
28
let's use another target for second backup.
29
30
Also, it's obvious now that we'd like to drop this op-blocker at all
31
and add a test-case for two backups from one node (to different
32
destinations) actually works. But not in these series.
33
34
141: Output changed: prepatch, "Node is in use" comes from bdrv_has_blk
35
check inside qmp_blockdev_del. But we've dropped block-copy blk
36
objects, so no more blk objects on source bs (job blk is on backup-top
37
filter bs). New message is from op-blocker, which is the next check in
38
qmp_blockdev_add.
39
40
257: The test wants to emulate guest write during backup. They should
41
go to filter node, not to original source node, of course. Therefore we
42
need to specify filter node name and use it.
43
44
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
45
Message-id: 20191001131409.14202-6-vsementsov@virtuozzo.com
46
Reviewed-by: Max Reitz <mreitz@redhat.com>
47
Signed-off-by: Max Reitz <mreitz@redhat.com>
48
---
49
qapi/block-core.json | 8 +-
50
include/block/block-copy.h | 14 +-
51
include/block/block_int.h | 1 +
52
block/backup-top.c | 21 +--
53
block/backup.c | 73 +++------
54
block/block-copy.c | 81 +++-------
55
block/replication.c | 2 +-
56
blockdev.c | 1 +
57
tests/qemu-iotests/056 | 8 +-
58
tests/qemu-iotests/141.out | 2 +-
59
tests/qemu-iotests/257 | 7 +-
60
tests/qemu-iotests/257.out | 306 ++++++++++++++++++-------------------
61
12 files changed, 237 insertions(+), 287 deletions(-)
62
63
diff --git a/qapi/block-core.json b/qapi/block-core.json
64
index XXXXXXX..XXXXXXX 100644
65
--- a/qapi/block-core.json
66
+++ b/qapi/block-core.json
67
@@ -XXX,XX +XXX,XX @@
68
# list without user intervention.
69
# Defaults to true. (Since 2.12)
70
#
71
+# @filter-node-name: the node name that should be assigned to the
72
+# filter driver that the backup job inserts into the graph
73
+# above node specified by @drive. If this option is not given,
74
+# a node name is autogenerated. (Since: 4.2)
75
+#
76
# Note: @on-source-error and @on-target-error only affect background
77
# I/O. If an error occurs during a guest write request, the device's
78
# rerror/werror actions will be used.
79
@@ -XXX,XX +XXX,XX @@
80
'*compress': 'bool',
81
'*on-source-error': 'BlockdevOnError',
82
'*on-target-error': 'BlockdevOnError',
83
- '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
84
+ '*auto-finalize': 'bool', '*auto-dismiss': 'bool',
85
+ '*filter-node-name': 'str' } }
86
87
##
88
# @DriveBackup:
89
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
90
index XXXXXXX..XXXXXXX 100644
91
--- a/include/block/block-copy.h
92
+++ b/include/block/block-copy.h
93
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyInFlightReq {
94
typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
95
typedef void (*ProgressResetCallbackFunc)(void *opaque);
96
typedef struct BlockCopyState {
97
- BlockBackend *source;
98
- BlockBackend *target;
99
+ /*
100
+ * BdrvChild objects are not owned or managed by block-copy. They are
101
+ * provided by block-copy user and user is responsible for appropriate
102
+ * permissions on these children.
103
+ */
104
+ BdrvChild *source;
105
+ BdrvChild *target;
106
BdrvDirtyBitmap *copy_bitmap;
107
int64_t cluster_size;
108
bool use_copy_range;
109
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
110
void *progress_opaque;
111
} BlockCopyState;
112
113
-BlockCopyState *block_copy_state_new(BlockDriverState *source,
114
- BlockDriverState *target,
115
+BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
116
int64_t cluster_size,
117
BdrvRequestFlags write_flags,
118
Error **errp);
119
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
120
int64_t offset, int64_t *count);
121
122
int coroutine_fn block_copy(BlockCopyState *s, int64_t start, uint64_t bytes,
123
- bool *error_is_read, bool is_write_notifier);
124
+ bool *error_is_read);
125
126
#endif /* BLOCK_COPY_H */
127
diff --git a/include/block/block_int.h b/include/block/block_int.h
128
index XXXXXXX..XXXXXXX 100644
129
--- a/include/block/block_int.h
130
+++ b/include/block/block_int.h
131
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
132
BdrvDirtyBitmap *sync_bitmap,
133
BitmapSyncMode bitmap_mode,
134
bool compress,
135
+ const char *filter_node_name,
136
BlockdevOnError on_source_error,
137
BlockdevOnError on_target_error,
138
int creation_flags,
139
diff --git a/block/backup-top.c b/block/backup-top.c
140
index XXXXXXX..XXXXXXX 100644
141
--- a/block/backup-top.c
142
+++ b/block/backup-top.c
143
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_co_preadv(
144
static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
145
uint64_t bytes)
146
{
147
- /*
148
- * Here we'd like to use block_copy(), but block-copy need to be moved to
149
- * use BdrvChildren to correctly use it in backup-top filter. It's a TODO.
150
- */
151
+ BDRVBackupTopState *s = bs->opaque;
152
+ uint64_t end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size);
153
+ uint64_t off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size);
154
155
- abort();
156
+ return block_copy(s->bcs, off, end - off, NULL);
157
}
158
159
static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
160
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
161
goto failed_after_append;
162
}
163
164
- /*
165
- * TODO: Create block-copy-state here (which will utilize @cluster_size and
166
- * @write_flags parameters which are unused now). For this, block-copy
167
- * should be refactored to use BdrvChildren.
168
- */
169
- state->bcs = NULL;
170
- if (!state->bcs) {
171
- error_setg(&local_err, "Cannot create block-copy-state");
172
+ state->bcs = block_copy_state_new(top->backing, state->target,
173
+ cluster_size, write_flags, &local_err);
174
+ if (local_err) {
175
+ error_prepend(&local_err, "Cannot create block-copy-state: ");
176
goto failed_after_append;
177
}
178
*bcs = state->bcs;
179
diff --git a/block/backup.c b/block/backup.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/block/backup.c
182
+++ b/block/backup.c
183
@@ -XXX,XX +XXX,XX @@
184
* QEMU backup
185
*
186
* Copyright (C) 2013 Proxmox Server Solutions
187
+ * Copyright (c) 2019 Virtuozzo International GmbH.
188
*
189
* Authors:
190
* Dietmar Maurer (dietmar@proxmox.com)
191
@@ -XXX,XX +XXX,XX @@
192
#include "qemu/bitmap.h"
193
#include "qemu/error-report.h"
194
195
+#include "block/backup-top.h"
196
+
197
#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
198
199
typedef struct BackupBlockJob {
200
BlockJob common;
201
+ BlockDriverState *backup_top;
202
BlockDriverState *source_bs;
203
204
BdrvDirtyBitmap *sync_bitmap;
205
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
206
BitmapSyncMode bitmap_mode;
207
BlockdevOnError on_source_error;
208
BlockdevOnError on_target_error;
209
- CoRwlock flush_rwlock;
210
uint64_t len;
211
uint64_t bytes_read;
212
int64_t cluster_size;
213
- NotifierWithReturn before_write;
214
215
BlockCopyState *bcs;
216
} BackupBlockJob;
217
@@ -XXX,XX +XXX,XX @@ static void backup_progress_reset_callback(void *opaque)
218
219
static int coroutine_fn backup_do_cow(BackupBlockJob *job,
220
int64_t offset, uint64_t bytes,
221
- bool *error_is_read,
222
- bool is_write_notifier)
223
+ bool *error_is_read)
224
{
225
int ret = 0;
226
int64_t start, end; /* bytes */
227
228
- qemu_co_rwlock_rdlock(&job->flush_rwlock);
229
-
230
start = QEMU_ALIGN_DOWN(offset, job->cluster_size);
231
end = QEMU_ALIGN_UP(bytes + offset, job->cluster_size);
232
233
trace_backup_do_cow_enter(job, start, offset, bytes);
234
235
- ret = block_copy(job->bcs, start, end - start, error_is_read,
236
- is_write_notifier);
237
+ ret = block_copy(job->bcs, start, end - start, error_is_read);
238
239
trace_backup_do_cow_return(job, offset, bytes, ret);
240
241
- qemu_co_rwlock_unlock(&job->flush_rwlock);
242
-
243
return ret;
244
}
245
246
-static int coroutine_fn backup_before_write_notify(
247
- NotifierWithReturn *notifier,
248
- void *opaque)
249
-{
250
- BackupBlockJob *job = container_of(notifier, BackupBlockJob, before_write);
251
- BdrvTrackedRequest *req = opaque;
252
-
253
- assert(req->bs == job->source_bs);
254
- assert(QEMU_IS_ALIGNED(req->offset, BDRV_SECTOR_SIZE));
255
- assert(QEMU_IS_ALIGNED(req->bytes, BDRV_SECTOR_SIZE));
256
-
257
- return backup_do_cow(job, req->offset, req->bytes, NULL, true);
258
-}
259
-
260
static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
261
{
262
BdrvDirtyBitmap *bm;
263
@@ -XXX,XX +XXX,XX @@ static void backup_clean(Job *job)
264
{
265
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
266
267
- block_copy_state_free(s->bcs);
268
+ bdrv_backup_top_drop(s->backup_top);
269
}
270
271
void backup_do_checkpoint(BlockJob *job, Error **errp)
272
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_loop(BackupBlockJob *job)
273
if (yield_and_check(job)) {
274
goto out;
275
}
276
- ret = backup_do_cow(job, offset,
277
- job->cluster_size, &error_is_read, false);
278
+ ret = backup_do_cow(job, offset, job->cluster_size, &error_is_read);
279
if (ret < 0 && backup_error_action(job, error_is_read, -ret) ==
280
BLOCK_ERROR_ACTION_REPORT)
281
{
282
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
283
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
284
int ret = 0;
285
286
- qemu_co_rwlock_init(&s->flush_rwlock);
287
-
288
backup_init_copy_bitmap(s);
289
290
- s->before_write.notify = backup_before_write_notify;
291
- bdrv_add_before_write_notifier(s->source_bs, &s->before_write);
292
-
293
if (s->sync_mode == MIRROR_SYNC_MODE_TOP) {
294
int64_t offset = 0;
295
int64_t count;
296
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
297
}
298
299
out:
300
- notifier_with_return_remove(&s->before_write);
301
-
302
- /* wait until pending backup_do_cow() calls have completed */
303
- qemu_co_rwlock_wrlock(&s->flush_rwlock);
304
- qemu_co_rwlock_unlock(&s->flush_rwlock);
305
-
306
return ret;
307
}
308
309
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
310
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
311
BitmapSyncMode bitmap_mode,
312
bool compress,
313
+ const char *filter_node_name,
314
BlockdevOnError on_source_error,
315
BlockdevOnError on_target_error,
316
int creation_flags,
317
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
318
BackupBlockJob *job = NULL;
319
int64_t cluster_size;
320
BdrvRequestFlags write_flags;
321
+ BlockDriverState *backup_top = NULL;
322
+ BlockCopyState *bcs = NULL;
323
324
assert(bs);
325
assert(target);
326
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
327
write_flags = (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
328
(compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
329
330
+ backup_top = bdrv_backup_top_append(bs, target, filter_node_name,
331
+ cluster_size, write_flags, &bcs, errp);
332
+ if (!backup_top) {
333
+ goto error;
334
+ }
335
+
336
/* job->len is fixed, so we can't allow resize */
337
- job = block_job_create(job_id, &backup_job_driver, txn, bs, 0, BLK_PERM_ALL,
338
+ job = block_job_create(job_id, &backup_job_driver, txn, backup_top,
339
+ 0, BLK_PERM_ALL,
340
speed, creation_flags, cb, opaque, errp);
341
if (!job) {
342
goto error;
343
}
344
345
+ job->backup_top = backup_top;
346
job->source_bs = bs;
347
job->on_source_error = on_source_error;
348
job->on_target_error = on_target_error;
349
job->sync_mode = sync_mode;
350
job->sync_bitmap = sync_bitmap;
351
job->bitmap_mode = bitmap_mode;
352
-
353
- job->bcs = block_copy_state_new(bs, target, cluster_size, write_flags,
354
- errp);
355
- if (!job->bcs) {
356
- goto error;
357
- }
358
-
359
+ job->bcs = bcs;
360
job->cluster_size = cluster_size;
361
job->len = len;
362
363
- block_copy_set_callbacks(job->bcs, backup_progress_bytes_callback,
364
+ block_copy_set_callbacks(bcs, backup_progress_bytes_callback,
365
backup_progress_reset_callback, job);
366
367
- /* Required permissions are already taken by block-copy-state target */
368
+ /* Required permissions are already taken by backup-top target */
369
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
370
&error_abort);
371
372
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
373
if (job) {
374
backup_clean(&job->common.job);
375
job_early_fail(&job->common.job);
376
+ } else if (backup_top) {
377
+ bdrv_backup_top_drop(backup_top);
378
}
379
380
return NULL;
381
diff --git a/block/block-copy.c b/block/block-copy.c
382
index XXXXXXX..XXXXXXX 100644
383
--- a/block/block-copy.c
384
+++ b/block/block-copy.c
385
@@ -XXX,XX +XXX,XX @@ void block_copy_state_free(BlockCopyState *s)
386
return;
387
}
388
389
- bdrv_release_dirty_bitmap(blk_bs(s->source), s->copy_bitmap);
390
- blk_unref(s->source);
391
- blk_unref(s->target);
392
+ bdrv_release_dirty_bitmap(s->source->bs, s->copy_bitmap);
393
g_free(s);
394
}
395
396
-BlockCopyState *block_copy_state_new(BlockDriverState *source,
397
- BlockDriverState *target,
398
+BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
399
int64_t cluster_size,
400
BdrvRequestFlags write_flags, Error **errp)
401
{
402
BlockCopyState *s;
403
- int ret;
404
- uint64_t no_resize = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
405
- BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD;
406
BdrvDirtyBitmap *copy_bitmap;
407
+ uint32_t max_transfer =
408
+ MIN_NON_ZERO(INT_MAX, MIN_NON_ZERO(source->bs->bl.max_transfer,
409
+ target->bs->bl.max_transfer));
410
411
- copy_bitmap = bdrv_create_dirty_bitmap(source, cluster_size, NULL, errp);
412
+ copy_bitmap = bdrv_create_dirty_bitmap(source->bs, cluster_size, NULL,
413
+ errp);
414
if (!copy_bitmap) {
415
return NULL;
416
}
417
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BlockDriverState *source,
418
419
s = g_new(BlockCopyState, 1);
420
*s = (BlockCopyState) {
421
- .source = blk_new(bdrv_get_aio_context(source),
422
- BLK_PERM_CONSISTENT_READ, no_resize),
423
- .target = blk_new(bdrv_get_aio_context(target),
424
- BLK_PERM_WRITE, no_resize),
425
+ .source = source,
426
+ .target = target,
427
.copy_bitmap = copy_bitmap,
428
.cluster_size = cluster_size,
429
.len = bdrv_dirty_bitmap_size(copy_bitmap),
430
.write_flags = write_flags,
431
};
432
433
- s->copy_range_size = QEMU_ALIGN_DOWN(MIN(blk_get_max_transfer(s->source),
434
- blk_get_max_transfer(s->target)),
435
- s->cluster_size);
436
+ s->copy_range_size = QEMU_ALIGN_DOWN(max_transfer, cluster_size),
437
/*
438
* Set use_copy_range, consider the following:
439
* 1. Compression is not supported for copy_range.
440
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BlockDriverState *source,
441
442
QLIST_INIT(&s->inflight_reqs);
443
444
- /*
445
- * We just allow aio context change on our block backends. block_copy() user
446
- * (now it's only backup) is responsible for source and target being in same
447
- * aio context.
448
- */
449
- blk_set_disable_request_queuing(s->source, true);
450
- blk_set_allow_aio_context_change(s->source, true);
451
- blk_set_disable_request_queuing(s->target, true);
452
- blk_set_allow_aio_context_change(s->target, true);
453
-
454
- ret = blk_insert_bs(s->source, source, errp);
455
- if (ret < 0) {
456
- goto fail;
457
- }
458
-
459
- ret = blk_insert_bs(s->target, target, errp);
460
- if (ret < 0) {
461
- goto fail;
462
- }
463
-
464
return s;
465
-
466
-fail:
467
- block_copy_state_free(s);
468
-
469
- return NULL;
470
}
471
472
void block_copy_set_callbacks(
473
@@ -XXX,XX +XXX,XX @@ void block_copy_set_callbacks(
474
static int coroutine_fn block_copy_with_bounce_buffer(BlockCopyState *s,
475
int64_t start,
476
int64_t end,
477
- bool is_write_notifier,
478
bool *error_is_read,
479
void **bounce_buffer)
480
{
481
int ret;
482
int nbytes;
483
- int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
484
485
assert(QEMU_IS_ALIGNED(start, s->cluster_size));
486
bdrv_reset_dirty_bitmap(s->copy_bitmap, start, s->cluster_size);
487
nbytes = MIN(s->cluster_size, s->len - start);
488
if (!*bounce_buffer) {
489
- *bounce_buffer = blk_blockalign(s->source, s->cluster_size);
490
+ *bounce_buffer = qemu_blockalign(s->source->bs, s->cluster_size);
491
}
492
493
- ret = blk_co_pread(s->source, start, nbytes, *bounce_buffer, read_flags);
494
+ ret = bdrv_co_pread(s->source, start, nbytes, *bounce_buffer, 0);
495
if (ret < 0) {
496
trace_block_copy_with_bounce_buffer_read_fail(s, start, ret);
497
if (error_is_read) {
498
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_with_bounce_buffer(BlockCopyState *s,
499
goto fail;
500
}
501
502
- ret = blk_co_pwrite(s->target, start, nbytes, *bounce_buffer,
503
- s->write_flags);
504
+ ret = bdrv_co_pwrite(s->target, start, nbytes, *bounce_buffer,
505
+ s->write_flags);
506
if (ret < 0) {
507
trace_block_copy_with_bounce_buffer_write_fail(s, start, ret);
508
if (error_is_read) {
509
@@ -XXX,XX +XXX,XX @@ fail:
510
*/
511
static int coroutine_fn block_copy_with_offload(BlockCopyState *s,
512
int64_t start,
513
- int64_t end,
514
- bool is_write_notifier)
515
+ int64_t end)
516
{
517
int ret;
518
int nr_clusters;
519
int nbytes;
520
- int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
521
522
assert(QEMU_IS_ALIGNED(s->copy_range_size, s->cluster_size));
523
assert(QEMU_IS_ALIGNED(start, s->cluster_size));
524
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_with_offload(BlockCopyState *s,
525
nr_clusters = DIV_ROUND_UP(nbytes, s->cluster_size);
526
bdrv_reset_dirty_bitmap(s->copy_bitmap, start,
527
s->cluster_size * nr_clusters);
528
- ret = blk_co_copy_range(s->source, start, s->target, start, nbytes,
529
- read_flags, s->write_flags);
530
+ ret = bdrv_co_copy_range(s->source, start, s->target, start, nbytes,
531
+ 0, s->write_flags);
532
if (ret < 0) {
533
trace_block_copy_with_offload_fail(s, start, ret);
534
bdrv_set_dirty_bitmap(s->copy_bitmap, start,
535
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_with_offload(BlockCopyState *s,
536
static int block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
537
int64_t *pnum)
538
{
539
- BlockDriverState *bs = blk_bs(s->source);
540
+ BlockDriverState *bs = s->source->bs;
541
int64_t count, total_count = 0;
542
int64_t bytes = s->len - offset;
543
int ret;
544
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
545
546
int coroutine_fn block_copy(BlockCopyState *s,
547
int64_t start, uint64_t bytes,
548
- bool *error_is_read,
549
- bool is_write_notifier)
550
+ bool *error_is_read)
551
{
552
int ret = 0;
553
int64_t end = bytes + start; /* bytes */
554
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
555
* block_copy() user is responsible for keeping source and target in same
556
* aio context
557
*/
558
- assert(blk_get_aio_context(s->source) == blk_get_aio_context(s->target));
559
+ assert(bdrv_get_aio_context(s->source->bs) ==
560
+ bdrv_get_aio_context(s->target->bs));
561
562
assert(QEMU_IS_ALIGNED(start, s->cluster_size));
563
assert(QEMU_IS_ALIGNED(end, s->cluster_size));
564
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
565
trace_block_copy_process(s, start);
566
567
if (s->use_copy_range) {
568
- ret = block_copy_with_offload(s, start, dirty_end,
569
- is_write_notifier);
570
+ ret = block_copy_with_offload(s, start, dirty_end);
571
if (ret < 0) {
572
s->use_copy_range = false;
573
}
574
}
575
if (!s->use_copy_range) {
576
ret = block_copy_with_bounce_buffer(s, start, dirty_end,
577
- is_write_notifier,
578
error_is_read, &bounce_buffer);
579
}
580
if (ret < 0) {
581
diff --git a/block/replication.c b/block/replication.c
582
index XXXXXXX..XXXXXXX 100644
583
--- a/block/replication.c
584
+++ b/block/replication.c
585
@@ -XXX,XX +XXX,XX @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
586
587
s->backup_job = backup_job_create(
588
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
589
- 0, MIRROR_SYNC_MODE_NONE, NULL, 0, false,
590
+ 0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, NULL,
591
BLOCKDEV_ON_ERROR_REPORT,
592
BLOCKDEV_ON_ERROR_REPORT, JOB_INTERNAL,
593
backup_job_completed, bs, NULL, &local_err);
594
diff --git a/blockdev.c b/blockdev.c
15
diff --git a/blockdev.c b/blockdev.c
595
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
596
--- a/blockdev.c
17
--- a/blockdev.c
597
+++ b/blockdev.c
18
+++ b/blockdev.c
598
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
19
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDirtyBitmapState {
599
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
20
BlkActionState common;
600
backup->sync, bmap, backup->bitmap_mode,
21
BdrvDirtyBitmap *bitmap;
601
backup->compress,
22
BlockDriverState *bs;
602
+ backup->filter_node_name,
23
- AioContext *aio_context;
603
backup->on_source_error,
24
HBitmap *backup;
604
backup->on_target_error,
25
bool prepared;
605
job_flags, NULL, NULL, txn, errp);
26
} BlockDirtyBitmapState;
606
diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
27
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
607
index XXXXXXX..XXXXXXX 100755
28
}
608
--- a/tests/qemu-iotests/056
29
609
+++ b/tests/qemu-iotests/056
30
bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
610
@@ -XXX,XX +XXX,XX @@ class BackupTest(iotests.QMPTestCase):
31
- /* AioContext is released in .clean() */
611
self.vm = iotests.VM()
32
}
612
self.test_img = img_create('test')
33
613
self.dest_img = img_create('dest')
34
static void block_dirty_bitmap_clear_abort(BlkActionState *common)
614
+ self.dest_img2 = img_create('dest2')
35
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_commit(BlkActionState *common)
615
self.ref_img = img_create('ref')
36
hbitmap_free(state->backup);
616
self.vm.add_drive(self.test_img)
37
}
617
self.vm.launch()
38
618
@@ -XXX,XX +XXX,XX @@ class BackupTest(iotests.QMPTestCase):
39
-static void block_dirty_bitmap_clear_clean(BlkActionState *common)
619
self.vm.shutdown()
40
-{
620
try_remove(self.test_img)
41
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
621
try_remove(self.dest_img)
42
- common, common);
622
+ try_remove(self.dest_img2)
43
-
623
try_remove(self.ref_img)
44
- if (state->aio_context) {
624
45
- aio_context_release(state->aio_context);
625
def hmp_io_writes(self, drive, patterns):
46
- }
626
@@ -XXX,XX +XXX,XX @@ class BackupTest(iotests.QMPTestCase):
47
-}
627
res = self.vm.qmp('query-block-jobs')
48
-
628
self.assert_qmp(res, 'return[0]/status', 'concluded')
49
static void abort_prepare(BlkActionState *common, Error **errp)
629
# Leave zombie job un-dismissed, observe a failure:
50
{
630
- res = self.qmp_backup_and_wait(serror="Node 'drive0' is busy: block device is in use by block job: backup",
51
error_setg(errp, "Transaction aborted using Abort action");
631
+ res = self.qmp_backup_and_wait(serror="Job ID 'drive0' already in use",
52
@@ -XXX,XX +XXX,XX @@ static const BlkActionOps actions[] = {
632
device='drive0', format=iotests.imgfmt,
53
.prepare = block_dirty_bitmap_clear_prepare,
633
- sync='full', target=self.dest_img,
54
.commit = block_dirty_bitmap_clear_commit,
634
+ sync='full', target=self.dest_img2,
55
.abort = block_dirty_bitmap_clear_abort,
635
auto_dismiss=False)
56
- .clean = block_dirty_bitmap_clear_clean,
636
self.assertEqual(res, False)
57
}
637
# OK, dismiss the zombie.
58
};
638
@@ -XXX,XX +XXX,XX @@ class BackupTest(iotests.QMPTestCase):
639
self.assert_qmp(res, 'return', [])
640
# Ensure it's really gone.
641
self.qmp_backup_and_wait(device='drive0', format=iotests.imgfmt,
642
- sync='full', target=self.dest_img,
643
+ sync='full', target=self.dest_img2,
644
auto_dismiss=False)
645
646
def dismissal_failure(self, dismissal_opt):
647
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
648
index XXXXXXX..XXXXXXX 100644
649
--- a/tests/qemu-iotests/141.out
650
+++ b/tests/qemu-iotests/141.out
651
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
652
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
653
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
654
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
655
-{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
656
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
657
{"return": {}}
658
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
659
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
660
diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257
661
index XXXXXXX..XXXXXXX 100755
662
--- a/tests/qemu-iotests/257
663
+++ b/tests/qemu-iotests/257
664
@@ -XXX,XX +XXX,XX @@ def blockdev_backup(vm, device, target, sync, **kwargs):
665
device=device,
666
target=target,
667
sync=sync,
668
+ filter_node_name='backup-top',
669
**kwargs)
670
return result
671
672
@@ -XXX,XX +XXX,XX @@ def backup(drive, n, filepath, sync, **kwargs):
673
job_id=job_id, **kwargs)
674
return job_id
675
676
-def perform_writes(drive, n):
677
+def perform_writes(drive, n, filter_node_name=None):
678
log("--- Write #{:d} ---\n".format(n))
679
for pattern in GROUPS[n].patterns:
680
cmd = "write -P{:s} 0x{:07x} 0x{:x}".format(
681
@@ -XXX,XX +XXX,XX @@ def perform_writes(drive, n):
682
pattern.offset,
683
pattern.size)
684
log(cmd)
685
- log(drive.vm.hmp_qemu_io(drive.node, cmd))
686
+ log(drive.vm.hmp_qemu_io(filter_node_name or drive.node, cmd))
687
bitmaps = drive.vm.query_bitmaps()
688
log({'bitmaps': bitmaps}, indent=2)
689
log('')
690
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
691
"""Issue writes while the job is open to test bitmap divergence."""
692
# Note: when `failure` is 'intermediate', this isn't called.
693
log('')
694
- bitmaps = perform_writes(drive0, 2)
695
+ bitmaps = perform_writes(drive0, 2, filter_node_name='backup-top')
696
# Named bitmap (static, should be unchanged)
697
ebitmap.compare(vm.get_bitmap(drive0.node, 'bitmap0',
698
bitmaps=bitmaps))
699
diff --git a/tests/qemu-iotests/257.out b/tests/qemu-iotests/257.out
700
index XXXXXXX..XXXXXXX 100644
701
--- a/tests/qemu-iotests/257.out
702
+++ b/tests/qemu-iotests/257.out
703
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
704
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
705
{"return": {}}
706
{}
707
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
708
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
709
{"return": {}}
710
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
711
712
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
713
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
714
{"return": {}}
715
{}
716
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
717
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
718
{"return": {}}
719
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
720
721
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
722
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
723
{"return": {}}
724
{}
725
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
726
+{"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"}}
727
{"return": {}}
728
729
--- Write #2 ---
730
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
731
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
732
{"return": {}}
733
{}
734
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
735
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
736
{"return": {}}
737
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
738
739
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
740
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
741
{"return": {}}
742
{}
743
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
744
+{"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"}}
745
{"return": {}}
746
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
747
{"return": {}}
748
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
749
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
750
{"return": {}}
751
{}
752
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
753
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
754
{"return": {}}
755
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
756
757
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
758
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
759
{"return": {}}
760
{}
761
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
762
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
763
{"return": {}}
764
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
765
766
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
767
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
768
{"return": {}}
769
{}
770
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
771
+{"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"}}
772
{"return": {}}
773
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
774
{"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"}}
775
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
776
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
777
{"return": {}}
778
{}
779
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
780
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
781
{"return": {}}
782
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
783
784
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
785
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
786
{"return": {}}
787
{}
788
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
789
+{"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"}}
790
{"return": {}}
791
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
792
{"return": {}}
793
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
794
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
795
{"return": {}}
796
{}
797
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
798
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
799
{"return": {}}
800
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
801
802
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
803
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
804
{"return": {}}
805
{}
806
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
807
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
808
{"return": {}}
809
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
810
811
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
812
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
813
{"return": {}}
814
{}
815
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
816
+{"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"}}
817
{"return": {}}
818
819
--- Write #2 ---
820
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
821
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
822
{"return": {}}
823
{}
824
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
825
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
826
{"return": {}}
827
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
828
829
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
830
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
831
{"return": {}}
832
{}
833
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
834
+{"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"}}
835
{"return": {}}
836
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
837
{"return": {}}
838
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
839
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
840
{"return": {}}
841
{}
842
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
843
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
844
{"return": {}}
845
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
846
847
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
848
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
849
{"return": {}}
850
{}
851
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
852
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
853
{"return": {}}
854
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
855
856
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
857
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
858
{"return": {}}
859
{}
860
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
861
+{"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"}}
862
{"return": {}}
863
864
--- Write #2 ---
865
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
866
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
867
{"return": {}}
868
{}
869
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
870
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
871
{"return": {}}
872
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
873
874
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
875
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
876
{"return": {}}
877
{}
878
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
879
+{"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"}}
880
{"return": {}}
881
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
882
{"return": {}}
883
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
884
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
885
{"return": {}}
886
{}
887
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
888
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
889
{"return": {}}
890
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
891
892
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
893
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
894
{"return": {}}
895
{}
896
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
897
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
898
{"return": {}}
899
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
900
901
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
902
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
903
{"return": {}}
904
{}
905
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
906
+{"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"}}
907
{"return": {}}
908
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
909
{"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"}}
910
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
911
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
912
{"return": {}}
913
{}
914
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
915
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
916
{"return": {}}
917
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
918
919
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
920
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
921
{"return": {}}
922
{}
923
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
924
+{"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"}}
925
{"return": {}}
926
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
927
{"return": {}}
928
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
929
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
930
{"return": {}}
931
{}
932
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
933
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
934
{"return": {}}
935
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
936
937
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
938
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
939
{"return": {}}
940
{}
941
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
942
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
943
{"return": {}}
944
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
945
946
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
947
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
948
{"return": {}}
949
{}
950
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
951
+{"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"}}
952
{"return": {}}
953
954
--- Write #2 ---
955
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
956
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
957
{"return": {}}
958
{}
959
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
960
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
961
{"return": {}}
962
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
963
964
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
965
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
966
{"return": {}}
967
{}
968
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
969
+{"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"}}
970
{"return": {}}
971
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
972
{"return": {}}
973
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
974
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
975
{"return": {}}
976
{}
977
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
978
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
979
{"return": {}}
980
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
981
982
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
983
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
984
{"return": {}}
985
{}
986
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
987
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
988
{"return": {}}
989
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
990
991
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
992
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
993
{"return": {}}
994
{}
995
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
996
+{"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"}}
997
{"return": {}}
998
999
--- Write #2 ---
1000
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1001
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1002
{"return": {}}
1003
{}
1004
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1005
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1006
{"return": {}}
1007
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1008
1009
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1010
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1011
{"return": {}}
1012
{}
1013
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1014
+{"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"}}
1015
{"return": {}}
1016
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1017
{"return": {}}
1018
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1019
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1020
{"return": {}}
1021
{}
1022
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1023
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1024
{"return": {}}
1025
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1026
1027
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1028
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1029
{"return": {}}
1030
{}
1031
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1032
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1033
{"return": {}}
1034
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1035
1036
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1037
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1038
{"return": {}}
1039
{}
1040
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
1041
+{"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"}}
1042
{"return": {}}
1043
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1044
{"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"}}
1045
@@ -XXX,XX +XXX,XX @@ expecting 13 dirty sectors; have 13. OK!
1046
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1047
{"return": {}}
1048
{}
1049
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1050
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1051
{"return": {}}
1052
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1053
1054
@@ -XXX,XX +XXX,XX @@ expecting 13 dirty sectors; have 13. OK!
1055
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1056
{"return": {}}
1057
{}
1058
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1059
+{"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"}}
1060
{"return": {}}
1061
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1062
{"return": {}}
1063
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1064
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1065
{"return": {}}
1066
{}
1067
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1068
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1069
{"return": {}}
1070
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1071
1072
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1073
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1074
{"return": {}}
1075
{}
1076
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1077
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1078
{"return": {}}
1079
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1080
1081
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1082
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1083
{"return": {}}
1084
{}
1085
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "bitmap", "target": "backup_target_1"}}
1086
+{"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"}}
1087
{"return": {}}
1088
1089
--- Write #2 ---
1090
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1091
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1092
{"return": {}}
1093
{}
1094
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1095
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1096
{"return": {}}
1097
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1098
1099
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1100
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1101
{"return": {}}
1102
{}
1103
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1104
+{"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"}}
1105
{"return": {}}
1106
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1107
{"return": {}}
1108
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1109
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1110
{"return": {}}
1111
{}
1112
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1113
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1114
{"return": {}}
1115
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1116
1117
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1118
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1119
{"return": {}}
1120
{}
1121
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1122
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1123
{"return": {}}
1124
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1125
1126
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1127
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1128
{"return": {}}
1129
{}
1130
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
1131
+{"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"}}
1132
{"return": {}}
1133
1134
--- Write #2 ---
1135
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
1136
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1137
{"return": {}}
1138
{}
1139
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1140
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1141
{"return": {}}
1142
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1143
1144
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
1145
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1146
{"return": {}}
1147
{}
1148
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1149
+{"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"}}
1150
{"return": {}}
1151
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1152
{"return": {}}
1153
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1154
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1155
{"return": {}}
1156
{}
1157
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1158
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1159
{"return": {}}
1160
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1161
1162
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1163
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1164
{"return": {}}
1165
{}
1166
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1167
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1168
{"return": {}}
1169
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1170
1171
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1172
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1173
{"return": {}}
1174
{}
1175
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
1176
+{"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"}}
1177
{"return": {}}
1178
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1179
{"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"}}
1180
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
1181
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1182
{"return": {}}
1183
{}
1184
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1185
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1186
{"return": {}}
1187
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1188
1189
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
1190
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1191
{"return": {}}
1192
{}
1193
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1194
+{"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"}}
1195
{"return": {}}
1196
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1197
{"return": {}}
1198
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1199
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1200
{"return": {}}
1201
{}
1202
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1203
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1204
{"return": {}}
1205
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1206
1207
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1208
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1209
{"return": {}}
1210
{}
1211
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1212
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1213
{"return": {}}
1214
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1215
1216
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1217
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1218
{"return": {}}
1219
{}
1220
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
1221
+{"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"}}
1222
{"return": {}}
1223
1224
--- Write #2 ---
1225
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1226
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1227
{"return": {}}
1228
{}
1229
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1230
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1231
{"return": {}}
1232
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1233
1234
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1235
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1236
{"return": {}}
1237
{}
1238
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1239
+{"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"}}
1240
{"return": {}}
1241
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1242
{"return": {}}
1243
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1244
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1245
{"return": {}}
1246
{}
1247
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1248
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1249
{"return": {}}
1250
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1251
1252
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1253
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1254
{"return": {}}
1255
{}
1256
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1257
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1258
{"return": {}}
1259
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1260
1261
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1262
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1263
{"return": {}}
1264
{}
1265
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
1266
+{"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"}}
1267
{"return": {}}
1268
1269
--- Write #2 ---
1270
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1271
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1272
{"return": {}}
1273
{}
1274
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1275
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1276
{"return": {}}
1277
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1278
1279
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1280
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1281
{"return": {}}
1282
{}
1283
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1284
+{"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"}}
1285
{"return": {}}
1286
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1287
{"return": {}}
1288
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1289
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1290
{"return": {}}
1291
{}
1292
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1293
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1294
{"return": {}}
1295
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1296
1297
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1298
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1299
{"return": {}}
1300
{}
1301
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1302
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1303
{"return": {}}
1304
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1305
1306
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1307
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1308
{"return": {}}
1309
{}
1310
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
1311
+{"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"}}
1312
{"return": {}}
1313
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1314
{"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"}}
1315
@@ -XXX,XX +XXX,XX @@ expecting 1014 dirty sectors; have 1014. OK!
1316
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1317
{"return": {}}
1318
{}
1319
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1320
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1321
{"return": {}}
1322
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1323
1324
@@ -XXX,XX +XXX,XX @@ expecting 1014 dirty sectors; have 1014. OK!
1325
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1326
{"return": {}}
1327
{}
1328
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1329
+{"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"}}
1330
{"return": {}}
1331
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1332
{"return": {}}
1333
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1334
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1335
{"return": {}}
1336
{}
1337
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1338
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1339
{"return": {}}
1340
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1341
1342
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1343
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1344
{"return": {}}
1345
{}
1346
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1347
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1348
{"return": {}}
1349
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1350
1351
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1352
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1353
{"return": {}}
1354
{}
1355
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "full", "target": "backup_target_1"}}
1356
+{"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"}}
1357
{"return": {}}
1358
1359
--- Write #2 ---
1360
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1361
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1362
{"return": {}}
1363
{}
1364
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1365
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1366
{"return": {}}
1367
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1368
1369
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1370
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1371
{"return": {}}
1372
{}
1373
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1374
+{"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"}}
1375
{"return": {}}
1376
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1377
{"return": {}}
1378
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1379
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1380
{"return": {}}
1381
{}
1382
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1383
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1384
{"return": {}}
1385
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1386
1387
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1388
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1389
{"return": {}}
1390
{}
1391
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1392
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1393
{"return": {}}
1394
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1395
1396
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1397
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1398
{"return": {}}
1399
{}
1400
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
1401
+{"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"}}
1402
{"return": {}}
1403
1404
--- Write #2 ---
1405
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
1406
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1407
{"return": {}}
1408
{}
1409
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1410
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1411
{"return": {}}
1412
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1413
1414
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
1415
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1416
{"return": {}}
1417
{}
1418
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1419
+{"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"}}
1420
{"return": {}}
1421
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1422
{"return": {}}
1423
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1424
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1425
{"return": {}}
1426
{}
1427
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1428
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1429
{"return": {}}
1430
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1431
1432
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1433
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1434
{"return": {}}
1435
{}
1436
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1437
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1438
{"return": {}}
1439
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1440
1441
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1442
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1443
{"return": {}}
1444
{}
1445
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
1446
+{"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"}}
1447
{"return": {}}
1448
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1449
{"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"}}
1450
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
1451
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1452
{"return": {}}
1453
{}
1454
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1455
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1456
{"return": {}}
1457
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1458
1459
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
1460
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1461
{"return": {}}
1462
{}
1463
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1464
+{"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"}}
1465
{"return": {}}
1466
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1467
{"return": {}}
1468
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1469
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1470
{"return": {}}
1471
{}
1472
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1473
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1474
{"return": {}}
1475
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1476
1477
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1478
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1479
{"return": {}}
1480
{}
1481
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1482
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1483
{"return": {}}
1484
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1485
1486
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1487
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1488
{"return": {}}
1489
{}
1490
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
1491
+{"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"}}
1492
{"return": {}}
1493
1494
--- Write #2 ---
1495
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1496
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1497
{"return": {}}
1498
{}
1499
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1500
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1501
{"return": {}}
1502
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1503
1504
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1505
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1506
{"return": {}}
1507
{}
1508
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1509
+{"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"}}
1510
{"return": {}}
1511
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1512
{"return": {}}
1513
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1514
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1515
{"return": {}}
1516
{}
1517
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1518
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1519
{"return": {}}
1520
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1521
1522
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1523
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1524
{"return": {}}
1525
{}
1526
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1527
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1528
{"return": {}}
1529
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1530
1531
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1532
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1533
{"return": {}}
1534
{}
1535
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
1536
+{"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"}}
1537
{"return": {}}
1538
1539
--- Write #2 ---
1540
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1541
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1542
{"return": {}}
1543
{}
1544
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1545
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1546
{"return": {}}
1547
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1548
1549
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1550
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1551
{"return": {}}
1552
{}
1553
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1554
+{"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"}}
1555
{"return": {}}
1556
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1557
{"return": {}}
1558
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1559
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1560
{"return": {}}
1561
{}
1562
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1563
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1564
{"return": {}}
1565
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1566
1567
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1568
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1569
{"return": {}}
1570
{}
1571
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1572
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1573
{"return": {}}
1574
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1575
1576
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1577
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1578
{"return": {}}
1579
{}
1580
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
1581
+{"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"}}
1582
{"return": {}}
1583
{"data": {"action": "report", "device": "backup_1", "operation": "read"}, "event": "BLOCK_JOB_ERROR", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1584
{"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"}}
1585
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
1586
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1587
{"return": {}}
1588
{}
1589
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1590
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1591
{"return": {}}
1592
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1593
1594
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
1595
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1596
{"return": {}}
1597
{}
1598
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1599
+{"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"}}
1600
{"return": {}}
1601
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1602
{"return": {}}
1603
@@ -XXX,XX +XXX,XX @@ write -P0x76 0x3ff0000 0x10000
1604
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1605
{"return": {}}
1606
{}
1607
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1608
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_0", "sync": "full", "target": "ref_target_0"}}
1609
{"return": {}}
1610
{"data": {"device": "ref_backup_0", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1611
1612
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1613
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1614
{"return": {}}
1615
{}
1616
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1617
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_1", "sync": "full", "target": "ref_target_1"}}
1618
{"return": {}}
1619
{"data": {"device": "ref_backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1620
1621
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1622
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1623
{"return": {}}
1624
{}
1625
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_1", "sync": "top", "target": "backup_target_1"}}
1626
+{"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"}}
1627
{"return": {}}
1628
1629
--- Write #2 ---
1630
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1631
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1632
{"return": {}}
1633
{}
1634
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1635
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "ref_backup_2", "sync": "full", "target": "ref_target_2"}}
1636
{"return": {}}
1637
{"data": {"device": "ref_backup_2", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1638
1639
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1640
{"execute": "job-dismiss", "arguments": {"id": "bdc-fmt-job"}}
1641
{"return": {}}
1642
{}
1643
-{"execute": "blockdev-backup", "arguments": {"auto-finalize": false, "bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "backup_2", "sync": "bitmap", "target": "backup_target_2"}}
1644
+{"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"}}
1645
{"return": {}}
1646
{"execute": "job-finalize", "arguments": {"id": "backup_2"}}
1647
{"return": {}}
1648
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
1649
1650
-- Sync mode incremental tests --
1651
1652
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1653
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1654
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'incremental' sync mode"}}
1655
1656
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1657
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1658
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'incremental' sync mode"}}
1659
1660
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1661
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1662
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'incremental' sync mode"}}
1663
1664
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1665
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1666
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'incremental' sync mode"}}
1667
1668
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1669
+{"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"}}
1670
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1671
1672
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1673
+{"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"}}
1674
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be 'on-success' when using sync mode 'incremental'"}}
1675
1676
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1677
+{"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"}}
1678
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be 'on-success' when using sync mode 'incremental'"}}
1679
1680
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1681
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1682
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1683
1684
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1685
+{"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"}}
1686
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be 'on-success' when using sync mode 'incremental'"}}
1687
1688
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "incremental", "target": "backup_target"}}
1689
+{"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"}}
1690
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be 'on-success' when using sync mode 'incremental'"}}
1691
1692
-- Sync mode bitmap tests --
1693
1694
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1695
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1696
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'bitmap' sync mode"}}
1697
1698
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1699
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1700
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'bitmap' sync mode"}}
1701
1702
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1703
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1704
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'bitmap' sync mode"}}
1705
1706
-{"execute": "blockdev-backup", "arguments": {"device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1707
+{"execute": "blockdev-backup", "arguments": {"device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1708
{"error": {"class": "GenericError", "desc": "must provide a valid bitmap name for 'bitmap' sync mode"}}
1709
1710
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1711
+{"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"}}
1712
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1713
1714
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1715
+{"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"}}
1716
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1717
1718
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1719
+{"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"}}
1720
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1721
1722
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1723
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1724
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1725
1726
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1727
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "bitmap", "target": "backup_target"}}
1728
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be given when providing a bitmap"}}
1729
1730
-- Sync mode full tests --
1731
1732
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1733
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1734
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1735
1736
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1737
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1738
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1739
1740
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1741
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1742
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1743
1744
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1745
+{"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"}}
1746
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1747
1748
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1749
+{"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"}}
1750
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1751
1752
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1753
+{"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"}}
1754
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1755
1756
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1757
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1758
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1759
1760
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1761
+{"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"}}
1762
{"error": {"class": "GenericError", "desc": "Bitmap sync mode 'never' has no meaningful effect when combined with sync mode 'full'"}}
1763
1764
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1765
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "full", "target": "backup_target"}}
1766
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be given when providing a bitmap"}}
1767
1768
-- Sync mode top tests --
1769
1770
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1771
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1772
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1773
1774
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1775
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1776
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1777
1778
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1779
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1780
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1781
1782
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1783
+{"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"}}
1784
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1785
1786
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1787
+{"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"}}
1788
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1789
1790
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1791
+{"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"}}
1792
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1793
1794
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1795
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1796
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1797
1798
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1799
+{"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"}}
1800
{"error": {"class": "GenericError", "desc": "Bitmap sync mode 'never' has no meaningful effect when combined with sync mode 'top'"}}
1801
1802
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1803
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "top", "target": "backup_target"}}
1804
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be given when providing a bitmap"}}
1805
1806
-- Sync mode none tests --
1807
1808
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1809
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "on-success", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1810
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1811
1812
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1813
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "always", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1814
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1815
1816
-{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1817
+{"execute": "blockdev-backup", "arguments": {"bitmap-mode": "never", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1818
{"error": {"class": "GenericError", "desc": "Cannot specify bitmap sync mode without a bitmap"}}
1819
1820
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1821
+{"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"}}
1822
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1823
1824
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1825
+{"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"}}
1826
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1827
1828
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1829
+{"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"}}
1830
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1831
1832
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1833
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap404", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1834
{"error": {"class": "GenericError", "desc": "Bitmap 'bitmap404' could not be found"}}
1835
1836
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "on-success", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1837
+{"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"}}
1838
{"error": {"class": "GenericError", "desc": "sync mode 'none' does not produce meaningful bitmap outputs"}}
1839
1840
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "always", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1841
+{"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"}}
1842
{"error": {"class": "GenericError", "desc": "sync mode 'none' does not produce meaningful bitmap outputs"}}
1843
1844
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "bitmap-mode": "never", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1845
+{"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"}}
1846
{"error": {"class": "GenericError", "desc": "sync mode 'none' does not produce meaningful bitmap outputs"}}
1847
1848
-{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1849
+{"execute": "blockdev-backup", "arguments": {"bitmap": "bitmap0", "device": "drive0", "filter-node-name": "backup-top", "job-id": "api_job", "sync": "none", "target": "backup_target"}}
1850
{"error": {"class": "GenericError", "desc": "Bitmap sync mode must be given when providing a bitmap"}}
1851
59
1852
--
60
--
1853
2.21.0
61
2.14.3
1854
62
1855
63
diff view generated by jsdifflib
1
From: Daniel P. Berrangé <berrange@redhat.com>
1
Encapsulate IOThread QOM object lookup so that callers don't need to
2
know how and where IOThread objects live.
2
3
3
Some distros are now defaulting to LUKS version 2 which QEMU cannot
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
process. For our I/O test that validates interoperability between the
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
kernel/cryptsetup and QEMU, we need to explicitly ask for version 1
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
of the LUKS format.
7
Message-id: 20171206144550.22295-8-stefanha@redhat.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
include/sysemu/iothread.h | 1 +
11
iothread.c | 7 +++++++
12
2 files changed, 8 insertions(+)
7
13
8
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
14
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
9
Message-id: 20190927101155.25896-1-berrange@redhat.com
10
Tested-by: Maxim Levitsky <mlevitsk@redhat.com>
11
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
tests/qemu-iotests/149 | 2 +-
15
tests/qemu-iotests/149.out | 44 +++++++++++++++++++-------------------
16
2 files changed, 23 insertions(+), 23 deletions(-)
17
18
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/149
21
+++ b/tests/qemu-iotests/149
22
@@ -XXX,XX +XXX,XX @@ def cryptsetup_format(config):
23
24
(password, slot) = config.first_password()
25
26
- args = ["luksFormat"]
27
+ args = ["luksFormat", "--type", "luks1"]
28
cipher = config.cipher + "-" + config.mode + "-" + config.ivgen
29
if config.ivgen_hash is not None:
30
cipher = cipher + ":" + config.ivgen_hash
31
diff --git a/tests/qemu-iotests/149.out b/tests/qemu-iotests/149.out
32
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/qemu-iotests/149.out
16
--- a/include/sysemu/iothread.h
34
+++ b/tests/qemu-iotests/149.out
17
+++ b/include/sysemu/iothread.h
35
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ typedef struct {
36
# Create image
19
OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD)
37
truncate TEST_DIR/luks-aes-256-xts-plain64-sha1.img --size 4194304MB
20
38
# Format image
21
char *iothread_get_id(IOThread *iothread);
39
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha1.img
22
+IOThread *iothread_by_id(const char *id);
40
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha1.img
23
AioContext *iothread_get_aio_context(IOThread *iothread);
41
# Open dev
24
void iothread_stop_all(void);
42
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
25
GMainContext *iothread_get_g_main_context(IOThread *iothread);
43
# Write test pattern 0xa7
26
diff --git a/iothread.c b/iothread.c
44
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha1.img
27
index XXXXXXX..XXXXXXX 100644
45
# Create image
28
--- a/iothread.c
46
truncate TEST_DIR/luks-twofish-256-xts-plain64-sha1.img --size 4194304MB
29
+++ b/iothread.c
47
# Format image
30
@@ -XXX,XX +XXX,XX @@ void iothread_destroy(IOThread *iothread)
48
-sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
31
{
49
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher twofish-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
32
object_unparent(OBJECT(iothread));
50
# Open dev
33
}
51
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
34
+
52
# Write test pattern 0xa7
35
+/* Lookup IOThread by its id. Only finds user-created objects, not internal
53
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
36
+ * iothread_create() objects. */
54
# Create image
37
+IOThread *iothread_by_id(const char *id)
55
truncate TEST_DIR/luks-serpent-256-xts-plain64-sha1.img --size 4194304MB
38
+{
56
# Format image
39
+ return IOTHREAD(object_resolve_path_type(id, TYPE_IOTHREAD, NULL));
57
-sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
40
+}
58
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher serpent-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
59
# Open dev
60
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
61
# Write test pattern 0xa7
62
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
63
# Create image
64
truncate TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img --size 4194304MB
65
# Format image
66
-sudo cryptsetup -q -v luksFormat --cipher cast5-cbc-plain64 --key-size 128 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
67
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher cast5-cbc-plain64 --key-size 128 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
68
# Open dev
69
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
70
# Write test pattern 0xa7
71
@@ -XXX,XX +XXX,XX @@ Skipping cast6-256-xts-plain64-sha1 in blacklist
72
# Create image
73
truncate TEST_DIR/luks-aes-256-cbc-plain-sha1.img --size 4194304MB
74
# Format image
75
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain-sha1.img
76
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-cbc-plain --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain-sha1.img
77
# Open dev
78
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
79
# Write test pattern 0xa7
80
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-plain-sha1.img
81
# Create image
82
truncate TEST_DIR/luks-aes-256-cbc-plain64-sha1.img --size 4194304MB
83
# Format image
84
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
85
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-cbc-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
86
# Open dev
87
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
88
# Write test pattern 0xa7
89
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
90
# Create image
91
truncate TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img --size 4194304MB
92
# Format image
93
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
94
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
95
# Open dev
96
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
97
# Write test pattern 0xa7
98
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
99
# Create image
100
truncate TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img --size 4194304MB
101
# Format image
102
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-essiv:sha256 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
103
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-essiv:sha256 --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
104
# Open dev
105
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
106
# Write test pattern 0xa7
107
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
108
# Create image
109
truncate TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img --size 4194304MB
110
# Format image
111
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
112
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
113
# Open dev
114
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
115
# Write test pattern 0xa7
116
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
117
# Create image
118
truncate TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img --size 4194304MB
119
# Format image
120
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
121
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
122
# Open dev
123
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
124
# Write test pattern 0xa7
125
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
126
# Create image
127
truncate TEST_DIR/luks-twofish-128-xts-plain64-sha1.img --size 4194304MB
128
# Format image
129
-sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
130
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher twofish-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
131
# Open dev
132
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
133
# Write test pattern 0xa7
134
@@ -XXX,XX +XXX,XX @@ Skipping twofish-192-xts-plain64-sha1 in blacklist
135
# Create image
136
truncate TEST_DIR/luks-serpent-128-xts-plain64-sha1.img --size 4194304MB
137
# Format image
138
-sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
139
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher serpent-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
140
# Open dev
141
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
142
# Write test pattern 0xa7
143
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
144
# Create image
145
truncate TEST_DIR/luks-serpent-192-xts-plain64-sha1.img --size 4194304MB
146
# Format image
147
-sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
148
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher serpent-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
149
# Open dev
150
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
151
# Write test pattern 0xa7
152
@@ -XXX,XX +XXX,XX @@ Skipping cast6-192-xts-plain64-sha1 in blacklist
153
# Create image
154
truncate TEST_DIR/luks-aes-256-xts-plain64-sha224.img --size 4194304MB
155
# Format image
156
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha224 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha224.img
157
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain64 --key-size 512 --hash sha224 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha224.img
158
# Open dev
159
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
160
# Write test pattern 0xa7
161
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha224.img
162
# Create image
163
truncate TEST_DIR/luks-aes-256-xts-plain64-sha256.img --size 4194304MB
164
# Format image
165
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha256 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha256.img
166
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain64 --key-size 512 --hash sha256 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha256.img
167
# Open dev
168
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
169
# Write test pattern 0xa7
170
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha256.img
171
# Create image
172
truncate TEST_DIR/luks-aes-256-xts-plain64-sha384.img --size 4194304MB
173
# Format image
174
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha384 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha384.img
175
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain64 --key-size 512 --hash sha384 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha384.img
176
# Open dev
177
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
178
# Write test pattern 0xa7
179
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha384.img
180
# Create image
181
truncate TEST_DIR/luks-aes-256-xts-plain64-sha512.img --size 4194304MB
182
# Format image
183
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha512 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha512.img
184
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-sha512.img
185
# Open dev
186
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
187
# Write test pattern 0xa7
188
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha512.img
189
# Create image
190
truncate TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img --size 4194304MB
191
# Format image
192
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash ripemd160 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
193
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain64 --key-size 512 --hash ripemd160 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
194
# Open dev
195
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
196
# Write test pattern 0xa7
197
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
198
# Create image
199
truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img --size 4194304MB
200
# Format image
201
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 3 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
202
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 3 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
203
# Open dev
204
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img qiotest-145-aes-256-xts-plain-sha1-pwslot3
205
# Write test pattern 0xa7
206
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
207
# Create image
208
truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --size 4194304MB
209
# Format image
210
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
211
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
212
# Add password slot 1
213
sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 1 --key-file - --iter-time 10 TEST_DIR/passwd.txt
214
# Add password slot 2
215
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
216
# Create image
217
truncate TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img --size 4194304MB
218
# Format image
219
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
220
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
221
# Open dev
222
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
223
# Write test pattern 0xa7
224
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
225
# Create image
226
truncate TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img --size 4194304MB
227
# Format image
228
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
229
+sudo cryptsetup -q -v luksFormat --type luks1 --cipher aes-cbc-plain64:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - --iter-time 10 TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
230
# Open dev
231
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
232
# Write test pattern 0xa7
233
--
41
--
234
2.21.0
42
2.14.3
235
43
236
44
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
Currently there is no easy way for iotests to ensure that a BDS is bound
2
to a particular IOThread. Normally the virtio-blk device calls
3
blk_set_aio_context() when dataplane is enabled during guest driver
4
initialization. This never happens in iotests since -machine
5
accel=qtest means there is no guest activity (including device driver
6
initialization).
2
7
3
A block driver can provide a callback to report driver-specific
8
This patch adds a QMP command to explicitly assign IOThreads in test
4
statistics.
9
cases. See qapi/block-core.json for a description of the command.
5
10
6
file-posix driver now reports discard statistics
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Message-id: 20171206144550.22295-9-stefanha@redhat.com
10
Acked-by: Markus Armbruster <armbru@redhat.com>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: 20190923121737.83281-10-anton.nefedov@virtuozzo.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
16
---
14
qapi/block-core.json | 38 ++++++++++++++++++++++++++++++++++++++
17
qapi/block-core.json | 36 ++++++++++++++++++++++++++++++++++++
15
include/block/block.h | 1 +
18
blockdev.c | 41 +++++++++++++++++++++++++++++++++++++++++
16
include/block/block_int.h | 1 +
19
2 files changed, 77 insertions(+)
17
block.c | 9 +++++++++
18
block/file-posix.c | 32 ++++++++++++++++++++++++++++++++
19
block/qapi.c | 5 +++++
20
6 files changed, 86 insertions(+)
21
20
22
diff --git a/qapi/block-core.json b/qapi/block-core.json
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
23
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
24
--- a/qapi/block-core.json
23
--- a/qapi/block-core.json
25
+++ b/qapi/block-core.json
24
+++ b/qapi/block-core.json
26
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
27
'*wr_latency_histogram': 'BlockLatencyHistogramInfo',
26
'data' : { 'parent': 'str',
28
'*flush_latency_histogram': 'BlockLatencyHistogramInfo' } }
27
'*child': 'str',
29
28
'*node': 'str' } }
30
+##
31
+# @BlockStatsSpecificFile:
32
+#
33
+# File driver statistics
34
+#
35
+# @discard-nb-ok: The number of successful discard operations performed by
36
+# the driver.
37
+#
38
+# @discard-nb-failed: The number of failed discard operations performed by
39
+# the driver.
40
+#
41
+# @discard-bytes-ok: The number of bytes discarded by the driver.
42
+#
43
+# Since: 4.2
44
+##
45
+{ 'struct': 'BlockStatsSpecificFile',
46
+ 'data': {
47
+ 'discard-nb-ok': 'uint64',
48
+ 'discard-nb-failed': 'uint64',
49
+ 'discard-bytes-ok': 'uint64' } }
50
+
29
+
51
+##
30
+##
52
+# @BlockStatsSpecific:
31
+# @x-blockdev-set-iothread:
53
+#
32
+#
54
+# Block driver specific statistics
33
+# Move @node and its children into the @iothread. If @iothread is null then
34
+# move @node and its children into the main loop.
55
+#
35
+#
56
+# Since: 4.2
36
+# The node must not be attached to a BlockBackend.
37
+#
38
+# @node-name: the name of the block driver node
39
+#
40
+# @iothread: the name of the IOThread object or null for the main loop
41
+#
42
+# Note: this command is experimental and intended for test cases that need
43
+# control over IOThreads only.
44
+#
45
+# Since: 2.12
46
+#
47
+# Example:
48
+#
49
+# 1. Move a node into an IOThread
50
+# -> { "execute": "x-blockdev-set-iothread",
51
+# "arguments": { "node-name": "disk1",
52
+# "iothread": "iothread0" } }
53
+# <- { "return": {} }
54
+#
55
+# 2. Move a node into the main loop
56
+# -> { "execute": "x-blockdev-set-iothread",
57
+# "arguments": { "node-name": "disk1",
58
+# "iothread": null } }
59
+# <- { "return": {} }
60
+#
57
+##
61
+##
58
+{ 'union': 'BlockStatsSpecific',
62
+{ 'command': 'x-blockdev-set-iothread',
59
+ 'base': { 'driver': 'BlockdevDriver' },
63
+ 'data' : { 'node-name': 'str',
60
+ 'discriminator': 'driver',
64
+ 'iothread': 'StrOrNull' } }
61
+ 'data': {
65
diff --git a/blockdev.c b/blockdev.c
62
+ 'file': 'BlockStatsSpecificFile',
66
index XXXXXXX..XXXXXXX 100644
63
+ 'host_device': 'BlockStatsSpecificFile' } }
67
--- a/blockdev.c
68
+++ b/blockdev.c
69
@@ -XXX,XX +XXX,XX @@
70
#include "qapi/qmp/qerror.h"
71
#include "qapi/qobject-output-visitor.h"
72
#include "sysemu/sysemu.h"
73
+#include "sysemu/iothread.h"
74
#include "block/block_int.h"
75
#include "qmp-commands.h"
76
#include "block/trace.h"
77
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
78
return head;
79
}
80
81
+void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
82
+ Error **errp)
83
+{
84
+ AioContext *old_context;
85
+ AioContext *new_context;
86
+ BlockDriverState *bs;
64
+
87
+
65
##
88
+ bs = bdrv_find_node(node_name);
66
# @BlockStats:
89
+ if (!bs) {
67
#
90
+ error_setg(errp, "Cannot find node %s", node_name);
68
@@ -XXX,XX +XXX,XX @@
91
+ return;
69
#
70
# @stats: A @BlockDeviceStats for the device.
71
#
72
+# @driver-specific: Optional driver-specific stats. (Since 4.2)
73
+#
74
# @parent: This describes the file block device if it has one.
75
# Contains recursively the statistics of the underlying
76
# protocol (e.g. the host file for a qcow2 image). If there is
77
@@ -XXX,XX +XXX,XX @@
78
{ 'struct': 'BlockStats',
79
'data': {'*device': 'str', '*qdev': 'str', '*node-name': 'str',
80
'stats': 'BlockDeviceStats',
81
+ '*driver-specific': 'BlockStatsSpecific',
82
'*parent': 'BlockStats',
83
'*backing': 'BlockStats'} }
84
85
diff --git a/include/block/block.h b/include/block/block.h
86
index XXXXXXX..XXXXXXX 100644
87
--- a/include/block/block.h
88
+++ b/include/block/block.h
89
@@ -XXX,XX +XXX,XX @@ int bdrv_get_flags(BlockDriverState *bs);
90
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
91
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
92
Error **errp);
93
+BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
94
void bdrv_round_to_clusters(BlockDriverState *bs,
95
int64_t offset, int64_t bytes,
96
int64_t *cluster_offset,
97
diff --git a/include/block/block_int.h b/include/block/block_int.h
98
index XXXXXXX..XXXXXXX 100644
99
--- a/include/block/block_int.h
100
+++ b/include/block/block_int.h
101
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
102
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
103
ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs,
104
Error **errp);
105
+ BlockStatsSpecific *(*bdrv_get_specific_stats)(BlockDriverState *bs);
106
107
int coroutine_fn (*bdrv_save_vmstate)(BlockDriverState *bs,
108
QEMUIOVector *qiov,
109
diff --git a/block.c b/block.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/block.c
112
+++ b/block.c
113
@@ -XXX,XX +XXX,XX @@ ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
114
return NULL;
115
}
116
117
+BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs)
118
+{
119
+ BlockDriver *drv = bs->drv;
120
+ if (!drv || !drv->bdrv_get_specific_stats) {
121
+ return NULL;
122
+ }
92
+ }
123
+ return drv->bdrv_get_specific_stats(bs);
93
+
94
+ /* If we want to allow more extreme test scenarios this guard could be
95
+ * removed. For now it protects against accidents. */
96
+ if (bdrv_has_blk(bs)) {
97
+ error_setg(errp, "Node %s is in use", node_name);
98
+ return;
99
+ }
100
+
101
+ if (iothread->type == QTYPE_QSTRING) {
102
+ IOThread *obj = iothread_by_id(iothread->u.s);
103
+ if (!obj) {
104
+ error_setg(errp, "Cannot find iothread %s", iothread->u.s);
105
+ return;
106
+ }
107
+
108
+ new_context = iothread_get_aio_context(obj);
109
+ } else {
110
+ new_context = qemu_get_aio_context();
111
+ }
112
+
113
+ old_context = bdrv_get_aio_context(bs);
114
+ aio_context_acquire(old_context);
115
+
116
+ bdrv_set_aio_context(bs, new_context);
117
+
118
+ aio_context_release(old_context);
124
+}
119
+}
125
+
120
+
126
void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event)
121
QemuOptsList qemu_common_drive_opts = {
127
{
122
.name = "drive",
128
if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) {
123
.head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
129
diff --git a/block/file-posix.c b/block/file-posix.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/file-posix.c
132
+++ b/block/file-posix.c
133
@@ -XXX,XX +XXX,XX @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
134
return 0;
135
}
136
137
+static BlockStatsSpecificFile get_blockstats_specific_file(BlockDriverState *bs)
138
+{
139
+ BDRVRawState *s = bs->opaque;
140
+ return (BlockStatsSpecificFile) {
141
+ .discard_nb_ok = s->stats.discard_nb_ok,
142
+ .discard_nb_failed = s->stats.discard_nb_failed,
143
+ .discard_bytes_ok = s->stats.discard_bytes_ok,
144
+ };
145
+}
146
+
147
+static BlockStatsSpecific *raw_get_specific_stats(BlockDriverState *bs)
148
+{
149
+ BlockStatsSpecific *stats = g_new(BlockStatsSpecific, 1);
150
+
151
+ stats->driver = BLOCKDEV_DRIVER_FILE;
152
+ stats->u.file = get_blockstats_specific_file(bs);
153
+
154
+ return stats;
155
+}
156
+
157
+static BlockStatsSpecific *hdev_get_specific_stats(BlockDriverState *bs)
158
+{
159
+ BlockStatsSpecific *stats = g_new(BlockStatsSpecific, 1);
160
+
161
+ stats->driver = BLOCKDEV_DRIVER_HOST_DEVICE;
162
+ stats->u.host_device = get_blockstats_specific_file(bs);
163
+
164
+ return stats;
165
+}
166
+
167
static QemuOptsList raw_create_opts = {
168
.name = "raw-create-opts",
169
.head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
170
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
171
.bdrv_get_info = raw_get_info,
172
.bdrv_get_allocated_file_size
173
= raw_get_allocated_file_size,
174
+ .bdrv_get_specific_stats = raw_get_specific_stats,
175
.bdrv_check_perm = raw_check_perm,
176
.bdrv_set_perm = raw_set_perm,
177
.bdrv_abort_perm_update = raw_abort_perm_update,
178
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
179
.bdrv_get_info = raw_get_info,
180
.bdrv_get_allocated_file_size
181
= raw_get_allocated_file_size,
182
+ .bdrv_get_specific_stats = hdev_get_specific_stats,
183
.bdrv_check_perm = raw_check_perm,
184
.bdrv_set_perm = raw_set_perm,
185
.bdrv_abort_perm_update = raw_abort_perm_update,
186
diff --git a/block/qapi.c b/block/qapi.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/block/qapi.c
189
+++ b/block/qapi.c
190
@@ -XXX,XX +XXX,XX @@ static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
191
192
s->stats->wr_highest_offset = stat64_get(&bs->wr_highest_offset);
193
194
+ s->driver_specific = bdrv_get_specific_stats(bs);
195
+ if (s->driver_specific) {
196
+ s->has_driver_specific = true;
197
+ }
198
+
199
if (bs->file) {
200
s->has_parent = true;
201
s->parent = bdrv_query_bds_stats(bs->file->bs, blk_level);
202
--
124
--
203
2.21.0
125
2.14.3
204
126
205
127
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
QMP 'transaction' blockdev-snapshot-sync with multiple disks in an
2
IOThread is an untested code path. Several bugs have been found in
3
connection with this command. This patch adds a test case to prevent
4
future regressions.
2
5
3
Common interface for aio task loops. To be used for improving
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
performance of synchronous io loops in qcow2, block-stream,
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
copy-on-read, and may be other places.
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Message-id: 20171206144550.22295-10-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
tests/qemu-iotests/202 | 95 ++++++++++++++++++++++++++++++++++++++++++++++
13
tests/qemu-iotests/202.out | 11 ++++++
14
tests/qemu-iotests/group | 1 +
15
3 files changed, 107 insertions(+)
16
create mode 100755 tests/qemu-iotests/202
17
create mode 100644 tests/qemu-iotests/202.out
6
18
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
new file mode 100755
9
Message-id: 20190916175324.18478-3-vsementsov@virtuozzo.com
21
index XXXXXXX..XXXXXXX
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
--- /dev/null
11
---
23
+++ b/tests/qemu-iotests/202
12
block/Makefile.objs | 2 +
24
@@ -XXX,XX +XXX,XX @@
13
include/block/aio_task.h | 54 +++++++++++++++++
25
+#!/usr/bin/env python
14
block/aio_task.c | 124 +++++++++++++++++++++++++++++++++++++++
26
+#
15
3 files changed, 180 insertions(+)
27
+# Copyright (C) 2017 Red Hat, Inc.
16
create mode 100644 include/block/aio_task.h
28
+#
17
create mode 100644 block/aio_task.c
29
+# This program is free software; you can redistribute it and/or modify
18
30
+# it under the terms of the GNU General Public License as published by
19
diff --git a/block/Makefile.objs b/block/Makefile.objs
31
+# the Free Software Foundation; either version 2 of the License, or
20
index XXXXXXX..XXXXXXX 100644
32
+# (at your option) any later version.
21
--- a/block/Makefile.objs
33
+#
22
+++ b/block/Makefile.objs
34
+# This program is distributed in the hope that it will be useful,
23
@@ -XXX,XX +XXX,XX @@ block-obj-y += throttle.o copy-on-read.o
35
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
24
36
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
block-obj-y += crypto.o
37
+# GNU General Public License for more details.
26
38
+#
27
+block-obj-y += aio_task.o
39
+# You should have received a copy of the GNU General Public License
40
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
41
+#
42
+# Creator/Owner: Stefan Hajnoczi <stefanha@redhat.com>
43
+#
44
+# Check that QMP 'transaction' blockdev-snapshot-sync with multiple drives on a
45
+# single IOThread completes successfully. This particular command triggered a
46
+# hang due to recursive AioContext locking and BDRV_POLL_WHILE(). Protect
47
+# against regressions.
28
+
48
+
29
common-obj-y += stream.o
49
+import iotests
30
50
+
31
nfs.o-libs := $(LIBNFS_LIBS)
51
+iotests.verify_image_format(supported_fmts=['qcow2'])
32
diff --git a/include/block/aio_task.h b/include/block/aio_task.h
52
+iotests.verify_platform(['linux'])
53
+
54
+with iotests.FilePath('disk0.img') as disk0_img_path, \
55
+ iotests.FilePath('disk1.img') as disk1_img_path, \
56
+ iotests.FilePath('disk0-snap.img') as disk0_snap_img_path, \
57
+ iotests.FilePath('disk1-snap.img') as disk1_snap_img_path, \
58
+ iotests.VM() as vm:
59
+
60
+ img_size = '10M'
61
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk0_img_path, img_size)
62
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk1_img_path, img_size)
63
+
64
+ iotests.log('Launching VM...')
65
+ vm.launch()
66
+
67
+ iotests.log('Adding IOThread...')
68
+ iotests.log(vm.qmp('object-add',
69
+ qom_type='iothread',
70
+ id='iothread0'))
71
+
72
+ iotests.log('Adding blockdevs...')
73
+ iotests.log(vm.qmp('blockdev-add',
74
+ driver=iotests.imgfmt,
75
+ node_name='disk0',
76
+ file={
77
+ 'driver': 'file',
78
+ 'filename': disk0_img_path,
79
+ }))
80
+ iotests.log(vm.qmp('blockdev-add',
81
+ driver=iotests.imgfmt,
82
+ node_name='disk1',
83
+ file={
84
+ 'driver': 'file',
85
+ 'filename': disk1_img_path,
86
+ }))
87
+
88
+ iotests.log('Setting iothread...')
89
+ iotests.log(vm.qmp('x-blockdev-set-iothread',
90
+ node_name='disk0',
91
+ iothread='iothread0'))
92
+ iotests.log(vm.qmp('x-blockdev-set-iothread',
93
+ node_name='disk1',
94
+ iothread='iothread0'))
95
+
96
+ iotests.log('Creating external snapshots...')
97
+ iotests.log(vm.qmp(
98
+ 'transaction',
99
+ actions=[
100
+ {
101
+ 'data': {
102
+ 'node-name': 'disk0',
103
+ 'snapshot-file': disk0_snap_img_path,
104
+ 'snapshot-node-name': 'disk0-snap',
105
+ 'mode': 'absolute-paths',
106
+ 'format': iotests.imgfmt,
107
+ },
108
+ 'type': 'blockdev-snapshot-sync'
109
+ }, {
110
+ 'data': {
111
+ 'node-name': 'disk1',
112
+ 'snapshot-file': disk1_snap_img_path,
113
+ 'snapshot-node-name': 'disk1-snap',
114
+ 'mode': 'absolute-paths',
115
+ 'format': iotests.imgfmt
116
+ },
117
+ 'type': 'blockdev-snapshot-sync'
118
+ }
119
+ ]))
120
diff --git a/tests/qemu-iotests/202.out b/tests/qemu-iotests/202.out
33
new file mode 100644
121
new file mode 100644
34
index XXXXXXX..XXXXXXX
122
index XXXXXXX..XXXXXXX
35
--- /dev/null
123
--- /dev/null
36
+++ b/include/block/aio_task.h
124
+++ b/tests/qemu-iotests/202.out
37
@@ -XXX,XX +XXX,XX @@
125
@@ -XXX,XX +XXX,XX @@
38
+/*
126
+Launching VM...
39
+ * Aio tasks loops
127
+Adding IOThread...
40
+ *
128
+{u'return': {}}
41
+ * Copyright (c) 2019 Virtuozzo International GmbH.
129
+Adding blockdevs...
42
+ *
130
+{u'return': {}}
43
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
131
+{u'return': {}}
44
+ * of this software and associated documentation files (the "Software"), to deal
132
+Setting iothread...
45
+ * in the Software without restriction, including without limitation the rights
133
+{u'return': {}}
46
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
134
+{u'return': {}}
47
+ * copies of the Software, and to permit persons to whom the Software is
135
+Creating external snapshots...
48
+ * furnished to do so, subject to the following conditions:
136
+{u'return': {}}
49
+ *
137
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
50
+ * The above copyright notice and this permission notice shall be included in
138
index XXXXXXX..XXXXXXX 100644
51
+ * all copies or substantial portions of the Software.
139
--- a/tests/qemu-iotests/group
52
+ *
140
+++ b/tests/qemu-iotests/group
53
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
54
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
55
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
56
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
57
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
58
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
59
+ * THE SOFTWARE.
60
+ */
61
+
62
+#ifndef BLOCK_AIO_TASK_H
63
+#define BLOCK_AIO_TASK_H
64
+
65
+#include "qemu/coroutine.h"
66
+
67
+typedef struct AioTaskPool AioTaskPool;
68
+typedef struct AioTask AioTask;
69
+typedef int coroutine_fn (*AioTaskFunc)(AioTask *task);
70
+struct AioTask {
71
+ AioTaskPool *pool;
72
+ AioTaskFunc func;
73
+ int ret;
74
+};
75
+
76
+AioTaskPool *coroutine_fn aio_task_pool_new(int max_busy_tasks);
77
+void aio_task_pool_free(AioTaskPool *);
78
+
79
+/* error code of failed task or 0 if all is OK */
80
+int aio_task_pool_status(AioTaskPool *pool);
81
+
82
+bool aio_task_pool_empty(AioTaskPool *pool);
83
+
84
+/* User provides filled @task, however task->pool will be set automatically */
85
+void coroutine_fn aio_task_pool_start_task(AioTaskPool *pool, AioTask *task);
86
+
87
+void coroutine_fn aio_task_pool_wait_slot(AioTaskPool *pool);
88
+void coroutine_fn aio_task_pool_wait_one(AioTaskPool *pool);
89
+void coroutine_fn aio_task_pool_wait_all(AioTaskPool *pool);
90
+
91
+#endif /* BLOCK_AIO_TASK_H */
92
diff --git a/block/aio_task.c b/block/aio_task.c
93
new file mode 100644
94
index XXXXXXX..XXXXXXX
95
--- /dev/null
96
+++ b/block/aio_task.c
97
@@ -XXX,XX +XXX,XX @@
141
@@ -XXX,XX +XXX,XX @@
98
+/*
142
197 rw auto quick
99
+ * Aio tasks loops
143
198 rw auto
100
+ *
144
200 rw auto
101
+ * Copyright (c) 2019 Virtuozzo International GmbH.
145
+202 rw auto quick
102
+ *
103
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
104
+ * of this software and associated documentation files (the "Software"), to deal
105
+ * in the Software without restriction, including without limitation the rights
106
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107
+ * copies of the Software, and to permit persons to whom the Software is
108
+ * furnished to do so, subject to the following conditions:
109
+ *
110
+ * The above copyright notice and this permission notice shall be included in
111
+ * all copies or substantial portions of the Software.
112
+ *
113
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
114
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
115
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
116
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
117
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
118
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
119
+ * THE SOFTWARE.
120
+ */
121
+
122
+#include "qemu/osdep.h"
123
+#include "block/aio.h"
124
+#include "block/aio_task.h"
125
+
126
+struct AioTaskPool {
127
+ Coroutine *main_co;
128
+ int status;
129
+ int max_busy_tasks;
130
+ int busy_tasks;
131
+ bool waiting;
132
+};
133
+
134
+static void coroutine_fn aio_task_co(void *opaque)
135
+{
136
+ AioTask *task = opaque;
137
+ AioTaskPool *pool = task->pool;
138
+
139
+ assert(pool->busy_tasks < pool->max_busy_tasks);
140
+ pool->busy_tasks++;
141
+
142
+ task->ret = task->func(task);
143
+
144
+ pool->busy_tasks--;
145
+
146
+ if (task->ret < 0 && pool->status == 0) {
147
+ pool->status = task->ret;
148
+ }
149
+
150
+ g_free(task);
151
+
152
+ if (pool->waiting) {
153
+ pool->waiting = false;
154
+ aio_co_wake(pool->main_co);
155
+ }
156
+}
157
+
158
+void coroutine_fn aio_task_pool_wait_one(AioTaskPool *pool)
159
+{
160
+ assert(pool->busy_tasks > 0);
161
+ assert(qemu_coroutine_self() == pool->main_co);
162
+
163
+ pool->waiting = true;
164
+ qemu_coroutine_yield();
165
+
166
+ assert(!pool->waiting);
167
+ assert(pool->busy_tasks < pool->max_busy_tasks);
168
+}
169
+
170
+void coroutine_fn aio_task_pool_wait_slot(AioTaskPool *pool)
171
+{
172
+ if (pool->busy_tasks < pool->max_busy_tasks) {
173
+ return;
174
+ }
175
+
176
+ aio_task_pool_wait_one(pool);
177
+}
178
+
179
+void coroutine_fn aio_task_pool_wait_all(AioTaskPool *pool)
180
+{
181
+ while (pool->busy_tasks > 0) {
182
+ aio_task_pool_wait_one(pool);
183
+ }
184
+}
185
+
186
+void coroutine_fn aio_task_pool_start_task(AioTaskPool *pool, AioTask *task)
187
+{
188
+ aio_task_pool_wait_slot(pool);
189
+
190
+ task->pool = pool;
191
+ qemu_coroutine_enter(qemu_coroutine_create(aio_task_co, task));
192
+}
193
+
194
+AioTaskPool *coroutine_fn aio_task_pool_new(int max_busy_tasks)
195
+{
196
+ AioTaskPool *pool = g_new0(AioTaskPool, 1);
197
+
198
+ pool->main_co = qemu_coroutine_self();
199
+ pool->max_busy_tasks = max_busy_tasks;
200
+
201
+ return pool;
202
+}
203
+
204
+void aio_task_pool_free(AioTaskPool *pool)
205
+{
206
+ g_free(pool);
207
+}
208
+
209
+int aio_task_pool_status(AioTaskPool *pool)
210
+{
211
+ if (!pool) {
212
+ return 0; /* Sugar for lazy allocation of aio pool */
213
+ }
214
+
215
+ return pool->status;
216
+}
217
+
218
+bool aio_task_pool_empty(AioTaskPool *pool)
219
+{
220
+ return pool->busy_tasks == 0;
221
+}
222
--
146
--
223
2.21.0
147
2.14.3
224
148
225
149
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Similarly to previous commit, prepare for parallelizing write-loop
4
iterations.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-id: 20190916175324.18478-5-vsementsov@virtuozzo.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/qcow2.c | 154 +++++++++++++++++++++++++++++---------------------
12
1 file changed, 90 insertions(+), 64 deletions(-)
13
14
diff --git a/block/qcow2.c b/block/qcow2.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow2.c
17
+++ b/block/qcow2.c
18
@@ -XXX,XX +XXX,XX @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
19
return 0;
20
}
21
22
+/*
23
+ * qcow2_co_pwritev_task
24
+ * Called with s->lock unlocked
25
+ * l2meta - if not NULL, qcow2_co_pwritev_task() will consume it. Caller must
26
+ * not use it somehow after qcow2_co_pwritev_task() call
27
+ */
28
+static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
29
+ uint64_t file_cluster_offset,
30
+ uint64_t offset, uint64_t bytes,
31
+ QEMUIOVector *qiov,
32
+ uint64_t qiov_offset,
33
+ QCowL2Meta *l2meta)
34
+{
35
+ int ret;
36
+ BDRVQcow2State *s = bs->opaque;
37
+ void *crypt_buf = NULL;
38
+ int offset_in_cluster = offset_into_cluster(s, offset);
39
+ QEMUIOVector encrypted_qiov;
40
+
41
+ if (bs->encrypted) {
42
+ assert(s->crypto);
43
+ assert(bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
44
+ crypt_buf = qemu_try_blockalign(bs->file->bs, bytes);
45
+ if (crypt_buf == NULL) {
46
+ ret = -ENOMEM;
47
+ goto out_unlocked;
48
+ }
49
+ qemu_iovec_to_buf(qiov, qiov_offset, crypt_buf, bytes);
50
+
51
+ if (qcow2_co_encrypt(bs, file_cluster_offset + offset_in_cluster,
52
+ offset, crypt_buf, bytes) < 0)
53
+ {
54
+ ret = -EIO;
55
+ goto out_unlocked;
56
+ }
57
+
58
+ qemu_iovec_init_buf(&encrypted_qiov, crypt_buf, bytes);
59
+ qiov = &encrypted_qiov;
60
+ qiov_offset = 0;
61
+ }
62
+
63
+ /* Try to efficiently initialize the physical space with zeroes */
64
+ ret = handle_alloc_space(bs, l2meta);
65
+ if (ret < 0) {
66
+ goto out_unlocked;
67
+ }
68
+
69
+ /*
70
+ * If we need to do COW, check if it's possible to merge the
71
+ * writing of the guest data together with that of the COW regions.
72
+ * If it's not possible (or not necessary) then write the
73
+ * guest data now.
74
+ */
75
+ if (!merge_cow(offset, bytes, qiov, qiov_offset, l2meta)) {
76
+ BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
77
+ trace_qcow2_writev_data(qemu_coroutine_self(),
78
+ file_cluster_offset + offset_in_cluster);
79
+ ret = bdrv_co_pwritev_part(s->data_file,
80
+ file_cluster_offset + offset_in_cluster,
81
+ bytes, qiov, qiov_offset, 0);
82
+ if (ret < 0) {
83
+ goto out_unlocked;
84
+ }
85
+ }
86
+
87
+ qemu_co_mutex_lock(&s->lock);
88
+
89
+ ret = qcow2_handle_l2meta(bs, &l2meta, true);
90
+ goto out_locked;
91
+
92
+out_unlocked:
93
+ qemu_co_mutex_lock(&s->lock);
94
+
95
+out_locked:
96
+ qcow2_handle_l2meta(bs, &l2meta, false);
97
+ qemu_co_mutex_unlock(&s->lock);
98
+
99
+ qemu_vfree(crypt_buf);
100
+
101
+ return ret;
102
+}
103
+
104
static coroutine_fn int qcow2_co_pwritev_part(
105
BlockDriverState *bs, uint64_t offset, uint64_t bytes,
106
QEMUIOVector *qiov, size_t qiov_offset, int flags)
107
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
108
int ret;
109
unsigned int cur_bytes; /* number of sectors in current iteration */
110
uint64_t cluster_offset;
111
- QEMUIOVector encrypted_qiov;
112
- uint64_t bytes_done = 0;
113
- uint8_t *cluster_data = NULL;
114
QCowL2Meta *l2meta = NULL;
115
116
trace_qcow2_writev_start_req(qemu_coroutine_self(), offset, bytes);
117
118
- qemu_co_mutex_lock(&s->lock);
119
-
120
while (bytes != 0) {
121
122
l2meta = NULL;
123
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
124
- offset_in_cluster);
125
}
126
127
+ qemu_co_mutex_lock(&s->lock);
128
+
129
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
130
&cluster_offset, &l2meta);
131
if (ret < 0) {
132
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
133
134
qemu_co_mutex_unlock(&s->lock);
135
136
- if (bs->encrypted) {
137
- assert(s->crypto);
138
- if (!cluster_data) {
139
- cluster_data = qemu_try_blockalign(bs->file->bs,
140
- QCOW_MAX_CRYPT_CLUSTERS
141
- * s->cluster_size);
142
- if (cluster_data == NULL) {
143
- ret = -ENOMEM;
144
- goto out_unlocked;
145
- }
146
- }
147
-
148
- assert(cur_bytes <= QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
149
- qemu_iovec_to_buf(qiov, qiov_offset + bytes_done,
150
- cluster_data, cur_bytes);
151
-
152
- if (qcow2_co_encrypt(bs, cluster_offset + offset_in_cluster, offset,
153
- cluster_data, cur_bytes) < 0) {
154
- ret = -EIO;
155
- goto out_unlocked;
156
- }
157
-
158
- qemu_iovec_init_buf(&encrypted_qiov, cluster_data, cur_bytes);
159
- }
160
-
161
- /* Try to efficiently initialize the physical space with zeroes */
162
- ret = handle_alloc_space(bs, l2meta);
163
+ ret = qcow2_co_pwritev_task(bs, cluster_offset, offset, cur_bytes,
164
+ qiov, qiov_offset, l2meta);
165
+ l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */
166
if (ret < 0) {
167
- goto out_unlocked;
168
- }
169
-
170
- /* If we need to do COW, check if it's possible to merge the
171
- * writing of the guest data together with that of the COW regions.
172
- * If it's not possible (or not necessary) then write the
173
- * guest data now. */
174
- if (!merge_cow(offset, cur_bytes,
175
- bs->encrypted ? &encrypted_qiov : qiov,
176
- bs->encrypted ? 0 : qiov_offset + bytes_done, l2meta))
177
- {
178
- BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
179
- trace_qcow2_writev_data(qemu_coroutine_self(),
180
- cluster_offset + offset_in_cluster);
181
- ret = bdrv_co_pwritev_part(
182
- s->data_file, cluster_offset + offset_in_cluster, cur_bytes,
183
- bs->encrypted ? &encrypted_qiov : qiov,
184
- bs->encrypted ? 0 : qiov_offset + bytes_done, 0);
185
- if (ret < 0) {
186
- goto out_unlocked;
187
- }
188
- }
189
-
190
- qemu_co_mutex_lock(&s->lock);
191
-
192
- ret = qcow2_handle_l2meta(bs, &l2meta, true);
193
- if (ret) {
194
- goto out_locked;
195
+ goto fail_nometa;
196
}
197
198
bytes -= cur_bytes;
199
offset += cur_bytes;
200
- bytes_done += cur_bytes;
201
+ qiov_offset += cur_bytes;
202
trace_qcow2_writev_done_part(qemu_coroutine_self(), cur_bytes);
203
}
204
ret = 0;
205
- goto out_locked;
206
207
-out_unlocked:
208
qemu_co_mutex_lock(&s->lock);
209
210
out_locked:
211
@@ -XXX,XX +XXX,XX @@ out_locked:
212
213
qemu_co_mutex_unlock(&s->lock);
214
215
- qemu_vfree(cluster_data);
216
+fail_nometa:
217
trace_qcow2_writev_done_req(qemu_coroutine_self(), ret);
218
219
return ret;
220
--
221
2.21.0
222
223
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Of course, QEMU_ALIGN_UP is a typo, it should be QEMU_ALIGN_DOWN, as we
4
are trying to find aligned size which satisfy both source and target.
5
Also, don't ignore too small max_transfer. In this case seems safer to
6
disable copy_range.
7
8
Fixes: 9ded4a0114968e
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Message-id: 20190920142056.12778-2-vsementsov@virtuozzo.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/backup.c | 15 +++++++++++----
14
1 file changed, 11 insertions(+), 4 deletions(-)
15
16
diff --git a/block/backup.c b/block/backup.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/backup.c
19
+++ b/block/backup.c
20
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
21
job->cluster_size = cluster_size;
22
job->copy_bitmap = copy_bitmap;
23
copy_bitmap = NULL;
24
- job->use_copy_range = !compress; /* compression isn't supported for it */
25
job->copy_range_size = MIN_NON_ZERO(blk_get_max_transfer(job->common.blk),
26
blk_get_max_transfer(job->target));
27
- job->copy_range_size = MAX(job->cluster_size,
28
- QEMU_ALIGN_UP(job->copy_range_size,
29
- job->cluster_size));
30
+ job->copy_range_size = QEMU_ALIGN_DOWN(job->copy_range_size,
31
+ job->cluster_size);
32
+ /*
33
+ * Set use_copy_range, consider the following:
34
+ * 1. Compression is not supported for copy_range.
35
+ * 2. copy_range does not respect max_transfer (it's a TODO), so we factor
36
+ * that in here. If max_transfer is smaller than the job->cluster_size,
37
+ * we do not use copy_range (in that case it's zero after aligning down
38
+ * above).
39
+ */
40
+ job->use_copy_range = !compress && job->copy_range_size > 0;
41
42
/* Required permissions are already taken with target's blk_new() */
43
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
44
--
45
2.21.0
46
47
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We shouldn't try to copy bytes beyond EOF. Fix it.
4
5
Fixes: 9ded4a0114968e
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-id: 20190920142056.12778-3-vsementsov@virtuozzo.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/backup.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
diff --git a/block/backup.c b/block/backup.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/backup.c
18
+++ b/block/backup.c
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job,
20
21
assert(QEMU_IS_ALIGNED(job->copy_range_size, job->cluster_size));
22
assert(QEMU_IS_ALIGNED(start, job->cluster_size));
23
- nbytes = MIN(job->copy_range_size, end - start);
24
+ nbytes = MIN(job->copy_range_size, MIN(end, job->len) - start);
25
nr_clusters = DIV_ROUND_UP(nbytes, job->cluster_size);
26
bdrv_reset_dirty_bitmap(job->copy_bitmap, start,
27
job->cluster_size * nr_clusters);
28
--
29
2.21.0
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Message-id: 20190920142056.12778-5-vsementsov@virtuozzo.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
block/backup.c | 15 ++++++++++++---
9
1 file changed, 12 insertions(+), 3 deletions(-)
10
11
diff --git a/block/backup.c b/block/backup.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/backup.c
14
+++ b/block/backup.c
15
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
16
job->bitmap_mode = bitmap_mode;
17
18
/*
19
- * Set write flags:
20
- * 1. Detect image-fleecing (and similar) schemes
21
- * 2. Handle compression
22
+ * If source is in backing chain of target assume that target is going to be
23
+ * used for "image fleecing", i.e. it should represent a kind of snapshot of
24
+ * source at backup-start point in time. And target is going to be read by
25
+ * somebody (for example, used as NBD export) during backup job.
26
+ *
27
+ * In this case, we need to add BDRV_REQ_SERIALISING write flag to avoid
28
+ * intersection of backup writes and third party reads from target,
29
+ * otherwise reading from target we may occasionally read already updated by
30
+ * guest data.
31
+ *
32
+ * For more information see commit f8d59dfb40bb and test
33
+ * tests/qemu-iotests/222
34
*/
35
job->write_flags =
36
(bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
37
--
38
2.21.0
39
40
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
From: Mark Kanda <mark.kanda@oracle.com>
2
2
3
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
3
Depending on the configuration, it can be beneficial to adjust the virtio-blk
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
queue size to something other than the current default of 128. Add a new
5
Message-id: 20190923121737.83281-8-anton.nefedov@virtuozzo.com
5
property to make the queue size configurable.
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
7
Signed-off-by: Mark Kanda <mark.kanda@oracle.com>
8
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
9
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
10
Reviewed-by: Ameya More <ameya.more@oracle.com>
11
Message-id: 52e6d742811f10dbd16e996e86cf375b9577c187.1513005190.git.mark.kanda@oracle.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
13
---
8
hw/scsi/scsi-disk.c | 12 +++++++++++-
14
include/hw/virtio/virtio-blk.h | 1 +
9
1 file changed, 11 insertions(+), 1 deletion(-)
15
hw/block/virtio-blk.c | 10 +++++++++-
16
2 files changed, 10 insertions(+), 1 deletion(-)
10
17
11
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
18
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/scsi/scsi-disk.c
20
--- a/include/hw/virtio/virtio-blk.h
14
+++ b/hw/scsi/scsi-disk.c
21
+++ b/include/hw/virtio/virtio-blk.h
15
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
22
@@ -XXX,XX +XXX,XX @@ struct VirtIOBlkConf
16
r->sector_count = (ldl_be_p(&data->inbuf[8]) & 0xffffffffULL)
23
uint32_t config_wce;
17
* (s->qdev.blocksize / BDRV_SECTOR_SIZE);
24
uint32_t request_merging;
18
if (!check_lba_range(s, r->sector, r->sector_count)) {
25
uint16_t num_queues;
19
+ block_acct_invalid(blk_get_stats(s->qdev.conf.blk),
26
+ uint16_t queue_size;
20
+ BLOCK_ACCT_UNMAP);
27
};
21
scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
28
22
goto done;
29
struct VirtIOBlockDataPlane;
23
}
30
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
24
31
index XXXXXXX..XXXXXXX 100644
25
+ block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
32
--- a/hw/block/virtio-blk.c
26
+ r->sector_count * BDRV_SECTOR_SIZE,
33
+++ b/hw/block/virtio-blk.c
27
+ BLOCK_ACCT_UNMAP);
34
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
28
+
35
error_setg(errp, "num-queues property must be larger than 0");
29
r->req.aiocb = blk_aio_pdiscard(s->qdev.conf.blk,
30
r->sector * BDRV_SECTOR_SIZE,
31
r->sector_count * BDRV_SECTOR_SIZE,
32
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete(void *opaque, int ret)
33
r->req.aiocb = NULL;
34
35
aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
36
- if (scsi_disk_req_check_error(r, ret, false)) {
37
+ if (scsi_disk_req_check_error(r, ret, true)) {
38
scsi_req_unref(&r->req);
39
g_free(data);
40
} else {
41
+ block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
42
scsi_unmap_complete_noio(data, ret);
43
}
44
aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
45
@@ -XXX,XX +XXX,XX @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
46
}
47
48
if (blk_is_read_only(s->qdev.conf.blk)) {
49
+ block_acct_invalid(blk_get_stats(s->qdev.conf.blk), BLOCK_ACCT_UNMAP);
50
scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
51
return;
36
return;
52
}
37
}
53
@@ -XXX,XX +XXX,XX @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
38
+ if (!is_power_of_2(conf->queue_size) ||
54
return;
39
+ conf->queue_size > VIRTQUEUE_MAX_SIZE) {
55
40
+ error_setg(errp, "invalid queue-size property (%" PRIu16 "), "
56
invalid_param_len:
41
+ "must be a power of 2 (max %d)",
57
+ block_acct_invalid(blk_get_stats(s->qdev.conf.blk), BLOCK_ACCT_UNMAP);
42
+ conf->queue_size, VIRTQUEUE_MAX_SIZE);
58
scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN));
43
+ return;
59
return;
44
+ }
60
45
61
invalid_field:
46
blkconf_serial(&conf->conf, &conf->serial);
62
+ block_acct_invalid(blk_get_stats(s->qdev.conf.blk), BLOCK_ACCT_UNMAP);
47
if (!blkconf_apply_backend_options(&conf->conf,
63
scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
48
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
64
}
49
s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1;
65
50
51
for (i = 0; i < conf->num_queues; i++) {
52
- virtio_add_queue(vdev, 128, virtio_blk_handle_output);
53
+ virtio_add_queue(vdev, conf->queue_size, virtio_blk_handle_output);
54
}
55
virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err);
56
if (err != NULL) {
57
@@ -XXX,XX +XXX,XX @@ static Property virtio_blk_properties[] = {
58
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
59
true),
60
DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1),
61
+ DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 128),
62
DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
63
IOThread *),
64
DEFINE_PROP_END_OF_LIST(),
66
--
65
--
67
2.21.0
66
2.14.3
68
67
69
68
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
From: Mark Kanda <mark.kanda@oracle.com>
2
2
3
Each block_acct_done/failed call is designed to correspond to a
3
virtio-blk logical block size should never be larger than physical block
4
previous block_acct_start call, which initializes the stats cookie.
4
size because it doesn't make sense to have such configurations. QEMU doesn't
5
However sometimes it is not the case, e.g. some error paths might
5
have a way to effectively express this condition; the best it can do is
6
report the same cookie twice because it is hard to accurately track if
6
report the physical block exponent as 0 - indicating the logical block size
7
the cookie was reported yet or not.
7
equals the physical block size.
8
8
9
This patch cleans the cookie after report.
9
This is identical to commit 3da023b5827543ee4c022986ea2ad9d1274410b2
10
(Note: block_acct_failed/done without a previous block_acct_start at
10
but applied to virtio-blk (instead of virtio-scsi).
11
all should be avoided. Uninitialized cookie might hold a garbage value
12
and there is still "< BLOCK_MAX_IOTYPE" assertion for that)
13
11
14
It will be particularly useful in ide code where it's hard to
12
Signed-off-by: Mark Kanda <mark.kanda@oracle.com>
15
keep track whether the request done its accounting or not: in the
13
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
16
following patch of the series, trim requests will do the accounting
14
Reviewed-by: Ameya More <ameya.more@oracle.com>
17
separately.
15
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Message-id: 773169891f9f2deb4cb7c4ef2655580dbe24c1d1.1513005190.git.mark.kanda@oracle.com
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
---
20
hw/block/virtio-blk.c | 7 +++++++
21
1 file changed, 7 insertions(+)
18
22
19
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
23
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
20
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
21
Message-id: 20190923121737.83281-4-anton.nefedov@virtuozzo.com
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
include/block/accounting.h | 1 +
25
block/accounting.c | 6 ++++++
26
2 files changed, 7 insertions(+)
27
28
diff --git a/include/block/accounting.h b/include/block/accounting.h
29
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/accounting.h
25
--- a/hw/block/virtio-blk.c
31
+++ b/include/block/accounting.h
26
+++ b/hw/block/virtio-blk.c
32
@@ -XXX,XX +XXX,XX @@ typedef struct BlockAcctTimedStats BlockAcctTimedStats;
27
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
33
typedef struct BlockAcctStats BlockAcctStats;
28
34
29
blkconf_blocksizes(&conf->conf);
35
enum BlockAcctType {
30
36
+ BLOCK_ACCT_NONE = 0,
31
+ if (conf->conf.logical_block_size >
37
BLOCK_ACCT_READ,
32
+ conf->conf.physical_block_size) {
38
BLOCK_ACCT_WRITE,
33
+ error_setg(errp,
39
BLOCK_ACCT_FLUSH,
34
+ "logical_block_size > physical_block_size not supported");
40
diff --git a/block/accounting.c b/block/accounting.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block/accounting.c
43
+++ b/block/accounting.c
44
@@ -XXX,XX +XXX,XX @@ static void block_account_one_io(BlockAcctStats *stats, BlockAcctCookie *cookie,
45
46
assert(cookie->type < BLOCK_MAX_IOTYPE);
47
48
+ if (cookie->type == BLOCK_ACCT_NONE) {
49
+ return;
35
+ return;
50
+ }
36
+ }
51
+
37
+
52
qemu_mutex_lock(&stats->lock);
38
virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
53
39
sizeof(struct virtio_blk_config));
54
if (failed) {
40
55
@@ -XXX,XX +XXX,XX @@ static void block_account_one_io(BlockAcctStats *stats, BlockAcctCookie *cookie,
56
}
57
58
qemu_mutex_unlock(&stats->lock);
59
+
60
+ cookie->type = BLOCK_ACCT_NONE;
61
}
62
63
void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie)
64
--
41
--
65
2.21.0
42
2.14.3
66
43
67
44
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Teach bdrv_debug_breakpoint and bdrv_debug_remove_breakpoint skip
3
BDRV_POLL_WHILE() does not support recursive AioContext locking. It
4
filters with backing. This is needed to implement and use in backup job
4
only releases the AioContext lock once regardless of how many times the
5
it's own backup_top filter driver (like mirror already has one), and
5
caller has acquired it. This results in a hang since the IOThread does
6
without this improvement, breakpoint removal will fail at least in 55
6
not make progress while the AioContext is still locked.
7
iotest.
8
7
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
The following steps trigger the hang:
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
11
Message-id: 20190920142056.12778-9-vsementsov@virtuozzo.com
10
$ qemu-system-x86_64 -M accel=kvm -m 1G -cpu host \
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
-object iothread,id=iothread0 \
12
-device virtio-scsi-pci,iothread=iothread0 \
13
-drive if=none,id=drive0,file=test.img,format=raw \
14
-device scsi-hd,drive=drive0 \
15
-drive if=none,id=drive1,file=test.img,format=raw \
16
-device scsi-hd,drive=drive1
17
$ qemu-system-x86_64 ...same options... \
18
-incoming tcp::1234
19
(qemu) migrate tcp:127.0.0.1:1234
20
...hang...
21
22
Tested-by: Stefan Hajnoczi <stefanha@redhat.com>
23
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
24
Reviewed-by: Eric Blake <eblake@redhat.com>
25
Message-id: 20171207201320.19284-2-stefanha@redhat.com
26
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
27
---
14
block.c | 34 ++++++++++++++++++++++++++--------
28
block.c | 14 +++++++++++---
15
1 file changed, 26 insertions(+), 8 deletions(-)
29
1 file changed, 11 insertions(+), 3 deletions(-)
16
30
17
diff --git a/block.c b/block.c
31
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
33
--- a/block.c
20
+++ b/block.c
34
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event)
35
@@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void)
22
bs->drv->bdrv_debug_event(bs, event);
36
BdrvNextIterator it;
37
int ret = 0;
38
int pass;
39
+ GSList *aio_ctxs = NULL, *ctx;
40
41
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
42
- aio_context_acquire(bdrv_get_aio_context(bs));
43
+ AioContext *aio_context = bdrv_get_aio_context(bs);
44
+
45
+ if (!g_slist_find(aio_ctxs, aio_context)) {
46
+ aio_ctxs = g_slist_prepend(aio_ctxs, aio_context);
47
+ aio_context_acquire(aio_context);
48
+ }
49
}
50
51
/* We do two passes of inactivation. The first pass calls to drivers'
52
@@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void)
53
}
54
55
out:
56
- for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
57
- aio_context_release(bdrv_get_aio_context(bs));
58
+ for (ctx = aio_ctxs; ctx != NULL; ctx = ctx->next) {
59
+ AioContext *aio_context = ctx->data;
60
+ aio_context_release(aio_context);
61
}
62
+ g_slist_free(aio_ctxs);
63
64
return ret;
23
}
65
}
24
25
-int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
26
- const char *tag)
27
+static BlockDriverState *bdrv_find_debug_node(BlockDriverState *bs)
28
{
29
while (bs && bs->drv && !bs->drv->bdrv_debug_breakpoint) {
30
- bs = bs->file ? bs->file->bs : NULL;
31
+ if (bs->file) {
32
+ bs = bs->file->bs;
33
+ continue;
34
+ }
35
+
36
+ if (bs->drv->is_filter && bs->backing) {
37
+ bs = bs->backing->bs;
38
+ continue;
39
+ }
40
+
41
+ break;
42
}
43
44
if (bs && bs->drv && bs->drv->bdrv_debug_breakpoint) {
45
+ assert(bs->drv->bdrv_debug_remove_breakpoint);
46
+ return bs;
47
+ }
48
+
49
+ return NULL;
50
+}
51
+
52
+int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
53
+ const char *tag)
54
+{
55
+ bs = bdrv_find_debug_node(bs);
56
+ if (bs) {
57
return bs->drv->bdrv_debug_breakpoint(bs, event, tag);
58
}
59
60
@@ -XXX,XX +XXX,XX @@ int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
61
62
int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag)
63
{
64
- while (bs && bs->drv && !bs->drv->bdrv_debug_remove_breakpoint) {
65
- bs = bs->file ? bs->file->bs : NULL;
66
- }
67
-
68
- if (bs && bs->drv && bs->drv->bdrv_debug_remove_breakpoint) {
69
+ bs = bdrv_find_debug_node(bs);
70
+ if (bs) {
71
return bs->drv->bdrv_debug_remove_breakpoint(bs, tag);
72
}
73
74
--
66
--
75
2.21.0
67
2.14.3
76
68
77
69
diff view generated by jsdifflib
1
From: Maxim Levitsky <mlevitsk@redhat.com>
1
See the patch for why nested AioContext locking is no longer allowed.
2
2
3
Fixes commit job / qemu-img commit, when
3
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
commiting qcow2 file which is based on nbd export.
4
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Message-id: 20171207201320.19284-3-stefanha@redhat.com
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
8
docs/devel/multiple-iothreads.txt | 7 ++++---
9
1 file changed, 4 insertions(+), 3 deletions(-)
5
10
6
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1718727
11
diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
7
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
8
Message-id: 20190930213820.29777-2-mlevitsk@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/nbd.c | 15 +++++++++++++++
12
1 file changed, 15 insertions(+)
13
14
diff --git a/block/nbd.c b/block/nbd.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/block/nbd.c
13
--- a/docs/devel/multiple-iothreads.txt
17
+++ b/block/nbd.c
14
+++ b/docs/devel/multiple-iothreads.txt
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_client_co_block_status(
15
@@ -XXX,XX +XXX,XX @@
19
BDRV_BLOCK_OFFSET_VALID;
16
-Copyright (c) 2014 Red Hat Inc.
20
}
17
+Copyright (c) 2014-2017 Red Hat Inc.
21
18
22
+static int nbd_client_reopen_prepare(BDRVReopenState *state,
19
This work is licensed under the terms of the GNU GPL, version 2 or later. See
23
+ BlockReopenQueue *queue, Error **errp)
20
the COPYING file in the top-level directory.
24
+{
21
@@ -XXX,XX +XXX,XX @@ aio_context_acquire()/aio_context_release() for mutual exclusion. Once the
25
+ BDRVNBDState *s = (BDRVNBDState *)state->bs->opaque;
22
context is acquired no other thread can access it or run event loop iterations
26
+
23
in this AioContext.
27
+ if ((state->flags & BDRV_O_RDWR) && (s->info.flags & NBD_FLAG_READ_ONLY)) {
24
28
+ error_setg(errp, "Can't reopen read-only NBD mount as read/write");
25
-aio_context_acquire()/aio_context_release() calls may be nested. This
29
+ return -EACCES;
26
-means you can call them if you're not sure whether #2 applies.
30
+ }
27
+Legacy code sometimes nests aio_context_acquire()/aio_context_release() calls.
31
+ return 0;
28
+Do not use nesting anymore, it is incompatible with the BDRV_POLL_WHILE() macro
32
+}
29
+used in the block layer and can lead to hangs.
33
+
30
34
static void nbd_client_close(BlockDriverState *bs)
31
There is currently no lock ordering rule if a thread needs to acquire multiple
35
{
32
AioContexts simultaneously. Therefore, it is only safe for code holding the
36
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
37
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
38
.instance_size = sizeof(BDRVNBDState),
39
.bdrv_parse_filename = nbd_parse_filename,
40
.bdrv_file_open = nbd_open,
41
+ .bdrv_reopen_prepare = nbd_client_reopen_prepare,
42
.bdrv_co_preadv = nbd_client_co_preadv,
43
.bdrv_co_pwritev = nbd_client_co_pwritev,
44
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
45
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
46
.instance_size = sizeof(BDRVNBDState),
47
.bdrv_parse_filename = nbd_parse_filename,
48
.bdrv_file_open = nbd_open,
49
+ .bdrv_reopen_prepare = nbd_client_reopen_prepare,
50
.bdrv_co_preadv = nbd_client_co_preadv,
51
.bdrv_co_pwritev = nbd_client_co_pwritev,
52
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
53
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
54
.instance_size = sizeof(BDRVNBDState),
55
.bdrv_parse_filename = nbd_parse_filename,
56
.bdrv_file_open = nbd_open,
57
+ .bdrv_reopen_prepare = nbd_client_reopen_prepare,
58
.bdrv_co_preadv = nbd_client_co_preadv,
59
.bdrv_co_pwritev = nbd_client_co_pwritev,
60
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
61
--
33
--
62
2.21.0
34
2.14.3
63
35
64
36
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
When a node is already associated with a BlockBackend the
2
x-blockdev-set-iothread command refuses to set the IOThread. This is to
3
prevent accidentally changing the IOThread when the nodes are in use.
2
4
3
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
5
When the nodes are created with -drive they automatically get a
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
BlockBackend. In that case we know nothing is using them yet and it's
5
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
safe to set the IOThread. Add a force boolean to override the check.
8
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Message-id: 20190923121737.83281-3-anton.nefedov@virtuozzo.com
11
Message-id: 20171207201320.19284-4-stefanha@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
13
---
10
qapi/block-core.json | 29 +++++++++++++++++++++++------
14
qapi/block-core.json | 6 +++++-
11
include/block/accounting.h | 1 +
15
blockdev.c | 11 ++++++-----
12
block/qapi.c | 6 ++++++
16
2 files changed, 11 insertions(+), 6 deletions(-)
13
tests/qemu-iotests/227.out | 18 ++++++++++++++++++
14
4 files changed, 48 insertions(+), 6 deletions(-)
15
17
16
diff --git a/qapi/block-core.json b/qapi/block-core.json
18
diff --git a/qapi/block-core.json b/qapi/block-core.json
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/qapi/block-core.json
20
--- a/qapi/block-core.json
19
+++ b/qapi/block-core.json
21
+++ b/qapi/block-core.json
20
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
21
#
23
#
22
# @wr_bytes: The number of bytes written by the device.
24
# @iothread: the name of the IOThread object or null for the main loop
23
#
25
#
24
+# @unmap_bytes: The number of bytes unmapped by the device (Since 4.2)
26
+# @force: true if the node and its children should be moved when a BlockBackend
27
+# is already attached
25
+#
28
+#
26
# @rd_operations: The number of read operations performed by the device.
29
# Note: this command is experimental and intended for test cases that need
27
#
30
# control over IOThreads only.
28
# @wr_operations: The number of write operations performed by the device.
29
@@ -XXX,XX +XXX,XX @@
30
# @flush_operations: The number of cache flush operations performed by the
31
# device (since 0.15.0)
32
#
33
+# @unmap_operations: The number of unmap operations performed by the device
34
+# (Since 4.2)
35
+#
36
# @rd_total_time_ns: Total time spent on reads in nanoseconds (since 0.15.0).
37
#
38
# @wr_total_time_ns: Total time spent on writes in nanoseconds (since 0.15.0).
39
@@ -XXX,XX +XXX,XX @@
40
# @flush_total_time_ns: Total time spent on cache flushes in nanoseconds
41
# (since 0.15.0).
42
#
43
+# @unmap_total_time_ns: Total time spent on unmap operations in nanoseconds
44
+# (Since 4.2)
45
+#
46
# @wr_highest_offset: The offset after the greatest byte written to the
47
# device. The intended use of this information is for
48
# growable sparse files (like qcow2) that are used on top
49
@@ -XXX,XX +XXX,XX @@
50
# @wr_merged: Number of write requests that have been merged into another
51
# request (Since 2.3).
52
#
53
+# @unmap_merged: Number of unmap requests that have been merged into another
54
+# request (Since 4.2)
55
+#
56
# @idle_time_ns: Time since the last I/O operation, in
57
# nanoseconds. If the field is absent it means that
58
# there haven't been any operations yet (Since 2.5).
59
@@ -XXX,XX +XXX,XX @@
60
# @failed_flush_operations: The number of failed flush operations
61
# performed by the device (Since 2.5)
62
#
63
+# @failed_unmap_operations: The number of failed unmap operations performed
64
+# by the device (Since 4.2)
65
+#
66
# @invalid_rd_operations: The number of invalid read operations
67
# performed by the device (Since 2.5)
68
#
31
#
69
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@
70
# @invalid_flush_operations: The number of invalid flush operations
71
# performed by the device (Since 2.5)
72
#
73
+# @invalid_unmap_operations: The number of invalid unmap operations performed
74
+# by the device (Since 4.2)
75
+#
76
# @account_invalid: Whether invalid operations are included in the
77
# last access statistics (Since 2.5)
78
#
79
@@ -XXX,XX +XXX,XX @@
80
# Since: 0.14.0
81
##
33
##
82
{ 'struct': 'BlockDeviceStats',
34
{ 'command': 'x-blockdev-set-iothread',
83
- 'data': {'rd_bytes': 'int', 'wr_bytes': 'int',
35
'data' : { 'node-name': 'str',
84
+ 'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'unmap_bytes' : 'int',
36
- 'iothread': 'StrOrNull' } }
85
'rd_operations': 'int', 'wr_operations': 'int',
37
+ 'iothread': 'StrOrNull',
86
- 'flush_operations': 'int',
38
+ '*force': 'bool' } }
87
+ 'flush_operations': 'int', 'unmap_operations': 'int',
39
diff --git a/blockdev.c b/blockdev.c
88
'rd_total_time_ns': 'int', 'wr_total_time_ns': 'int',
89
- 'flush_total_time_ns': 'int',
90
+ 'flush_total_time_ns': 'int', 'unmap_total_time_ns': 'int',
91
'wr_highest_offset': 'int',
92
- 'rd_merged': 'int', 'wr_merged': 'int',
93
+ 'rd_merged': 'int', 'wr_merged': 'int', 'unmap_merged': 'int',
94
'*idle_time_ns': 'int',
95
'failed_rd_operations': 'int', 'failed_wr_operations': 'int',
96
- 'failed_flush_operations': 'int',
97
+ 'failed_flush_operations': 'int', 'failed_unmap_operations': 'int',
98
'invalid_rd_operations': 'int', 'invalid_wr_operations': 'int',
99
- 'invalid_flush_operations': 'int',
100
+ 'invalid_flush_operations': 'int', 'invalid_unmap_operations': 'int',
101
'account_invalid': 'bool', 'account_failed': 'bool',
102
'timed_stats': ['BlockDeviceTimedStats'],
103
'*rd_latency_histogram': 'BlockLatencyHistogramInfo',
104
diff --git a/include/block/accounting.h b/include/block/accounting.h
105
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
106
--- a/include/block/accounting.h
41
--- a/blockdev.c
107
+++ b/include/block/accounting.h
42
+++ b/blockdev.c
108
@@ -XXX,XX +XXX,XX @@ enum BlockAcctType {
43
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
109
BLOCK_ACCT_READ,
44
}
110
BLOCK_ACCT_WRITE,
45
111
BLOCK_ACCT_FLUSH,
46
void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
112
+ BLOCK_ACCT_UNMAP,
47
- Error **errp)
113
BLOCK_MAX_IOTYPE,
48
+ bool has_force, bool force, Error **errp)
114
};
49
{
115
50
AioContext *old_context;
116
diff --git a/block/qapi.c b/block/qapi.c
51
AioContext *new_context;
117
index XXXXXXX..XXXXXXX 100644
52
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
118
--- a/block/qapi.c
53
return;
119
+++ b/block/qapi.c
54
}
120
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
55
121
56
- /* If we want to allow more extreme test scenarios this guard could be
122
ds->rd_bytes = stats->nr_bytes[BLOCK_ACCT_READ];
57
- * removed. For now it protects against accidents. */
123
ds->wr_bytes = stats->nr_bytes[BLOCK_ACCT_WRITE];
58
- if (bdrv_has_blk(bs)) {
124
+ ds->unmap_bytes = stats->nr_bytes[BLOCK_ACCT_UNMAP];
59
- error_setg(errp, "Node %s is in use", node_name);
125
ds->rd_operations = stats->nr_ops[BLOCK_ACCT_READ];
60
+ /* Protects against accidents. */
126
ds->wr_operations = stats->nr_ops[BLOCK_ACCT_WRITE];
61
+ if (!(has_force && force) && bdrv_has_blk(bs)) {
127
+ ds->unmap_operations = stats->nr_ops[BLOCK_ACCT_UNMAP];
62
+ error_setg(errp, "Node %s is associated with a BlockBackend and could "
128
63
+ "be in use (use force=true to override this check)",
129
ds->failed_rd_operations = stats->failed_ops[BLOCK_ACCT_READ];
64
+ node_name);
130
ds->failed_wr_operations = stats->failed_ops[BLOCK_ACCT_WRITE];
65
return;
131
ds->failed_flush_operations = stats->failed_ops[BLOCK_ACCT_FLUSH];
66
}
132
+ ds->failed_unmap_operations = stats->failed_ops[BLOCK_ACCT_UNMAP];
67
133
134
ds->invalid_rd_operations = stats->invalid_ops[BLOCK_ACCT_READ];
135
ds->invalid_wr_operations = stats->invalid_ops[BLOCK_ACCT_WRITE];
136
ds->invalid_flush_operations =
137
stats->invalid_ops[BLOCK_ACCT_FLUSH];
138
+ ds->invalid_unmap_operations = stats->invalid_ops[BLOCK_ACCT_UNMAP];
139
140
ds->rd_merged = stats->merged[BLOCK_ACCT_READ];
141
ds->wr_merged = stats->merged[BLOCK_ACCT_WRITE];
142
+ ds->unmap_merged = stats->merged[BLOCK_ACCT_UNMAP];
143
ds->flush_operations = stats->nr_ops[BLOCK_ACCT_FLUSH];
144
ds->wr_total_time_ns = stats->total_time_ns[BLOCK_ACCT_WRITE];
145
ds->rd_total_time_ns = stats->total_time_ns[BLOCK_ACCT_READ];
146
ds->flush_total_time_ns = stats->total_time_ns[BLOCK_ACCT_FLUSH];
147
+ ds->unmap_total_time_ns = stats->total_time_ns[BLOCK_ACCT_UNMAP];
148
149
ds->has_idle_time_ns = stats->last_access_time_ns > 0;
150
if (ds->has_idle_time_ns) {
151
diff --git a/tests/qemu-iotests/227.out b/tests/qemu-iotests/227.out
152
index XXXXXXX..XXXXXXX 100644
153
--- a/tests/qemu-iotests/227.out
154
+++ b/tests/qemu-iotests/227.out
155
@@ -XXX,XX +XXX,XX @@ Testing: -drive driver=null-co,read-zeroes=on,if=virtio
156
{
157
"device": "virtio0",
158
"stats": {
159
+ "unmap_operations": 0,
160
+ "unmap_merged": 0,
161
"flush_total_time_ns": 0,
162
"wr_highest_offset": 0,
163
"wr_total_time_ns": 0,
164
@@ -XXX,XX +XXX,XX @@ Testing: -drive driver=null-co,read-zeroes=on,if=virtio
165
"wr_bytes": 0,
166
"timed_stats": [
167
],
168
+ "failed_unmap_operations": 0,
169
"failed_flush_operations": 0,
170
"account_invalid": true,
171
"rd_total_time_ns": 0,
172
+ "invalid_unmap_operations": 0,
173
"flush_operations": 0,
174
"wr_operations": 0,
175
+ "unmap_bytes": 0,
176
"rd_merged": 0,
177
"rd_bytes": 0,
178
+ "unmap_total_time_ns": 0,
179
"invalid_flush_operations": 0,
180
"account_failed": true,
181
"rd_operations": 0,
182
@@ -XXX,XX +XXX,XX @@ Testing: -drive driver=null-co,if=none
183
{
184
"device": "none0",
185
"stats": {
186
+ "unmap_operations": 0,
187
+ "unmap_merged": 0,
188
"flush_total_time_ns": 0,
189
"wr_highest_offset": 0,
190
"wr_total_time_ns": 0,
191
@@ -XXX,XX +XXX,XX @@ Testing: -drive driver=null-co,if=none
192
"wr_bytes": 0,
193
"timed_stats": [
194
],
195
+ "failed_unmap_operations": 0,
196
"failed_flush_operations": 0,
197
"account_invalid": true,
198
"rd_total_time_ns": 0,
199
+ "invalid_unmap_operations": 0,
200
"flush_operations": 0,
201
"wr_operations": 0,
202
+ "unmap_bytes": 0,
203
"rd_merged": 0,
204
"rd_bytes": 0,
205
+ "unmap_total_time_ns": 0,
206
"invalid_flush_operations": 0,
207
"account_failed": true,
208
"rd_operations": 0,
209
@@ -XXX,XX +XXX,XX @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
210
{
211
"device": "",
212
"stats": {
213
+ "unmap_operations": 0,
214
+ "unmap_merged": 0,
215
"flush_total_time_ns": 0,
216
"wr_highest_offset": 0,
217
"wr_total_time_ns": 0,
218
@@ -XXX,XX +XXX,XX @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
219
"wr_bytes": 0,
220
"timed_stats": [
221
],
222
+ "failed_unmap_operations": 0,
223
"failed_flush_operations": 0,
224
"account_invalid": false,
225
"rd_total_time_ns": 0,
226
+ "invalid_unmap_operations": 0,
227
"flush_operations": 0,
228
"wr_operations": 0,
229
+ "unmap_bytes": 0,
230
"rd_merged": 0,
231
"rd_bytes": 0,
232
+ "unmap_total_time_ns": 0,
233
"invalid_flush_operations": 0,
234
"account_failed": false,
235
"rd_operations": 0,
236
--
68
--
237
2.21.0
69
2.14.3
238
70
239
71
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The VM.add_object() method can be used to add IOThreads or memory
2
backend objects.
2
3
3
After backup-top filter appearing it's not possible to see dirty
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
bitmaps in top node, so use node-name instead.
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-id: 20171207201320.19284-5-stefanha@redhat.com
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
tests/qemu-iotests/iotests.py | 5 +++++
10
1 file changed, 5 insertions(+)
5
11
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-id: 20190920142056.12778-10-vsementsov@virtuozzo.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/124 | 83 ++++----
12
tests/qemu-iotests/257 | 49 ++---
13
tests/qemu-iotests/257.out | 364 +++++++++++++---------------------
14
tests/qemu-iotests/iotests.py | 27 +++
15
4 files changed, 219 insertions(+), 304 deletions(-)
16
17
diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/124
20
+++ b/tests/qemu-iotests/124
21
@@ -XXX,XX +XXX,XX @@ class TestIncrementalBackupBase(iotests.QMPTestCase):
22
# Create a base image with a distinctive patterning
23
drive0 = self.add_node('drive0')
24
self.img_create(drive0['file'], drive0['fmt'])
25
- self.vm.add_drive(drive0['file'])
26
+ self.vm.add_drive(drive0['file'], opts='node-name=node0')
27
self.write_default_pattern(drive0['file'])
28
self.vm.launch()
29
30
@@ -XXX,XX +XXX,XX @@ class TestIncrementalBackup(TestIncrementalBackupBase):
31
('0xfe', '16M', '256k'),
32
('0x64', '32736k', '64k')))
33
# Check the dirty bitmap stats
34
- result = self.vm.qmp('query-block')
35
- self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/name', 'bitmap0')
36
- self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/count', 458752)
37
- self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/granularity', 65536)
38
- self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/status', 'active')
39
- self.assert_qmp(result, 'return[0]/dirty-bitmaps[0]/persistent', False)
40
+ self.assertTrue(self.vm.check_bitmap_status(
41
+ 'node0', bitmap0.name, {
42
+ 'name': 'bitmap0',
43
+ 'count': 458752,
44
+ 'granularity': 65536,
45
+ 'status': 'active',
46
+ 'persistent': False
47
+ }))
48
49
# Prepare a cluster_size=128k backup target without a backing file.
50
(target, _) = bitmap0.new_target()
51
@@ -XXX,XX +XXX,XX @@ class TestIncrementalBackupBlkdebug(TestIncrementalBackupBase):
52
"""
53
54
drive0 = self.drives[0]
55
- # NB: The blkdebug script here looks for a "flush, read, read" pattern.
56
- # The flush occurs in hmp_io_writes, the first read in device_add, and
57
- # the last read during the block job.
58
+ # NB: The blkdebug script here looks for a "flush, read" pattern.
59
+ # The flush occurs in hmp_io_writes, and the read during the block job.
60
result = self.vm.qmp('blockdev-add',
61
node_name=drive0['id'],
62
driver=drive0['fmt'],
63
@@ -XXX,XX +XXX,XX @@ class TestIncrementalBackupBlkdebug(TestIncrementalBackupBase):
64
'event': 'flush_to_disk',
65
'state': 1,
66
'new_state': 2
67
- },{
68
- 'event': 'read_aio',
69
- 'state': 2,
70
- 'new_state': 3
71
}],
72
'inject-error': [{
73
'event': 'read_aio',
74
'errno': 5,
75
- 'state': 3,
76
+ 'state': 2,
77
'immediately': False,
78
'once': True
79
}],
80
@@ -XXX,XX +XXX,XX @@ class TestIncrementalBackupBlkdebug(TestIncrementalBackupBase):
81
('0xfe', '16M', '256k'),
82
('0x64', '32736k', '64k')))
83
84
- # For the purposes of query-block visibility of bitmaps, add a drive
85
- # frontend after we've written data; otherwise we can't use hmp-io
86
- result = self.vm.qmp("device_add",
87
- id="device0",
88
- drive=drive0['id'],
89
- driver="virtio-blk")
90
- self.assert_qmp(result, 'return', {})
91
-
92
# Bitmap Status Check
93
- query = self.vm.qmp('query-block')
94
- ret = [bmap for bmap in query['return'][0]['dirty-bitmaps']
95
- if bmap.get('name') == bitmap.name][0]
96
- self.assert_qmp(ret, 'count', 458752)
97
- self.assert_qmp(ret, 'granularity', 65536)
98
- self.assert_qmp(ret, 'status', 'active')
99
- self.assert_qmp(ret, 'busy', False)
100
- self.assert_qmp(ret, 'recording', True)
101
+ self.assertTrue(self.vm.check_bitmap_status(
102
+ drive0['id'], bitmap.name, {
103
+ 'count': 458752,
104
+ 'granularity': 65536,
105
+ 'status': 'active',
106
+ 'busy': False,
107
+ 'recording': True
108
+ }))
109
110
# Start backup
111
parent, _ = bitmap.last_target()
112
@@ -XXX,XX +XXX,XX @@ class TestIncrementalBackupBlkdebug(TestIncrementalBackupBase):
113
'operation': 'read'})
114
115
# Bitmap Status Check
116
- query = self.vm.qmp('query-block')
117
- ret = [bmap for bmap in query['return'][0]['dirty-bitmaps']
118
- if bmap.get('name') == bitmap.name][0]
119
- self.assert_qmp(ret, 'count', 458752)
120
- self.assert_qmp(ret, 'granularity', 65536)
121
- self.assert_qmp(ret, 'status', 'frozen')
122
- self.assert_qmp(ret, 'busy', True)
123
- self.assert_qmp(ret, 'recording', True)
124
+ self.assertTrue(self.vm.check_bitmap_status(
125
+ drive0['id'], bitmap.name, {
126
+ 'count': 458752,
127
+ 'granularity': 65536,
128
+ 'status': 'frozen',
129
+ 'busy': True,
130
+ 'recording': True
131
+ }))
132
133
# Resume and check incremental backup for consistency
134
res = self.vm.qmp('block-job-resume', device=bitmap.drive['id'])
135
@@ -XXX,XX +XXX,XX @@ class TestIncrementalBackupBlkdebug(TestIncrementalBackupBase):
136
self.wait_qmp_backup(bitmap.drive['id'])
137
138
# Bitmap Status Check
139
- query = self.vm.qmp('query-block')
140
- ret = [bmap for bmap in query['return'][0]['dirty-bitmaps']
141
- if bmap.get('name') == bitmap.name][0]
142
- self.assert_qmp(ret, 'count', 0)
143
- self.assert_qmp(ret, 'granularity', 65536)
144
- self.assert_qmp(ret, 'status', 'active')
145
- self.assert_qmp(ret, 'busy', False)
146
- self.assert_qmp(ret, 'recording', True)
147
+ self.assertTrue(self.vm.check_bitmap_status(
148
+ drive0['id'], bitmap.name, {
149
+ 'count': 0,
150
+ 'granularity': 65536,
151
+ 'status': 'active',
152
+ 'busy': False,
153
+ 'recording': True
154
+ }))
155
156
# Finalize / Cleanup
157
self.make_reference_backup(bitmap)
158
diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257
159
index XXXXXXX..XXXXXXX 100755
160
--- a/tests/qemu-iotests/257
161
+++ b/tests/qemu-iotests/257
162
@@ -XXX,XX +XXX,XX @@ class Drive:
163
self.size = size
164
self.node = name
165
166
-def query_bitmaps(vm):
167
- res = vm.qmp("query-block")
168
- return {"bitmaps": {device['device'] or device['qdev']:
169
- device.get('dirty-bitmaps', []) for
170
- device in res['return']}}
171
-
172
-def get_bitmap(bitmaps, drivename, name, recording=None):
173
- """
174
- get a specific bitmap from the object returned by query_bitmaps.
175
- :param recording: If specified, filter results by the specified value.
176
- """
177
- for bitmap in bitmaps['bitmaps'][drivename]:
178
- if bitmap.get('name', '') == name:
179
- if recording is None:
180
- return bitmap
181
- elif bitmap.get('recording') == recording:
182
- return bitmap
183
- return None
184
-
185
def blockdev_backup(vm, device, target, sync, **kwargs):
186
# Strip any arguments explicitly nulled by the caller:
187
kwargs = {key: val for key, val in kwargs.items() if val is not None}
188
@@ -XXX,XX +XXX,XX @@ def perform_writes(drive, n):
189
pattern.size)
190
log(cmd)
191
log(drive.vm.hmp_qemu_io(drive.name, cmd))
192
- bitmaps = query_bitmaps(drive.vm)
193
- log(bitmaps, indent=2)
194
+ bitmaps = drive.vm.query_bitmaps()
195
+ log({'bitmaps': bitmaps}, indent=2)
196
log('')
197
return bitmaps
198
199
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
200
# 1 - Writes and Reference Backup
201
bitmaps = perform_writes(drive0, 1)
202
ebitmap.dirty_group(1)
203
- bitmap = get_bitmap(bitmaps, drive0.device, 'bitmap0')
204
+ bitmap = vm.get_bitmap(drive0.node, 'bitmap0', bitmaps=bitmaps)
205
ebitmap.compare(bitmap)
206
reference_backup(drive0, 1, fbackup1)
207
208
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
209
log('')
210
bitmaps = perform_writes(drive0, 2)
211
# Named bitmap (static, should be unchanged)
212
- ebitmap.compare(get_bitmap(bitmaps, drive0.device, 'bitmap0'))
213
+ ebitmap.compare(vm.get_bitmap(drive0.node, 'bitmap0',
214
+ bitmaps=bitmaps))
215
# Anonymous bitmap (dynamic, shows new writes)
216
anonymous = EmulatedBitmap()
217
anonymous.dirty_group(2)
218
- anonymous.compare(get_bitmap(bitmaps, drive0.device, '',
219
- recording=True))
220
+ anonymous.compare(vm.get_bitmap(drive0.node, '', recording=True,
221
+ bitmaps=bitmaps))
222
223
# Simulate the order in which this will happen:
224
# group 1 gets cleared first, then group two gets written.
225
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
226
vm.run_job(job, auto_dismiss=True, auto_finalize=False,
227
pre_finalize=_callback,
228
cancel=(failure == 'simulated'))
229
- bitmaps = query_bitmaps(vm)
230
- log(bitmaps, indent=2)
231
+ bitmaps = vm.query_bitmaps()
232
+ log({'bitmaps': bitmaps}, indent=2)
233
log('')
234
235
if bsync_mode == 'always' and failure == 'intermediate':
236
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
237
ebitmap.clear()
238
ebitmap.dirty_bits(range(fail_bit, SIZE // GRANULARITY))
239
240
- ebitmap.compare(get_bitmap(bitmaps, drive0.device, 'bitmap0'))
241
+ ebitmap.compare(vm.get_bitmap(drive0.node, 'bitmap0', bitmaps=bitmaps))
242
243
# 2 - Writes and Reference Backup
244
bitmaps = perform_writes(drive0, 3)
245
ebitmap.dirty_group(3)
246
- ebitmap.compare(get_bitmap(bitmaps, drive0.device, 'bitmap0'))
247
+ ebitmap.compare(vm.get_bitmap(drive0.node, 'bitmap0', bitmaps=bitmaps))
248
reference_backup(drive0, 2, fbackup2)
249
250
# 2 - Bitmap Backup (In failure modes, this is a recovery.)
251
job = backup(drive0, 2, bsync2, "bitmap",
252
bitmap="bitmap0", bitmap_mode=bsync_mode)
253
vm.run_job(job, auto_dismiss=True, auto_finalize=False)
254
- bitmaps = query_bitmaps(vm)
255
- log(bitmaps, indent=2)
256
+ bitmaps = vm.query_bitmaps()
257
+ log({'bitmaps': bitmaps}, indent=2)
258
log('')
259
if bsync_mode != 'never':
260
ebitmap.clear()
261
- ebitmap.compare(get_bitmap(bitmaps, drive0.device, 'bitmap0'))
262
+ ebitmap.compare(vm.get_bitmap(drive0.node, 'bitmap0', bitmaps=bitmaps))
263
264
log('--- Cleanup ---\n')
265
vm.qmp_log("block-dirty-bitmap-remove",
266
node=drive0.name, name="bitmap0")
267
- log(query_bitmaps(vm), indent=2)
268
+ bitmaps = vm.query_bitmaps()
269
+ log({'bitmaps': bitmaps}, indent=2)
270
vm.shutdown()
271
log('')
272
273
diff --git a/tests/qemu-iotests/257.out b/tests/qemu-iotests/257.out
274
index XXXXXXX..XXXXXXX 100644
275
--- a/tests/qemu-iotests/257.out
276
+++ b/tests/qemu-iotests/257.out
277
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
278
write -P0x76 0x3ff0000 0x10000
279
{"return": ""}
280
{
281
- "bitmaps": {
282
- "device0": []
283
- }
284
+ "bitmaps": {}
285
}
286
287
--- Reference Backup #0 ---
288
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
289
{"return": ""}
290
{
291
"bitmaps": {
292
- "device0": [
293
+ "drive0": [
294
{
295
"busy": false,
296
"count": 393216,
297
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
298
{"return": ""}
299
{
300
"bitmaps": {
301
- "device0": [
302
+ "drive0": [
303
{
304
"busy": false,
305
"count": 0,
306
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
307
{"data": {"device": "backup_1", "len": 393216, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
308
{
309
"bitmaps": {
310
- "device0": [
311
+ "drive0": [
312
{
313
"busy": false,
314
"count": 655360,
315
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
316
{"return": ""}
317
{
318
"bitmaps": {
319
- "device0": [
320
+ "drive0": [
321
{
322
"busy": false,
323
"count": 983040,
324
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
325
{"data": {"device": "backup_2", "len": 983040, "offset": 983040, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
326
{
327
"bitmaps": {
328
- "device0": [
329
+ "drive0": [
330
{
331
"busy": false,
332
"count": 983040,
333
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
334
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
335
{"return": {}}
336
{
337
- "bitmaps": {
338
- "device0": []
339
- }
340
+ "bitmaps": {}
341
}
342
343
--- Verification ---
344
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
345
write -P0x76 0x3ff0000 0x10000
346
{"return": ""}
347
{
348
- "bitmaps": {
349
- "device0": []
350
- }
351
+ "bitmaps": {}
352
}
353
354
--- Reference Backup #0 ---
355
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
356
{"return": ""}
357
{
358
"bitmaps": {
359
- "device0": [
360
+ "drive0": [
361
{
362
"busy": false,
363
"count": 393216,
364
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
365
{"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"}}
366
{
367
"bitmaps": {
368
- "device0": [
369
+ "drive0": [
370
{
371
"busy": false,
372
"count": 393216,
373
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
374
{"return": ""}
375
{
376
"bitmaps": {
377
- "device0": [
378
+ "drive0": [
379
{
380
"busy": false,
381
"count": 917504,
382
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
383
{"data": {"device": "backup_2", "len": 917504, "offset": 917504, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
384
{
385
"bitmaps": {
386
- "device0": [
387
+ "drive0": [
388
{
389
"busy": false,
390
"count": 917504,
391
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
392
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
393
{"return": {}}
394
{
395
- "bitmaps": {
396
- "device0": []
397
- }
398
+ "bitmaps": {}
399
}
400
401
--- Verification ---
402
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
403
write -P0x76 0x3ff0000 0x10000
404
{"return": ""}
405
{
406
- "bitmaps": {
407
- "device0": []
408
- }
409
+ "bitmaps": {}
410
}
411
412
--- Reference Backup #0 ---
413
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
414
{"return": ""}
415
{
416
"bitmaps": {
417
- "device0": [
418
+ "drive0": [
419
{
420
"busy": false,
421
"count": 393216,
422
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
423
{"return": ""}
424
{
425
"bitmaps": {
426
- "device0": [
427
+ "drive0": [
428
{
429
"busy": false,
430
"count": 0,
431
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
432
{"data": {"device": "backup_1", "len": 393216, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
433
{
434
"bitmaps": {
435
- "device0": [
436
+ "drive0": [
437
{
438
"busy": false,
439
"count": 655360,
440
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
441
{"return": ""}
442
{
443
"bitmaps": {
444
- "device0": [
445
+ "drive0": [
446
{
447
"busy": false,
448
"count": 983040,
449
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
450
{"data": {"device": "backup_2", "len": 983040, "offset": 983040, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
451
{
452
"bitmaps": {
453
- "device0": [
454
+ "drive0": [
455
{
456
"busy": false,
457
"count": 983040,
458
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
459
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
460
{"return": {}}
461
{
462
- "bitmaps": {
463
- "device0": []
464
- }
465
+ "bitmaps": {}
466
}
467
468
--- Verification ---
469
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
470
write -P0x76 0x3ff0000 0x10000
471
{"return": ""}
472
{
473
- "bitmaps": {
474
- "device0": []
475
- }
476
+ "bitmaps": {}
477
}
478
479
--- Reference Backup #0 ---
480
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
481
{"return": ""}
482
{
483
"bitmaps": {
484
- "device0": [
485
+ "drive0": [
486
{
487
"busy": false,
488
"count": 393216,
489
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
490
{"return": ""}
491
{
492
"bitmaps": {
493
- "device0": [
494
+ "drive0": [
495
{
496
"busy": false,
497
"count": 0,
498
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
499
{"data": {"device": "backup_1", "len": 393216, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
500
{
501
"bitmaps": {
502
- "device0": [
503
+ "drive0": [
504
{
505
"busy": false,
506
"count": 655360,
507
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
508
{"return": ""}
509
{
510
"bitmaps": {
511
- "device0": [
512
+ "drive0": [
513
{
514
"busy": false,
515
"count": 983040,
516
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
517
{"data": {"device": "backup_2", "len": 983040, "offset": 983040, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
518
{
519
"bitmaps": {
520
- "device0": [
521
+ "drive0": [
522
{
523
"busy": false,
524
"count": 0,
525
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
526
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
527
{"return": {}}
528
{
529
- "bitmaps": {
530
- "device0": []
531
- }
532
+ "bitmaps": {}
533
}
534
535
--- Verification ---
536
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
537
write -P0x76 0x3ff0000 0x10000
538
{"return": ""}
539
{
540
- "bitmaps": {
541
- "device0": []
542
- }
543
+ "bitmaps": {}
544
}
545
546
--- Reference Backup #0 ---
547
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
548
{"return": ""}
549
{
550
"bitmaps": {
551
- "device0": [
552
+ "drive0": [
553
{
554
"busy": false,
555
"count": 393216,
556
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
557
{"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"}}
558
{
559
"bitmaps": {
560
- "device0": [
561
+ "drive0": [
562
{
563
"busy": false,
564
"count": 393216,
565
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
566
{"return": ""}
567
{
568
"bitmaps": {
569
- "device0": [
570
+ "drive0": [
571
{
572
"busy": false,
573
"count": 917504,
574
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
575
{"data": {"device": "backup_2", "len": 917504, "offset": 917504, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
576
{
577
"bitmaps": {
578
- "device0": [
579
+ "drive0": [
580
{
581
"busy": false,
582
"count": 0,
583
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
584
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
585
{"return": {}}
586
{
587
- "bitmaps": {
588
- "device0": []
589
- }
590
+ "bitmaps": {}
591
}
592
593
--- Verification ---
594
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
595
write -P0x76 0x3ff0000 0x10000
596
{"return": ""}
597
{
598
- "bitmaps": {
599
- "device0": []
600
- }
601
+ "bitmaps": {}
602
}
603
604
--- Reference Backup #0 ---
605
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
606
{"return": ""}
607
{
608
"bitmaps": {
609
- "device0": [
610
+ "drive0": [
611
{
612
"busy": false,
613
"count": 393216,
614
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
615
{"return": ""}
616
{
617
"bitmaps": {
618
- "device0": [
619
+ "drive0": [
620
{
621
"busy": false,
622
"count": 0,
623
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
624
{"data": {"device": "backup_1", "len": 393216, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
625
{
626
"bitmaps": {
627
- "device0": [
628
+ "drive0": [
629
{
630
"busy": false,
631
"count": 458752,
632
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
633
{"return": ""}
634
{
635
"bitmaps": {
636
- "device0": [
637
+ "drive0": [
638
{
639
"busy": false,
640
"count": 786432,
641
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
642
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
643
{
644
"bitmaps": {
645
- "device0": [
646
+ "drive0": [
647
{
648
"busy": false,
649
"count": 0,
650
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
651
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
652
{"return": {}}
653
{
654
- "bitmaps": {
655
- "device0": []
656
- }
657
+ "bitmaps": {}
658
}
659
660
--- Verification ---
661
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
662
write -P0x76 0x3ff0000 0x10000
663
{"return": ""}
664
{
665
- "bitmaps": {
666
- "device0": []
667
- }
668
+ "bitmaps": {}
669
}
670
671
--- Reference Backup #0 ---
672
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
673
{"return": ""}
674
{
675
"bitmaps": {
676
- "device0": [
677
+ "drive0": [
678
{
679
"busy": false,
680
"count": 393216,
681
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
682
{"return": ""}
683
{
684
"bitmaps": {
685
- "device0": [
686
+ "drive0": [
687
{
688
"busy": false,
689
"count": 0,
690
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
691
{"data": {"device": "backup_1", "len": 393216, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
692
{
693
"bitmaps": {
694
- "device0": [
695
+ "drive0": [
696
{
697
"busy": false,
698
"count": 458752,
699
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
700
{"return": ""}
701
{
702
"bitmaps": {
703
- "device0": [
704
+ "drive0": [
705
{
706
"busy": false,
707
"count": 786432,
708
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
709
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
710
{
711
"bitmaps": {
712
- "device0": [
713
+ "drive0": [
714
{
715
"busy": false,
716
"count": 0,
717
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
718
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
719
{"return": {}}
720
{
721
- "bitmaps": {
722
- "device0": []
723
- }
724
+ "bitmaps": {}
725
}
726
727
--- Verification ---
728
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
729
write -P0x76 0x3ff0000 0x10000
730
{"return": ""}
731
{
732
- "bitmaps": {
733
- "device0": []
734
- }
735
+ "bitmaps": {}
736
}
737
738
--- Reference Backup #0 ---
739
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
740
{"return": ""}
741
{
742
"bitmaps": {
743
- "device0": [
744
+ "drive0": [
745
{
746
"busy": false,
747
"count": 393216,
748
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
749
{"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"}}
750
{
751
"bitmaps": {
752
- "device0": [
753
+ "drive0": [
754
{
755
"busy": false,
756
"count": 327680,
757
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
758
{"return": ""}
759
{
760
"bitmaps": {
761
- "device0": [
762
+ "drive0": [
763
{
764
"busy": false,
765
"count": 851968,
766
@@ -XXX,XX +XXX,XX @@ expecting 13 dirty sectors; have 13. OK!
767
{"data": {"device": "backup_2", "len": 851968, "offset": 851968, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
768
{
769
"bitmaps": {
770
- "device0": [
771
+ "drive0": [
772
{
773
"busy": false,
774
"count": 0,
775
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
776
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
777
{"return": {}}
778
{
779
- "bitmaps": {
780
- "device0": []
781
- }
782
+ "bitmaps": {}
783
}
784
785
--- Verification ---
786
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
787
write -P0x76 0x3ff0000 0x10000
788
{"return": ""}
789
{
790
- "bitmaps": {
791
- "device0": []
792
- }
793
+ "bitmaps": {}
794
}
795
796
--- Reference Backup #0 ---
797
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
798
{"return": ""}
799
{
800
"bitmaps": {
801
- "device0": [
802
+ "drive0": [
803
{
804
"busy": false,
805
"count": 393216,
806
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
807
{"return": ""}
808
{
809
"bitmaps": {
810
- "device0": [
811
+ "drive0": [
812
{
813
"busy": false,
814
"count": 0,
815
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
816
{"data": {"device": "backup_1", "len": 393216, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
817
{
818
"bitmaps": {
819
- "device0": [
820
+ "drive0": [
821
{
822
"busy": false,
823
"count": 458752,
824
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
825
{"return": ""}
826
{
827
"bitmaps": {
828
- "device0": [
829
+ "drive0": [
830
{
831
"busy": false,
832
"count": 786432,
833
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
834
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
835
{
836
"bitmaps": {
837
- "device0": [
838
+ "drive0": [
839
{
840
"busy": false,
841
"count": 0,
842
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
843
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
844
{"return": {}}
845
{
846
- "bitmaps": {
847
- "device0": []
848
- }
849
+ "bitmaps": {}
850
}
851
852
--- Verification ---
853
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
854
write -P0x76 0x3ff0000 0x10000
855
{"return": ""}
856
{
857
- "bitmaps": {
858
- "device0": []
859
- }
860
+ "bitmaps": {}
861
}
862
863
--- Reference Backup #0 ---
864
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
865
{"return": ""}
866
{
867
"bitmaps": {
868
- "device0": [
869
+ "drive0": [
870
{
871
"busy": false,
872
"count": 393216,
873
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
874
{"return": ""}
875
{
876
"bitmaps": {
877
- "device0": [
878
+ "drive0": [
879
{
880
"busy": false,
881
"count": 0,
882
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
883
{"data": {"device": "backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
884
{
885
"bitmaps": {
886
- "device0": [
887
+ "drive0": [
888
{
889
"busy": false,
890
"count": 655360,
891
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
892
{"return": ""}
893
{
894
"bitmaps": {
895
- "device0": [
896
+ "drive0": [
897
{
898
"busy": false,
899
"count": 983040,
900
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
901
{"data": {"device": "backup_2", "len": 983040, "offset": 983040, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
902
{
903
"bitmaps": {
904
- "device0": [
905
+ "drive0": [
906
{
907
"busy": false,
908
"count": 0,
909
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
910
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
911
{"return": {}}
912
{
913
- "bitmaps": {
914
- "device0": []
915
- }
916
+ "bitmaps": {}
917
}
918
919
--- Verification ---
920
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
921
write -P0x76 0x3ff0000 0x10000
922
{"return": ""}
923
{
924
- "bitmaps": {
925
- "device0": []
926
- }
927
+ "bitmaps": {}
928
}
929
930
--- Reference Backup #0 ---
931
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
932
{"return": ""}
933
{
934
"bitmaps": {
935
- "device0": [
936
+ "drive0": [
937
{
938
"busy": false,
939
"count": 393216,
940
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
941
{"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"}}
942
{
943
"bitmaps": {
944
- "device0": [
945
+ "drive0": [
946
{
947
"busy": false,
948
"count": 393216,
949
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
950
{"return": ""}
951
{
952
"bitmaps": {
953
- "device0": [
954
+ "drive0": [
955
{
956
"busy": false,
957
"count": 917504,
958
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
959
{"data": {"device": "backup_2", "len": 917504, "offset": 917504, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
960
{
961
"bitmaps": {
962
- "device0": [
963
+ "drive0": [
964
{
965
"busy": false,
966
"count": 0,
967
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
968
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
969
{"return": {}}
970
{
971
- "bitmaps": {
972
- "device0": []
973
- }
974
+ "bitmaps": {}
975
}
976
977
--- Verification ---
978
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
979
write -P0x76 0x3ff0000 0x10000
980
{"return": ""}
981
{
982
- "bitmaps": {
983
- "device0": []
984
- }
985
+ "bitmaps": {}
986
}
987
988
--- Reference Backup #0 ---
989
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
990
{"return": ""}
991
{
992
"bitmaps": {
993
- "device0": [
994
+ "drive0": [
995
{
996
"busy": false,
997
"count": 393216,
998
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
999
{"return": ""}
1000
{
1001
"bitmaps": {
1002
- "device0": [
1003
+ "drive0": [
1004
{
1005
"busy": false,
1006
"count": 0,
1007
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
1008
{"data": {"device": "backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1009
{
1010
"bitmaps": {
1011
- "device0": [
1012
+ "drive0": [
1013
{
1014
"busy": false,
1015
"count": 458752,
1016
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1017
{"return": ""}
1018
{
1019
"bitmaps": {
1020
- "device0": [
1021
+ "drive0": [
1022
{
1023
"busy": false,
1024
"count": 786432,
1025
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1026
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1027
{
1028
"bitmaps": {
1029
- "device0": [
1030
+ "drive0": [
1031
{
1032
"busy": false,
1033
"count": 0,
1034
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1035
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1036
{"return": {}}
1037
{
1038
- "bitmaps": {
1039
- "device0": []
1040
- }
1041
+ "bitmaps": {}
1042
}
1043
1044
--- Verification ---
1045
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1046
write -P0x76 0x3ff0000 0x10000
1047
{"return": ""}
1048
{
1049
- "bitmaps": {
1050
- "device0": []
1051
- }
1052
+ "bitmaps": {}
1053
}
1054
1055
--- Reference Backup #0 ---
1056
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1057
{"return": ""}
1058
{
1059
"bitmaps": {
1060
- "device0": [
1061
+ "drive0": [
1062
{
1063
"busy": false,
1064
"count": 393216,
1065
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
1066
{"return": ""}
1067
{
1068
"bitmaps": {
1069
- "device0": [
1070
+ "drive0": [
1071
{
1072
"busy": false,
1073
"count": 0,
1074
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
1075
{"data": {"device": "backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1076
{
1077
"bitmaps": {
1078
- "device0": [
1079
+ "drive0": [
1080
{
1081
"busy": false,
1082
"count": 458752,
1083
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1084
{"return": ""}
1085
{
1086
"bitmaps": {
1087
- "device0": [
1088
+ "drive0": [
1089
{
1090
"busy": false,
1091
"count": 786432,
1092
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1093
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1094
{
1095
"bitmaps": {
1096
- "device0": [
1097
+ "drive0": [
1098
{
1099
"busy": false,
1100
"count": 0,
1101
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1102
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1103
{"return": {}}
1104
{
1105
- "bitmaps": {
1106
- "device0": []
1107
- }
1108
+ "bitmaps": {}
1109
}
1110
1111
--- Verification ---
1112
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1113
write -P0x76 0x3ff0000 0x10000
1114
{"return": ""}
1115
{
1116
- "bitmaps": {
1117
- "device0": []
1118
- }
1119
+ "bitmaps": {}
1120
}
1121
1122
--- Reference Backup #0 ---
1123
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1124
{"return": ""}
1125
{
1126
"bitmaps": {
1127
- "device0": [
1128
+ "drive0": [
1129
{
1130
"busy": false,
1131
"count": 393216,
1132
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1133
{"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"}}
1134
{
1135
"bitmaps": {
1136
- "device0": [
1137
+ "drive0": [
1138
{
1139
"busy": false,
1140
"count": 66125824,
1141
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1142
{"return": ""}
1143
{
1144
"bitmaps": {
1145
- "device0": [
1146
+ "drive0": [
1147
{
1148
"busy": false,
1149
"count": 66453504,
1150
@@ -XXX,XX +XXX,XX @@ expecting 1014 dirty sectors; have 1014. OK!
1151
{"data": {"device": "backup_2", "len": 66453504, "offset": 66453504, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1152
{
1153
"bitmaps": {
1154
- "device0": [
1155
+ "drive0": [
1156
{
1157
"busy": false,
1158
"count": 0,
1159
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1160
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1161
{"return": {}}
1162
{
1163
- "bitmaps": {
1164
- "device0": []
1165
- }
1166
+ "bitmaps": {}
1167
}
1168
1169
--- Verification ---
1170
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1171
write -P0x76 0x3ff0000 0x10000
1172
{"return": ""}
1173
{
1174
- "bitmaps": {
1175
- "device0": []
1176
- }
1177
+ "bitmaps": {}
1178
}
1179
1180
--- Reference Backup #0 ---
1181
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1182
{"return": ""}
1183
{
1184
"bitmaps": {
1185
- "device0": [
1186
+ "drive0": [
1187
{
1188
"busy": false,
1189
"count": 393216,
1190
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
1191
{"return": ""}
1192
{
1193
"bitmaps": {
1194
- "device0": [
1195
+ "drive0": [
1196
{
1197
"busy": false,
1198
"count": 0,
1199
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
1200
{"data": {"device": "backup_1", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1201
{
1202
"bitmaps": {
1203
- "device0": [
1204
+ "drive0": [
1205
{
1206
"busy": false,
1207
"count": 458752,
1208
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1209
{"return": ""}
1210
{
1211
"bitmaps": {
1212
- "device0": [
1213
+ "drive0": [
1214
{
1215
"busy": false,
1216
"count": 786432,
1217
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1218
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1219
{
1220
"bitmaps": {
1221
- "device0": [
1222
+ "drive0": [
1223
{
1224
"busy": false,
1225
"count": 0,
1226
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1227
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1228
{"return": {}}
1229
{
1230
- "bitmaps": {
1231
- "device0": []
1232
- }
1233
+ "bitmaps": {}
1234
}
1235
1236
--- Verification ---
1237
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1238
write -P0x76 0x3ff0000 0x10000
1239
{"return": ""}
1240
{
1241
- "bitmaps": {
1242
- "device0": []
1243
- }
1244
+ "bitmaps": {}
1245
}
1246
1247
--- Reference Backup #0 ---
1248
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1249
{"return": ""}
1250
{
1251
"bitmaps": {
1252
- "device0": [
1253
+ "drive0": [
1254
{
1255
"busy": false,
1256
"count": 393216,
1257
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
1258
{"return": ""}
1259
{
1260
"bitmaps": {
1261
- "device0": [
1262
+ "drive0": [
1263
{
1264
"busy": false,
1265
"count": 0,
1266
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
1267
{"data": {"device": "backup_1", "len": 458752, "offset": 458752, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1268
{
1269
"bitmaps": {
1270
- "device0": [
1271
+ "drive0": [
1272
{
1273
"busy": false,
1274
"count": 655360,
1275
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1276
{"return": ""}
1277
{
1278
"bitmaps": {
1279
- "device0": [
1280
+ "drive0": [
1281
{
1282
"busy": false,
1283
"count": 983040,
1284
@@ -XXX,XX +XXX,XX @@ expecting 15 dirty sectors; have 15. OK!
1285
{"data": {"device": "backup_2", "len": 983040, "offset": 983040, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1286
{
1287
"bitmaps": {
1288
- "device0": [
1289
+ "drive0": [
1290
{
1291
"busy": false,
1292
"count": 0,
1293
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1294
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1295
{"return": {}}
1296
{
1297
- "bitmaps": {
1298
- "device0": []
1299
- }
1300
+ "bitmaps": {}
1301
}
1302
1303
--- Verification ---
1304
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1305
write -P0x76 0x3ff0000 0x10000
1306
{"return": ""}
1307
{
1308
- "bitmaps": {
1309
- "device0": []
1310
- }
1311
+ "bitmaps": {}
1312
}
1313
1314
--- Reference Backup #0 ---
1315
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1316
{"return": ""}
1317
{
1318
"bitmaps": {
1319
- "device0": [
1320
+ "drive0": [
1321
{
1322
"busy": false,
1323
"count": 393216,
1324
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1325
{"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"}}
1326
{
1327
"bitmaps": {
1328
- "device0": [
1329
+ "drive0": [
1330
{
1331
"busy": false,
1332
"count": 393216,
1333
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1334
{"return": ""}
1335
{
1336
"bitmaps": {
1337
- "device0": [
1338
+ "drive0": [
1339
{
1340
"busy": false,
1341
"count": 917504,
1342
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
1343
{"data": {"device": "backup_2", "len": 917504, "offset": 917504, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1344
{
1345
"bitmaps": {
1346
- "device0": [
1347
+ "drive0": [
1348
{
1349
"busy": false,
1350
"count": 0,
1351
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1352
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1353
{"return": {}}
1354
{
1355
- "bitmaps": {
1356
- "device0": []
1357
- }
1358
+ "bitmaps": {}
1359
}
1360
1361
--- Verification ---
1362
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1363
write -P0x76 0x3ff0000 0x10000
1364
{"return": ""}
1365
{
1366
- "bitmaps": {
1367
- "device0": []
1368
- }
1369
+ "bitmaps": {}
1370
}
1371
1372
--- Reference Backup #0 ---
1373
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1374
{"return": ""}
1375
{
1376
"bitmaps": {
1377
- "device0": [
1378
+ "drive0": [
1379
{
1380
"busy": false,
1381
"count": 393216,
1382
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
1383
{"return": ""}
1384
{
1385
"bitmaps": {
1386
- "device0": [
1387
+ "drive0": [
1388
{
1389
"busy": false,
1390
"count": 0,
1391
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
1392
{"data": {"device": "backup_1", "len": 458752, "offset": 458752, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1393
{
1394
"bitmaps": {
1395
- "device0": [
1396
+ "drive0": [
1397
{
1398
"busy": false,
1399
"count": 458752,
1400
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1401
{"return": ""}
1402
{
1403
"bitmaps": {
1404
- "device0": [
1405
+ "drive0": [
1406
{
1407
"busy": false,
1408
"count": 786432,
1409
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1410
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1411
{
1412
"bitmaps": {
1413
- "device0": [
1414
+ "drive0": [
1415
{
1416
"busy": false,
1417
"count": 0,
1418
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1419
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1420
{"return": {}}
1421
{
1422
- "bitmaps": {
1423
- "device0": []
1424
- }
1425
+ "bitmaps": {}
1426
}
1427
1428
--- Verification ---
1429
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1430
write -P0x76 0x3ff0000 0x10000
1431
{"return": ""}
1432
{
1433
- "bitmaps": {
1434
- "device0": []
1435
- }
1436
+ "bitmaps": {}
1437
}
1438
1439
--- Reference Backup #0 ---
1440
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1441
{"return": ""}
1442
{
1443
"bitmaps": {
1444
- "device0": [
1445
+ "drive0": [
1446
{
1447
"busy": false,
1448
"count": 393216,
1449
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
1450
{"return": ""}
1451
{
1452
"bitmaps": {
1453
- "device0": [
1454
+ "drive0": [
1455
{
1456
"busy": false,
1457
"count": 0,
1458
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
1459
{"data": {"device": "backup_1", "len": 458752, "offset": 458752, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1460
{
1461
"bitmaps": {
1462
- "device0": [
1463
+ "drive0": [
1464
{
1465
"busy": false,
1466
"count": 458752,
1467
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1468
{"return": ""}
1469
{
1470
"bitmaps": {
1471
- "device0": [
1472
+ "drive0": [
1473
{
1474
"busy": false,
1475
"count": 786432,
1476
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1477
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1478
{
1479
"bitmaps": {
1480
- "device0": [
1481
+ "drive0": [
1482
{
1483
"busy": false,
1484
"count": 0,
1485
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1486
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1487
{"return": {}}
1488
{
1489
- "bitmaps": {
1490
- "device0": []
1491
- }
1492
+ "bitmaps": {}
1493
}
1494
1495
--- Verification ---
1496
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1497
write -P0x76 0x3ff0000 0x10000
1498
{"return": ""}
1499
{
1500
- "bitmaps": {
1501
- "device0": []
1502
- }
1503
+ "bitmaps": {}
1504
}
1505
1506
--- Reference Backup #0 ---
1507
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1508
{"return": ""}
1509
{
1510
"bitmaps": {
1511
- "device0": [
1512
+ "drive0": [
1513
{
1514
"busy": false,
1515
"count": 393216,
1516
@@ -XXX,XX +XXX,XX @@ expecting 6 dirty sectors; have 6. OK!
1517
{"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"}}
1518
{
1519
"bitmaps": {
1520
- "device0": [
1521
+ "drive0": [
1522
{
1523
"busy": false,
1524
"count": 393216,
1525
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1526
{"return": ""}
1527
{
1528
"bitmaps": {
1529
- "device0": [
1530
+ "drive0": [
1531
{
1532
"busy": false,
1533
"count": 917504,
1534
@@ -XXX,XX +XXX,XX @@ expecting 14 dirty sectors; have 14. OK!
1535
{"data": {"device": "backup_2", "len": 917504, "offset": 917504, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1536
{
1537
"bitmaps": {
1538
- "device0": [
1539
+ "drive0": [
1540
{
1541
"busy": false,
1542
"count": 0,
1543
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1544
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1545
{"return": {}}
1546
{
1547
- "bitmaps": {
1548
- "device0": []
1549
- }
1550
+ "bitmaps": {}
1551
}
1552
1553
--- Verification ---
1554
@@ -XXX,XX +XXX,XX @@ write -P0x6f 0x2000000 0x10000
1555
write -P0x76 0x3ff0000 0x10000
1556
{"return": ""}
1557
{
1558
- "bitmaps": {
1559
- "device0": []
1560
- }
1561
+ "bitmaps": {}
1562
}
1563
1564
--- Reference Backup #0 ---
1565
@@ -XXX,XX +XXX,XX @@ write -P0x69 0x3fe0000 0x10000
1566
{"return": ""}
1567
{
1568
"bitmaps": {
1569
- "device0": [
1570
+ "drive0": [
1571
{
1572
"busy": false,
1573
"count": 393216,
1574
@@ -XXX,XX +XXX,XX @@ write -P0x67 0x3fe0000 0x20000
1575
{"return": ""}
1576
{
1577
"bitmaps": {
1578
- "device0": [
1579
+ "drive0": [
1580
{
1581
"busy": false,
1582
"count": 0,
1583
@@ -XXX,XX +XXX,XX @@ expecting 7 dirty sectors; have 7. OK!
1584
{"data": {"device": "backup_1", "len": 458752, "offset": 458752, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1585
{
1586
"bitmaps": {
1587
- "device0": [
1588
+ "drive0": [
1589
{
1590
"busy": false,
1591
"count": 458752,
1592
@@ -XXX,XX +XXX,XX @@ write -P0xdd 0x3fc0000 0x10000
1593
{"return": ""}
1594
{
1595
"bitmaps": {
1596
- "device0": [
1597
+ "drive0": [
1598
{
1599
"busy": false,
1600
"count": 786432,
1601
@@ -XXX,XX +XXX,XX @@ expecting 12 dirty sectors; have 12. OK!
1602
{"data": {"device": "backup_2", "len": 786432, "offset": 786432, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
1603
{
1604
"bitmaps": {
1605
- "device0": [
1606
+ "drive0": [
1607
{
1608
"busy": false,
1609
"count": 0,
1610
@@ -XXX,XX +XXX,XX @@ expecting 0 dirty sectors; have 0. OK!
1611
{"execute": "block-dirty-bitmap-remove", "arguments": {"name": "bitmap0", "node": "drive0"}}
1612
{"return": {}}
1613
{
1614
- "bitmaps": {
1615
- "device0": []
1616
- }
1617
+ "bitmaps": {}
1618
}
1619
1620
--- Verification ---
1621
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
1622
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
1623
--- a/tests/qemu-iotests/iotests.py
14
--- a/tests/qemu-iotests/iotests.py
1624
+++ b/tests/qemu-iotests/iotests.py
15
+++ b/tests/qemu-iotests/iotests.py
1625
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
16
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
1626
return x
17
socket_scm_helper=socket_scm_helper)
1627
return None
18
self._num_drives = 0
1628
19
1629
+ def query_bitmaps(self):
20
+ def add_object(self, opts):
1630
+ res = self.qmp("query-named-block-nodes")
21
+ self._args.append('-object')
1631
+ return {device['node-name']: device['dirty-bitmaps']
22
+ self._args.append(opts)
1632
+ for device in res['return'] if 'dirty-bitmaps' in device}
23
+ return self
1633
+
24
+
1634
+ def get_bitmap(self, node_name, bitmap_name, recording=None, bitmaps=None):
25
def add_device(self, opts):
1635
+ """
26
self._args.append('-device')
1636
+ get a specific bitmap from the object returned by query_bitmaps.
27
self._args.append(opts)
1637
+ :param recording: If specified, filter results by the specified value.
1638
+ :param bitmaps: If specified, use it instead of call query_bitmaps()
1639
+ """
1640
+ if bitmaps is None:
1641
+ bitmaps = self.query_bitmaps()
1642
+
1643
+ for bitmap in bitmaps[node_name]:
1644
+ if bitmap.get('name', '') == bitmap_name:
1645
+ if recording is None:
1646
+ return bitmap
1647
+ elif bitmap.get('recording') == recording:
1648
+ return bitmap
1649
+ return None
1650
+
1651
+ def check_bitmap_status(self, node_name, bitmap_name, fields):
1652
+ ret = self.get_bitmap(node_name, bitmap_name)
1653
+
1654
+ return fields.items() <= ret.items()
1655
+
1656
1657
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
1658
1659
--
28
--
1660
2.21.0
29
2.14.3
1661
30
1662
31
diff view generated by jsdifflib
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
1
There is a small chance that iothread_stop() hangs as follows:
2
2
3
This will help to identify how many of the user-issued discard operations
3
Thread 3 (Thread 0x7f63eba5f700 (LWP 16105)):
4
(accounted on a device level) have actually suceeded down on the host file
4
#0 0x00007f64012c09b6 in ppoll () at /lib64/libc.so.6
5
(even though the numbers will not be exactly the same if non-raw format
5
#1 0x000055959992eac9 in ppoll (__ss=0x0, __timeout=0x0, __nfds=<optimized out>, __fds=<optimized out>) at /usr/include/bits/poll2.h:77
6
driver is used (e.g. qcow2 sending metadata discards)).
6
#2 0x000055959992eac9 in qemu_poll_ns (fds=<optimized out>, nfds=<optimized out>, timeout=<optimized out>) at util/qemu-timer.c:322
7
#3 0x0000559599930711 in aio_poll (ctx=0x55959bdb83c0, blocking=blocking@entry=true) at util/aio-posix.c:629
8
#4 0x00005595996806fe in iothread_run (opaque=0x55959bd78400) at iothread.c:59
9
#5 0x00007f640159f609 in start_thread () at /lib64/libpthread.so.0
10
#6 0x00007f64012cce6f in clone () at /lib64/libc.so.6
7
11
8
Note that these numbers will not include discards triggered by
12
Thread 1 (Thread 0x7f640b45b280 (LWP 16103)):
9
write-zeroes + MAY_UNMAP calls.
13
#0 0x00007f64015a0b6d in pthread_join () at /lib64/libpthread.so.0
14
#1 0x00005595999332ef in qemu_thread_join (thread=<optimized out>) at util/qemu-thread-posix.c:547
15
#2 0x00005595996808ae in iothread_stop (iothread=<optimized out>) at iothread.c:91
16
#3 0x000055959968094d in iothread_stop_iter (object=<optimized out>, opaque=<optimized out>) at iothread.c:102
17
#4 0x0000559599857d97 in do_object_child_foreach (obj=obj@entry=0x55959bdb8100, fn=fn@entry=0x559599680930 <iothread_stop_iter>, opaque=opaque@entry=0x0, recurse=recurse@entry=false) at qom/object.c:852
18
#5 0x0000559599859477 in object_child_foreach (obj=obj@entry=0x55959bdb8100, fn=fn@entry=0x559599680930 <iothread_stop_iter>, opaque=opaque@entry=0x0) at qom/object.c:867
19
#6 0x0000559599680a6e in iothread_stop_all () at iothread.c:341
20
#7 0x000055959955b1d5 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4913
10
21
11
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
22
The relevant code from iothread_run() is:
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
23
13
Message-id: 20190923121737.83281-9-anton.nefedov@virtuozzo.com
24
while (!atomic_read(&iothread->stopping)) {
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
aio_poll(iothread->ctx, true);
26
27
and iothread_stop():
28
29
iothread->stopping = true;
30
aio_notify(iothread->ctx);
31
...
32
qemu_thread_join(&iothread->thread);
33
34
The following scenario can occur:
35
36
1. IOThread:
37
while (!atomic_read(&iothread->stopping)) -> stopping=false
38
39
2. Main loop:
40
iothread->stopping = true;
41
aio_notify(iothread->ctx);
42
43
3. IOThread:
44
aio_poll(iothread->ctx, true); -> hang
45
46
The bug is explained by the AioContext->notify_me doc comments:
47
48
"If this field is 0, everything (file descriptors, bottom halves,
49
timers) will be re-evaluated before the next blocking poll(), thus the
50
event_notifier_set call can be skipped."
51
52
The problem is that "everything" does not include checking
53
iothread->stopping. This means iothread_run() will block in aio_poll()
54
if aio_notify() was called just before aio_poll().
55
56
This patch fixes the hang by replacing aio_notify() with
57
aio_bh_schedule_oneshot(). This makes aio_poll() or g_main_loop_run()
58
to return.
59
60
Implementing this properly required a new bool running flag. The new
61
flag prevents races that are tricky if we try to use iothread->stopping.
62
Now iothread->stopping is purely for iothread_stop() and
63
iothread->running is purely for the iothread_run() thread.
64
65
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
66
Reviewed-by: Eric Blake <eblake@redhat.com>
67
Message-id: 20171207201320.19284-6-stefanha@redhat.com
68
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
69
---
16
block/file-posix.c | 22 +++++++++++++++++++++-
70
include/sysemu/iothread.h | 3 ++-
17
1 file changed, 21 insertions(+), 1 deletion(-)
71
iothread.c | 20 +++++++++++++++-----
72
2 files changed, 17 insertions(+), 6 deletions(-)
18
73
19
diff --git a/block/file-posix.c b/block/file-posix.c
74
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
20
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
21
--- a/block/file-posix.c
76
--- a/include/sysemu/iothread.h
22
+++ b/block/file-posix.c
77
+++ b/include/sysemu/iothread.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
78
@@ -XXX,XX +XXX,XX @@ typedef struct {
24
bool needs_alignment;
79
GOnce once;
25
bool drop_cache;
80
QemuMutex init_done_lock;
26
bool check_cache_dropped;
81
QemuCond init_done_cond; /* is thread initialization done? */
27
+ struct {
82
- bool stopping;
28
+ uint64_t discard_nb_ok;
83
+ bool stopping; /* has iothread_stop() been called? */
29
+ uint64_t discard_nb_failed;
84
+ bool running; /* should iothread_run() continue? */
30
+ uint64_t discard_bytes_ok;
85
int thread_id;
31
+ } stats;
86
32
87
/* AioContext poll parameters */
33
PRManager *pr_mgr;
88
diff --git a/iothread.c b/iothread.c
34
} BDRVRawState;
89
index XXXXXXX..XXXXXXX 100644
35
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
90
--- a/iothread.c
36
#endif /* !__linux__ */
91
+++ b/iothread.c
92
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
93
qemu_cond_signal(&iothread->init_done_cond);
94
qemu_mutex_unlock(&iothread->init_done_lock);
95
96
- while (!atomic_read(&iothread->stopping)) {
97
+ while (iothread->running) {
98
aio_poll(iothread->ctx, true);
99
100
if (atomic_read(&iothread->worker_context)) {
101
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
102
return NULL;
37
}
103
}
38
104
39
+static void raw_account_discard(BDRVRawState *s, uint64_t nbytes, int ret)
105
+/* Runs in iothread_run() thread */
106
+static void iothread_stop_bh(void *opaque)
40
+{
107
+{
41
+ if (ret) {
108
+ IOThread *iothread = opaque;
42
+ s->stats.discard_nb_failed++;
109
+
43
+ } else {
110
+ iothread->running = false; /* stop iothread_run() */
44
+ s->stats.discard_nb_ok++;
111
+
45
+ s->stats.discard_bytes_ok += nbytes;
112
+ if (iothread->main_loop) {
113
+ g_main_loop_quit(iothread->main_loop);
46
+ }
114
+ }
47
+}
115
+}
48
+
116
+
49
static coroutine_fn int
117
void iothread_stop(IOThread *iothread)
50
raw_do_pdiscard(BlockDriverState *bs, int64_t offset, int bytes, bool blkdev)
51
{
118
{
52
BDRVRawState *s = bs->opaque;
119
if (!iothread->ctx || iothread->stopping) {
53
RawPosixAIOData acb;
120
return;
54
+ int ret;
55
56
acb = (RawPosixAIOData) {
57
.bs = bs,
58
@@ -XXX,XX +XXX,XX @@ raw_do_pdiscard(BlockDriverState *bs, int64_t offset, int bytes, bool blkdev)
59
acb.aio_type |= QEMU_AIO_BLKDEV;
60
}
121
}
61
122
iothread->stopping = true;
62
- return raw_thread_pool_submit(bs, handle_aiocb_discard, &acb);
123
- aio_notify(iothread->ctx);
63
+ ret = raw_thread_pool_submit(bs, handle_aiocb_discard, &acb);
124
- if (atomic_read(&iothread->main_loop)) {
64
+ raw_account_discard(s, bytes, ret);
125
- g_main_loop_quit(iothread->main_loop);
65
+ return ret;
126
- }
127
+ aio_bh_schedule_oneshot(iothread->ctx, iothread_stop_bh, iothread);
128
qemu_thread_join(&iothread->thread);
66
}
129
}
67
130
68
static coroutine_fn int
131
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
69
@@ -XXX,XX +XXX,XX @@ static int fd_open(BlockDriverState *bs)
132
char *name, *thread_name;
70
static coroutine_fn int
133
71
hdev_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
134
iothread->stopping = false;
72
{
135
+ iothread->running = true;
73
+ BDRVRawState *s = bs->opaque;
136
iothread->thread_id = -1;
74
int ret;
137
iothread->ctx = aio_context_new(&local_error);
75
138
if (!iothread->ctx) {
76
ret = fd_open(bs);
77
if (ret < 0) {
78
+ raw_account_discard(s, bytes, ret);
79
return ret;
80
}
81
return raw_do_pdiscard(bs, offset, bytes, true);
82
--
139
--
83
2.21.0
140
2.14.3
84
141
85
142
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
This test case will prevent future regressions with savevm and
2
IOThreads.
2
3
3
Split block_copy to separate file, to be cleanly shared with backup-top
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
filter driver in further commits.
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-id: 20171207201320.19284-7-stefanha@redhat.com
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
tests/qemu-iotests/203 | 59 ++++++++++++++++++++++++++++++++++++++++++++++
10
tests/qemu-iotests/203.out | 6 +++++
11
tests/qemu-iotests/group | 1 +
12
3 files changed, 66 insertions(+)
13
create mode 100755 tests/qemu-iotests/203
14
create mode 100644 tests/qemu-iotests/203.out
5
15
6
It's a clean movement, the only change is drop "static" from interface
16
diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203
7
functions.
17
new file mode 100755
8
18
index XXXXXXX..XXXXXXX
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
--- /dev/null
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
+++ b/tests/qemu-iotests/203
11
Message-id: 20190920142056.12778-8-vsementsov@virtuozzo.com
21
@@ -XXX,XX +XXX,XX @@
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
+#!/usr/bin/env python
13
---
23
+#
14
block/Makefile.objs | 1 +
24
+# Copyright (C) 2017 Red Hat, Inc.
15
include/block/block-copy.h | 76 ++++++++
25
+#
16
block/backup.c | 355 +------------------------------------
26
+# This program is free software; you can redistribute it and/or modify
17
block/block-copy.c | 333 ++++++++++++++++++++++++++++++++++
27
+# it under the terms of the GNU General Public License as published by
18
block/trace-events | 2 +
28
+# the Free Software Foundation; either version 2 of the License, or
19
5 files changed, 413 insertions(+), 354 deletions(-)
29
+# (at your option) any later version.
20
create mode 100644 include/block/block-copy.h
30
+#
21
create mode 100644 block/block-copy.c
31
+# This program is distributed in the hope that it will be useful,
22
32
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
23
diff --git a/block/Makefile.objs b/block/Makefile.objs
33
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
index XXXXXXX..XXXXXXX 100644
34
+# GNU General Public License for more details.
25
--- a/block/Makefile.objs
35
+#
26
+++ b/block/Makefile.objs
36
+# You should have received a copy of the GNU General Public License
27
@@ -XXX,XX +XXX,XX @@ block-obj-y += write-threshold.o
37
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
28
block-obj-y += backup.o
38
+#
29
block-obj-$(CONFIG_REPLICATION) += replication.o
39
+# Creator/Owner: Stefan Hajnoczi <stefanha@redhat.com>
30
block-obj-y += throttle.o copy-on-read.o
40
+#
31
+block-obj-y += block-copy.o
41
+# Check that QMP 'migrate' with multiple drives on a single IOThread completes
32
42
+# successfully. This particular command triggered a hang in the source QEMU
33
block-obj-y += crypto.o
43
+# process due to recursive AioContext locking in bdrv_invalidate_all() and
34
44
+# BDRV_POLL_WHILE().
35
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
45
+
46
+import iotests
47
+
48
+iotests.verify_image_format(supported_fmts=['qcow2'])
49
+iotests.verify_platform(['linux'])
50
+
51
+with iotests.FilePath('disk0.img') as disk0_img_path, \
52
+ iotests.FilePath('disk1.img') as disk1_img_path, \
53
+ iotests.VM() as vm:
54
+
55
+ img_size = '10M'
56
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk0_img_path, img_size)
57
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk1_img_path, img_size)
58
+
59
+ iotests.log('Launching VM...')
60
+ (vm.add_object('iothread,id=iothread0')
61
+ .add_drive(disk0_img_path, 'node-name=drive0-node', interface='none')
62
+ .add_drive(disk1_img_path, 'node-name=drive1-node', interface='none')
63
+ .launch())
64
+
65
+ iotests.log('Setting IOThreads...')
66
+ iotests.log(vm.qmp('x-blockdev-set-iothread',
67
+ node_name='drive0-node', iothread='iothread0',
68
+ force=True))
69
+ iotests.log(vm.qmp('x-blockdev-set-iothread',
70
+ node_name='drive1-node', iothread='iothread0',
71
+ force=True))
72
+
73
+ iotests.log('Starting migration...')
74
+ iotests.log(vm.qmp('migrate', uri='exec:cat >/dev/null'))
75
+ while True:
76
+ vm.get_qmp_event(wait=60.0)
77
+ result = vm.qmp('query-migrate')
78
+ status = result.get('return', {}).get('status', None)
79
+ if status == 'completed':
80
+ break
81
diff --git a/tests/qemu-iotests/203.out b/tests/qemu-iotests/203.out
36
new file mode 100644
82
new file mode 100644
37
index XXXXXXX..XXXXXXX
83
index XXXXXXX..XXXXXXX
38
--- /dev/null
84
--- /dev/null
39
+++ b/include/block/block-copy.h
85
+++ b/tests/qemu-iotests/203.out
40
@@ -XXX,XX +XXX,XX @@
86
@@ -XXX,XX +XXX,XX @@
41
+/*
87
+Launching VM...
42
+ * block_copy API
88
+Setting IOThreads...
43
+ *
89
+{u'return': {}}
44
+ * Copyright (C) 2013 Proxmox Server Solutions
90
+{u'return': {}}
45
+ * Copyright (c) 2019 Virtuozzo International GmbH.
91
+Starting migration...
46
+ *
92
+{u'return': {}}
47
+ * Authors:
93
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
48
+ * Dietmar Maurer (dietmar@proxmox.com)
49
+ * Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
50
+ *
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
52
+ * See the COPYING file in the top-level directory.
53
+ */
54
+
55
+#ifndef BLOCK_COPY_H
56
+#define BLOCK_COPY_H
57
+
58
+#include "block/block.h"
59
+
60
+typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
61
+typedef void (*ProgressResetCallbackFunc)(void *opaque);
62
+typedef struct BlockCopyState {
63
+ BlockBackend *source;
64
+ BlockBackend *target;
65
+ BdrvDirtyBitmap *copy_bitmap;
66
+ int64_t cluster_size;
67
+ bool use_copy_range;
68
+ int64_t copy_range_size;
69
+ uint64_t len;
70
+
71
+ BdrvRequestFlags write_flags;
72
+
73
+ /*
74
+ * skip_unallocated:
75
+ *
76
+ * Used by sync=top jobs, which first scan the source node for unallocated
77
+ * areas and clear them in the copy_bitmap. During this process, the bitmap
78
+ * is thus not fully initialized: It may still have bits set for areas that
79
+ * are unallocated and should actually not be copied.
80
+ *
81
+ * This is indicated by skip_unallocated.
82
+ *
83
+ * In this case, block_copy() will query the source’s allocation status,
84
+ * skip unallocated regions, clear them in the copy_bitmap, and invoke
85
+ * block_copy_reset_unallocated() every time it does.
86
+ */
87
+ bool skip_unallocated;
88
+
89
+ /* progress_bytes_callback: called when some copying progress is done. */
90
+ ProgressBytesCallbackFunc progress_bytes_callback;
91
+
92
+ /*
93
+ * progress_reset_callback: called when some bytes reset from copy_bitmap
94
+ * (see @skip_unallocated above). The callee is assumed to recalculate how
95
+ * many bytes remain based on the dirty bit count of copy_bitmap.
96
+ */
97
+ ProgressResetCallbackFunc progress_reset_callback;
98
+ void *progress_opaque;
99
+} BlockCopyState;
100
+
101
+BlockCopyState *block_copy_state_new(
102
+ BlockDriverState *source, BlockDriverState *target,
103
+ int64_t cluster_size, BdrvRequestFlags write_flags,
104
+ ProgressBytesCallbackFunc progress_bytes_callback,
105
+ ProgressResetCallbackFunc progress_reset_callback,
106
+ void *progress_opaque, Error **errp);
107
+
108
+void block_copy_state_free(BlockCopyState *s);
109
+
110
+int64_t block_copy_reset_unallocated(BlockCopyState *s,
111
+ int64_t offset, int64_t *count);
112
+
113
+int coroutine_fn block_copy(BlockCopyState *s, int64_t start, uint64_t bytes,
114
+ bool *error_is_read, bool is_write_notifier);
115
+
116
+#endif /* BLOCK_COPY_H */
117
diff --git a/block/backup.c b/block/backup.c
118
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
119
--- a/block/backup.c
95
--- a/tests/qemu-iotests/group
120
+++ b/block/backup.c
96
+++ b/tests/qemu-iotests/group
121
@@ -XXX,XX +XXX,XX @@
97
@@ -XXX,XX +XXX,XX @@
122
#include "block/block_int.h"
98
198 rw auto
123
#include "block/blockjob_int.h"
99
200 rw auto
124
#include "block/block_backup.h"
100
202 rw auto quick
125
+#include "block/block-copy.h"
101
+203 rw auto
126
#include "qapi/error.h"
127
#include "qapi/qmp/qerror.h"
128
#include "qemu/ratelimit.h"
129
@@ -XXX,XX +XXX,XX @@ typedef struct CowRequest {
130
CoQueue wait_queue; /* coroutines blocked on this request */
131
} CowRequest;
132
133
-typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
134
-typedef void (*ProgressResetCallbackFunc)(void *opaque);
135
-typedef struct BlockCopyState {
136
- BlockBackend *source;
137
- BlockBackend *target;
138
- BdrvDirtyBitmap *copy_bitmap;
139
- int64_t cluster_size;
140
- bool use_copy_range;
141
- int64_t copy_range_size;
142
- uint64_t len;
143
-
144
- BdrvRequestFlags write_flags;
145
-
146
- /*
147
- * skip_unallocated:
148
- *
149
- * Used by sync=top jobs, which first scan the source node for unallocated
150
- * areas and clear them in the copy_bitmap. During this process, the bitmap
151
- * is thus not fully initialized: It may still have bits set for areas that
152
- * are unallocated and should actually not be copied.
153
- *
154
- * This is indicated by skip_unallocated.
155
- *
156
- * In this case, block_copy() will query the source’s allocation status,
157
- * skip unallocated regions, clear them in the copy_bitmap, and invoke
158
- * block_copy_reset_unallocated() every time it does.
159
- */
160
- bool skip_unallocated;
161
-
162
- /* progress_bytes_callback: called when some copying progress is done. */
163
- ProgressBytesCallbackFunc progress_bytes_callback;
164
-
165
- /*
166
- * progress_reset_callback: called when some bytes reset from copy_bitmap
167
- * (see @skip_unallocated above). The callee is assumed to recalculate how
168
- * many bytes remain based on the dirty bit count of copy_bitmap.
169
- */
170
- ProgressResetCallbackFunc progress_reset_callback;
171
- void *progress_opaque;
172
-} BlockCopyState;
173
-
174
typedef struct BackupBlockJob {
175
BlockJob common;
176
BlockDriverState *source_bs;
177
@@ -XXX,XX +XXX,XX @@ static void cow_request_end(CowRequest *req)
178
qemu_co_queue_restart_all(&req->wait_queue);
179
}
180
181
-static void block_copy_state_free(BlockCopyState *s)
182
-{
183
- if (!s) {
184
- return;
185
- }
186
-
187
- bdrv_release_dirty_bitmap(blk_bs(s->source), s->copy_bitmap);
188
- blk_unref(s->source);
189
- blk_unref(s->target);
190
- g_free(s);
191
-}
192
-
193
-static BlockCopyState *block_copy_state_new(
194
- BlockDriverState *source, BlockDriverState *target,
195
- int64_t cluster_size, BdrvRequestFlags write_flags,
196
- ProgressBytesCallbackFunc progress_bytes_callback,
197
- ProgressResetCallbackFunc progress_reset_callback,
198
- void *progress_opaque, Error **errp)
199
-{
200
- BlockCopyState *s;
201
- int ret;
202
- uint64_t no_resize = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
203
- BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD;
204
- BdrvDirtyBitmap *copy_bitmap;
205
-
206
- copy_bitmap = bdrv_create_dirty_bitmap(source, cluster_size, NULL, errp);
207
- if (!copy_bitmap) {
208
- return NULL;
209
- }
210
- bdrv_disable_dirty_bitmap(copy_bitmap);
211
-
212
- s = g_new(BlockCopyState, 1);
213
- *s = (BlockCopyState) {
214
- .source = blk_new(bdrv_get_aio_context(source),
215
- BLK_PERM_CONSISTENT_READ, no_resize),
216
- .target = blk_new(bdrv_get_aio_context(target),
217
- BLK_PERM_WRITE, no_resize),
218
- .copy_bitmap = copy_bitmap,
219
- .cluster_size = cluster_size,
220
- .len = bdrv_dirty_bitmap_size(copy_bitmap),
221
- .write_flags = write_flags,
222
- .progress_bytes_callback = progress_bytes_callback,
223
- .progress_reset_callback = progress_reset_callback,
224
- .progress_opaque = progress_opaque,
225
- };
226
-
227
- s->copy_range_size = QEMU_ALIGN_DOWN(MIN(blk_get_max_transfer(s->source),
228
- blk_get_max_transfer(s->target)),
229
- s->cluster_size);
230
- /*
231
- * Set use_copy_range, consider the following:
232
- * 1. Compression is not supported for copy_range.
233
- * 2. copy_range does not respect max_transfer (it's a TODO), so we factor
234
- * that in here. If max_transfer is smaller than the job->cluster_size,
235
- * we do not use copy_range (in that case it's zero after aligning down
236
- * above).
237
- */
238
- s->use_copy_range =
239
- !(write_flags & BDRV_REQ_WRITE_COMPRESSED) && s->copy_range_size > 0;
240
-
241
- /*
242
- * We just allow aio context change on our block backends. block_copy() user
243
- * (now it's only backup) is responsible for source and target being in same
244
- * aio context.
245
- */
246
- blk_set_disable_request_queuing(s->source, true);
247
- blk_set_allow_aio_context_change(s->source, true);
248
- blk_set_disable_request_queuing(s->target, true);
249
- blk_set_allow_aio_context_change(s->target, true);
250
-
251
- ret = blk_insert_bs(s->source, source, errp);
252
- if (ret < 0) {
253
- goto fail;
254
- }
255
-
256
- ret = blk_insert_bs(s->target, target, errp);
257
- if (ret < 0) {
258
- goto fail;
259
- }
260
-
261
- return s;
262
-
263
-fail:
264
- block_copy_state_free(s);
265
-
266
- return NULL;
267
-}
268
-
269
-/*
270
- * Copy range to target with a bounce buffer and return the bytes copied. If
271
- * error occurred, return a negative error number
272
- */
273
-static int coroutine_fn block_copy_with_bounce_buffer(BlockCopyState *s,
274
- int64_t start,
275
- int64_t end,
276
- bool is_write_notifier,
277
- bool *error_is_read,
278
- void **bounce_buffer)
279
-{
280
- int ret;
281
- int nbytes;
282
- int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
283
-
284
- assert(QEMU_IS_ALIGNED(start, s->cluster_size));
285
- bdrv_reset_dirty_bitmap(s->copy_bitmap, start, s->cluster_size);
286
- nbytes = MIN(s->cluster_size, s->len - start);
287
- if (!*bounce_buffer) {
288
- *bounce_buffer = blk_blockalign(s->source, s->cluster_size);
289
- }
290
-
291
- ret = blk_co_pread(s->source, start, nbytes, *bounce_buffer, read_flags);
292
- if (ret < 0) {
293
- trace_block_copy_with_bounce_buffer_read_fail(s, start, ret);
294
- if (error_is_read) {
295
- *error_is_read = true;
296
- }
297
- goto fail;
298
- }
299
-
300
- ret = blk_co_pwrite(s->target, start, nbytes, *bounce_buffer,
301
- s->write_flags);
302
- if (ret < 0) {
303
- trace_block_copy_with_bounce_buffer_write_fail(s, start, ret);
304
- if (error_is_read) {
305
- *error_is_read = false;
306
- }
307
- goto fail;
308
- }
309
-
310
- return nbytes;
311
-fail:
312
- bdrv_set_dirty_bitmap(s->copy_bitmap, start, s->cluster_size);
313
- return ret;
314
-
315
-}
316
-
317
-/*
318
- * Copy range to target and return the bytes copied. If error occurred, return a
319
- * negative error number.
320
- */
321
-static int coroutine_fn block_copy_with_offload(BlockCopyState *s,
322
- int64_t start,
323
- int64_t end,
324
- bool is_write_notifier)
325
-{
326
- int ret;
327
- int nr_clusters;
328
- int nbytes;
329
- int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
330
-
331
- assert(QEMU_IS_ALIGNED(s->copy_range_size, s->cluster_size));
332
- assert(QEMU_IS_ALIGNED(start, s->cluster_size));
333
- nbytes = MIN(s->copy_range_size, MIN(end, s->len) - start);
334
- nr_clusters = DIV_ROUND_UP(nbytes, s->cluster_size);
335
- bdrv_reset_dirty_bitmap(s->copy_bitmap, start,
336
- s->cluster_size * nr_clusters);
337
- ret = blk_co_copy_range(s->source, start, s->target, start, nbytes,
338
- read_flags, s->write_flags);
339
- if (ret < 0) {
340
- trace_block_copy_with_offload_fail(s, start, ret);
341
- bdrv_set_dirty_bitmap(s->copy_bitmap, start,
342
- s->cluster_size * nr_clusters);
343
- return ret;
344
- }
345
-
346
- return nbytes;
347
-}
348
-
349
-/*
350
- * Check if the cluster starting at offset is allocated or not.
351
- * return via pnum the number of contiguous clusters sharing this allocation.
352
- */
353
-static int block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
354
- int64_t *pnum)
355
-{
356
- BlockDriverState *bs = blk_bs(s->source);
357
- int64_t count, total_count = 0;
358
- int64_t bytes = s->len - offset;
359
- int ret;
360
-
361
- assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
362
-
363
- while (true) {
364
- ret = bdrv_is_allocated(bs, offset, bytes, &count);
365
- if (ret < 0) {
366
- return ret;
367
- }
368
-
369
- total_count += count;
370
-
371
- if (ret || count == 0) {
372
- /*
373
- * ret: partial segment(s) are considered allocated.
374
- * otherwise: unallocated tail is treated as an entire segment.
375
- */
376
- *pnum = DIV_ROUND_UP(total_count, s->cluster_size);
377
- return ret;
378
- }
379
-
380
- /* Unallocated segment(s) with uncertain following segment(s) */
381
- if (total_count >= s->cluster_size) {
382
- *pnum = total_count / s->cluster_size;
383
- return 0;
384
- }
385
-
386
- offset += count;
387
- bytes -= count;
388
- }
389
-}
390
-
391
-/*
392
- * Reset bits in copy_bitmap starting at offset if they represent unallocated
393
- * data in the image. May reset subsequent contiguous bits.
394
- * @return 0 when the cluster at @offset was unallocated,
395
- * 1 otherwise, and -ret on error.
396
- */
397
-static int64_t block_copy_reset_unallocated(BlockCopyState *s,
398
- int64_t offset, int64_t *count)
399
-{
400
- int ret;
401
- int64_t clusters, bytes;
402
-
403
- ret = block_copy_is_cluster_allocated(s, offset, &clusters);
404
- if (ret < 0) {
405
- return ret;
406
- }
407
-
408
- bytes = clusters * s->cluster_size;
409
-
410
- if (!ret) {
411
- bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
412
- s->progress_reset_callback(s->progress_opaque);
413
- }
414
-
415
- *count = bytes;
416
- return ret;
417
-}
418
-
419
-static int coroutine_fn block_copy(BlockCopyState *s,
420
- int64_t start, uint64_t bytes,
421
- bool *error_is_read,
422
- bool is_write_notifier)
423
-{
424
- int ret = 0;
425
- int64_t end = bytes + start; /* bytes */
426
- void *bounce_buffer = NULL;
427
- int64_t status_bytes;
428
-
429
- /*
430
- * block_copy() user is responsible for keeping source and target in same
431
- * aio context
432
- */
433
- assert(blk_get_aio_context(s->source) == blk_get_aio_context(s->target));
434
-
435
- assert(QEMU_IS_ALIGNED(start, s->cluster_size));
436
- assert(QEMU_IS_ALIGNED(end, s->cluster_size));
437
-
438
- while (start < end) {
439
- int64_t dirty_end;
440
-
441
- if (!bdrv_dirty_bitmap_get(s->copy_bitmap, start)) {
442
- trace_block_copy_skip(s, start);
443
- start += s->cluster_size;
444
- continue; /* already copied */
445
- }
446
-
447
- dirty_end = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, start,
448
- (end - start));
449
- if (dirty_end < 0) {
450
- dirty_end = end;
451
- }
452
-
453
- if (s->skip_unallocated) {
454
- ret = block_copy_reset_unallocated(s, start, &status_bytes);
455
- if (ret == 0) {
456
- trace_block_copy_skip_range(s, start, status_bytes);
457
- start += status_bytes;
458
- continue;
459
- }
460
- /* Clamp to known allocated region */
461
- dirty_end = MIN(dirty_end, start + status_bytes);
462
- }
463
-
464
- trace_block_copy_process(s, start);
465
-
466
- if (s->use_copy_range) {
467
- ret = block_copy_with_offload(s, start, dirty_end,
468
- is_write_notifier);
469
- if (ret < 0) {
470
- s->use_copy_range = false;
471
- }
472
- }
473
- if (!s->use_copy_range) {
474
- ret = block_copy_with_bounce_buffer(s, start, dirty_end,
475
- is_write_notifier,
476
- error_is_read, &bounce_buffer);
477
- }
478
- if (ret < 0) {
479
- break;
480
- }
481
-
482
- start += ret;
483
- s->progress_bytes_callback(ret, s->progress_opaque);
484
- ret = 0;
485
- }
486
-
487
- if (bounce_buffer) {
488
- qemu_vfree(bounce_buffer);
489
- }
490
-
491
- return ret;
492
-}
493
-
494
static void backup_progress_bytes_callback(int64_t bytes, void *opaque)
495
{
496
BackupBlockJob *s = opaque;
497
diff --git a/block/block-copy.c b/block/block-copy.c
498
new file mode 100644
499
index XXXXXXX..XXXXXXX
500
--- /dev/null
501
+++ b/block/block-copy.c
502
@@ -XXX,XX +XXX,XX @@
503
+/*
504
+ * block_copy API
505
+ *
506
+ * Copyright (C) 2013 Proxmox Server Solutions
507
+ * Copyright (c) 2019 Virtuozzo International GmbH.
508
+ *
509
+ * Authors:
510
+ * Dietmar Maurer (dietmar@proxmox.com)
511
+ * Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
512
+ *
513
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
514
+ * See the COPYING file in the top-level directory.
515
+ */
516
+
517
+#include "qemu/osdep.h"
518
+
519
+#include "trace.h"
520
+#include "qapi/error.h"
521
+#include "block/block-copy.h"
522
+#include "sysemu/block-backend.h"
523
+
524
+void block_copy_state_free(BlockCopyState *s)
525
+{
526
+ if (!s) {
527
+ return;
528
+ }
529
+
530
+ bdrv_release_dirty_bitmap(blk_bs(s->source), s->copy_bitmap);
531
+ blk_unref(s->source);
532
+ blk_unref(s->target);
533
+ g_free(s);
534
+}
535
+
536
+BlockCopyState *block_copy_state_new(
537
+ BlockDriverState *source, BlockDriverState *target,
538
+ int64_t cluster_size, BdrvRequestFlags write_flags,
539
+ ProgressBytesCallbackFunc progress_bytes_callback,
540
+ ProgressResetCallbackFunc progress_reset_callback,
541
+ void *progress_opaque, Error **errp)
542
+{
543
+ BlockCopyState *s;
544
+ int ret;
545
+ uint64_t no_resize = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
546
+ BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD;
547
+ BdrvDirtyBitmap *copy_bitmap;
548
+
549
+ copy_bitmap = bdrv_create_dirty_bitmap(source, cluster_size, NULL, errp);
550
+ if (!copy_bitmap) {
551
+ return NULL;
552
+ }
553
+ bdrv_disable_dirty_bitmap(copy_bitmap);
554
+
555
+ s = g_new(BlockCopyState, 1);
556
+ *s = (BlockCopyState) {
557
+ .source = blk_new(bdrv_get_aio_context(source),
558
+ BLK_PERM_CONSISTENT_READ, no_resize),
559
+ .target = blk_new(bdrv_get_aio_context(target),
560
+ BLK_PERM_WRITE, no_resize),
561
+ .copy_bitmap = copy_bitmap,
562
+ .cluster_size = cluster_size,
563
+ .len = bdrv_dirty_bitmap_size(copy_bitmap),
564
+ .write_flags = write_flags,
565
+ .progress_bytes_callback = progress_bytes_callback,
566
+ .progress_reset_callback = progress_reset_callback,
567
+ .progress_opaque = progress_opaque,
568
+ };
569
+
570
+ s->copy_range_size = QEMU_ALIGN_DOWN(MIN(blk_get_max_transfer(s->source),
571
+ blk_get_max_transfer(s->target)),
572
+ s->cluster_size);
573
+ /*
574
+ * Set use_copy_range, consider the following:
575
+ * 1. Compression is not supported for copy_range.
576
+ * 2. copy_range does not respect max_transfer (it's a TODO), so we factor
577
+ * that in here. If max_transfer is smaller than the job->cluster_size,
578
+ * we do not use copy_range (in that case it's zero after aligning down
579
+ * above).
580
+ */
581
+ s->use_copy_range =
582
+ !(write_flags & BDRV_REQ_WRITE_COMPRESSED) && s->copy_range_size > 0;
583
+
584
+ /*
585
+ * We just allow aio context change on our block backends. block_copy() user
586
+ * (now it's only backup) is responsible for source and target being in same
587
+ * aio context.
588
+ */
589
+ blk_set_disable_request_queuing(s->source, true);
590
+ blk_set_allow_aio_context_change(s->source, true);
591
+ blk_set_disable_request_queuing(s->target, true);
592
+ blk_set_allow_aio_context_change(s->target, true);
593
+
594
+ ret = blk_insert_bs(s->source, source, errp);
595
+ if (ret < 0) {
596
+ goto fail;
597
+ }
598
+
599
+ ret = blk_insert_bs(s->target, target, errp);
600
+ if (ret < 0) {
601
+ goto fail;
602
+ }
603
+
604
+ return s;
605
+
606
+fail:
607
+ block_copy_state_free(s);
608
+
609
+ return NULL;
610
+}
611
+
612
+/*
613
+ * Copy range to target with a bounce buffer and return the bytes copied. If
614
+ * error occurred, return a negative error number
615
+ */
616
+static int coroutine_fn block_copy_with_bounce_buffer(BlockCopyState *s,
617
+ int64_t start,
618
+ int64_t end,
619
+ bool is_write_notifier,
620
+ bool *error_is_read,
621
+ void **bounce_buffer)
622
+{
623
+ int ret;
624
+ int nbytes;
625
+ int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
626
+
627
+ assert(QEMU_IS_ALIGNED(start, s->cluster_size));
628
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, start, s->cluster_size);
629
+ nbytes = MIN(s->cluster_size, s->len - start);
630
+ if (!*bounce_buffer) {
631
+ *bounce_buffer = blk_blockalign(s->source, s->cluster_size);
632
+ }
633
+
634
+ ret = blk_co_pread(s->source, start, nbytes, *bounce_buffer, read_flags);
635
+ if (ret < 0) {
636
+ trace_block_copy_with_bounce_buffer_read_fail(s, start, ret);
637
+ if (error_is_read) {
638
+ *error_is_read = true;
639
+ }
640
+ goto fail;
641
+ }
642
+
643
+ ret = blk_co_pwrite(s->target, start, nbytes, *bounce_buffer,
644
+ s->write_flags);
645
+ if (ret < 0) {
646
+ trace_block_copy_with_bounce_buffer_write_fail(s, start, ret);
647
+ if (error_is_read) {
648
+ *error_is_read = false;
649
+ }
650
+ goto fail;
651
+ }
652
+
653
+ return nbytes;
654
+fail:
655
+ bdrv_set_dirty_bitmap(s->copy_bitmap, start, s->cluster_size);
656
+ return ret;
657
+
658
+}
659
+
660
+/*
661
+ * Copy range to target and return the bytes copied. If error occurred, return a
662
+ * negative error number.
663
+ */
664
+static int coroutine_fn block_copy_with_offload(BlockCopyState *s,
665
+ int64_t start,
666
+ int64_t end,
667
+ bool is_write_notifier)
668
+{
669
+ int ret;
670
+ int nr_clusters;
671
+ int nbytes;
672
+ int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
673
+
674
+ assert(QEMU_IS_ALIGNED(s->copy_range_size, s->cluster_size));
675
+ assert(QEMU_IS_ALIGNED(start, s->cluster_size));
676
+ nbytes = MIN(s->copy_range_size, MIN(end, s->len) - start);
677
+ nr_clusters = DIV_ROUND_UP(nbytes, s->cluster_size);
678
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, start,
679
+ s->cluster_size * nr_clusters);
680
+ ret = blk_co_copy_range(s->source, start, s->target, start, nbytes,
681
+ read_flags, s->write_flags);
682
+ if (ret < 0) {
683
+ trace_block_copy_with_offload_fail(s, start, ret);
684
+ bdrv_set_dirty_bitmap(s->copy_bitmap, start,
685
+ s->cluster_size * nr_clusters);
686
+ return ret;
687
+ }
688
+
689
+ return nbytes;
690
+}
691
+
692
+/*
693
+ * Check if the cluster starting at offset is allocated or not.
694
+ * return via pnum the number of contiguous clusters sharing this allocation.
695
+ */
696
+static int block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
697
+ int64_t *pnum)
698
+{
699
+ BlockDriverState *bs = blk_bs(s->source);
700
+ int64_t count, total_count = 0;
701
+ int64_t bytes = s->len - offset;
702
+ int ret;
703
+
704
+ assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
705
+
706
+ while (true) {
707
+ ret = bdrv_is_allocated(bs, offset, bytes, &count);
708
+ if (ret < 0) {
709
+ return ret;
710
+ }
711
+
712
+ total_count += count;
713
+
714
+ if (ret || count == 0) {
715
+ /*
716
+ * ret: partial segment(s) are considered allocated.
717
+ * otherwise: unallocated tail is treated as an entire segment.
718
+ */
719
+ *pnum = DIV_ROUND_UP(total_count, s->cluster_size);
720
+ return ret;
721
+ }
722
+
723
+ /* Unallocated segment(s) with uncertain following segment(s) */
724
+ if (total_count >= s->cluster_size) {
725
+ *pnum = total_count / s->cluster_size;
726
+ return 0;
727
+ }
728
+
729
+ offset += count;
730
+ bytes -= count;
731
+ }
732
+}
733
+
734
+/*
735
+ * Reset bits in copy_bitmap starting at offset if they represent unallocated
736
+ * data in the image. May reset subsequent contiguous bits.
737
+ * @return 0 when the cluster at @offset was unallocated,
738
+ * 1 otherwise, and -ret on error.
739
+ */
740
+int64_t block_copy_reset_unallocated(BlockCopyState *s,
741
+ int64_t offset, int64_t *count)
742
+{
743
+ int ret;
744
+ int64_t clusters, bytes;
745
+
746
+ ret = block_copy_is_cluster_allocated(s, offset, &clusters);
747
+ if (ret < 0) {
748
+ return ret;
749
+ }
750
+
751
+ bytes = clusters * s->cluster_size;
752
+
753
+ if (!ret) {
754
+ bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
755
+ s->progress_reset_callback(s->progress_opaque);
756
+ }
757
+
758
+ *count = bytes;
759
+ return ret;
760
+}
761
+
762
+int coroutine_fn block_copy(BlockCopyState *s,
763
+ int64_t start, uint64_t bytes,
764
+ bool *error_is_read,
765
+ bool is_write_notifier)
766
+{
767
+ int ret = 0;
768
+ int64_t end = bytes + start; /* bytes */
769
+ void *bounce_buffer = NULL;
770
+ int64_t status_bytes;
771
+
772
+ /*
773
+ * block_copy() user is responsible for keeping source and target in same
774
+ * aio context
775
+ */
776
+ assert(blk_get_aio_context(s->source) == blk_get_aio_context(s->target));
777
+
778
+ assert(QEMU_IS_ALIGNED(start, s->cluster_size));
779
+ assert(QEMU_IS_ALIGNED(end, s->cluster_size));
780
+
781
+ while (start < end) {
782
+ int64_t dirty_end;
783
+
784
+ if (!bdrv_dirty_bitmap_get(s->copy_bitmap, start)) {
785
+ trace_block_copy_skip(s, start);
786
+ start += s->cluster_size;
787
+ continue; /* already copied */
788
+ }
789
+
790
+ dirty_end = bdrv_dirty_bitmap_next_zero(s->copy_bitmap, start,
791
+ (end - start));
792
+ if (dirty_end < 0) {
793
+ dirty_end = end;
794
+ }
795
+
796
+ if (s->skip_unallocated) {
797
+ ret = block_copy_reset_unallocated(s, start, &status_bytes);
798
+ if (ret == 0) {
799
+ trace_block_copy_skip_range(s, start, status_bytes);
800
+ start += status_bytes;
801
+ continue;
802
+ }
803
+ /* Clamp to known allocated region */
804
+ dirty_end = MIN(dirty_end, start + status_bytes);
805
+ }
806
+
807
+ trace_block_copy_process(s, start);
808
+
809
+ if (s->use_copy_range) {
810
+ ret = block_copy_with_offload(s, start, dirty_end,
811
+ is_write_notifier);
812
+ if (ret < 0) {
813
+ s->use_copy_range = false;
814
+ }
815
+ }
816
+ if (!s->use_copy_range) {
817
+ ret = block_copy_with_bounce_buffer(s, start, dirty_end,
818
+ is_write_notifier,
819
+ error_is_read, &bounce_buffer);
820
+ }
821
+ if (ret < 0) {
822
+ break;
823
+ }
824
+
825
+ start += ret;
826
+ s->progress_bytes_callback(ret, s->progress_opaque);
827
+ ret = 0;
828
+ }
829
+
830
+ if (bounce_buffer) {
831
+ qemu_vfree(bounce_buffer);
832
+ }
833
+
834
+ return ret;
835
+}
836
diff --git a/block/trace-events b/block/trace-events
837
index XXXXXXX..XXXXXXX 100644
838
--- a/block/trace-events
839
+++ b/block/trace-events
840
@@ -XXX,XX +XXX,XX @@ mirror_yield_in_flight(void *s, int64_t offset, int in_flight) "s %p offset %" P
841
# backup.c
842
backup_do_cow_enter(void *job, int64_t start, int64_t offset, uint64_t bytes) "job %p start %" PRId64 " offset %" PRId64 " bytes %" PRIu64
843
backup_do_cow_return(void *job, int64_t offset, uint64_t bytes, int ret) "job %p offset %" PRId64 " bytes %" PRIu64 " ret %d"
844
+
845
+# block-copy.c
846
block_copy_skip(void *bcs, int64_t start) "bcs %p start %"PRId64
847
block_copy_skip_range(void *bcs, int64_t start, uint64_t bytes) "bcs %p start %"PRId64" bytes %"PRId64
848
block_copy_process(void *bcs, int64_t start) "bcs %p start %"PRId64
849
--
102
--
850
2.21.0
103
2.14.3
851
104
852
105
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
After previous commit Drive.device is actually unused. Drop it together
4
with .name property. While being here reuse .node in qmp commands
5
instead of writing 'drive0' twice.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20190920142056.12778-11-vsementsov@virtuozzo.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/257 | 37 +++++++++++++++----------------------
13
1 file changed, 15 insertions(+), 22 deletions(-)
14
15
diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/257
18
+++ b/tests/qemu-iotests/257
19
@@ -XXX,XX +XXX,XX @@ class Drive:
20
self.fmt = None
21
self.size = None
22
self.node = None
23
- self.device = None
24
-
25
- @property
26
- def name(self):
27
- return self.node or self.device
28
29
def img_create(self, fmt, size):
30
self.fmt = fmt
31
@@ -XXX,XX +XXX,XX @@ def blockdev_backup(vm, device, target, sync, **kwargs):
32
def blockdev_backup_mktarget(drive, target_id, filepath, sync, **kwargs):
33
target_drive = Drive(filepath, vm=drive.vm)
34
target_drive.create_target(target_id, drive.fmt, drive.size)
35
- blockdev_backup(drive.vm, drive.name, target_id, sync, **kwargs)
36
+ blockdev_backup(drive.vm, drive.node, target_id, sync, **kwargs)
37
38
def reference_backup(drive, n, filepath):
39
log("--- Reference Backup #{:d} ---\n".format(n))
40
@@ -XXX,XX +XXX,XX @@ def perform_writes(drive, n):
41
pattern.offset,
42
pattern.size)
43
log(cmd)
44
- log(drive.vm.hmp_qemu_io(drive.name, cmd))
45
+ log(drive.vm.hmp_qemu_io(drive.node, cmd))
46
bitmaps = drive.vm.query_bitmaps()
47
log({'bitmaps': bitmaps}, indent=2)
48
log('')
49
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
50
}]
51
}
52
53
+ drive0.node = 'drive0'
54
vm.qmp_log('blockdev-add',
55
filters=[iotests.filter_qmp_testfiles],
56
- node_name="drive0",
57
+ node_name=drive0.node,
58
driver=drive0.fmt,
59
file=file_config)
60
- drive0.node = 'drive0'
61
- drive0.device = 'device0'
62
# Use share-rw to allow writes directly to the node;
63
# The anonymous block-backend for this configuration prevents us
64
# from using HMP's qemu-io commands to address the device.
65
- vm.qmp_log("device_add", id=drive0.device,
66
- drive=drive0.name, driver="scsi-hd",
67
+ vm.qmp_log("device_add", id='device0',
68
+ drive=drive0.node, driver="scsi-hd",
69
share_rw=True)
70
log('')
71
72
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
73
perform_writes(drive0, 0)
74
reference_backup(drive0, 0, fbackup0)
75
log('--- Add Bitmap ---\n')
76
- vm.qmp_log("block-dirty-bitmap-add", node=drive0.name,
77
+ vm.qmp_log("block-dirty-bitmap-add", node=drive0.node,
78
name="bitmap0", granularity=GRANULARITY)
79
log('')
80
ebitmap = EmulatedBitmap()
81
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
82
# 1 - Test Backup (w/ Optional induced failure)
83
if failure == 'intermediate':
84
# Activate blkdebug induced failure for second-to-next read
85
- log(vm.hmp_qemu_io(drive0.name, 'flush'))
86
+ log(vm.hmp_qemu_io(drive0.node, 'flush'))
87
log('')
88
job = backup(drive0, 1, bsync1, msync_mode,
89
bitmap="bitmap0", bitmap_mode=bsync_mode)
90
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
91
92
log('--- Cleanup ---\n')
93
vm.qmp_log("block-dirty-bitmap-remove",
94
- node=drive0.name, name="bitmap0")
95
+ node=drive0.node, name="bitmap0")
96
bitmaps = vm.query_bitmaps()
97
log({'bitmaps': bitmaps}, indent=2)
98
vm.shutdown()
99
@@ -XXX,XX +XXX,XX @@ def test_backup_api():
100
'filename': drive0.path
101
}
102
103
+ drive0.node = 'drive0'
104
vm.qmp_log('blockdev-add',
105
filters=[iotests.filter_qmp_testfiles],
106
- node_name="drive0",
107
+ node_name=drive0.node,
108
driver=drive0.fmt,
109
file=file_config)
110
- drive0.node = 'drive0'
111
- drive0.device = 'device0'
112
- vm.qmp_log("device_add", id=drive0.device,
113
- drive=drive0.name, driver="scsi-hd")
114
+ vm.qmp_log("device_add", id='device0',
115
+ drive=drive0.node, driver="scsi-hd")
116
log('')
117
118
target0 = Drive(backup_path, vm=vm)
119
target0.create_target("backup_target", drive0.fmt, drive0.size)
120
log('')
121
122
- vm.qmp_log("block-dirty-bitmap-add", node=drive0.name,
123
+ vm.qmp_log("block-dirty-bitmap-add", node=drive0.node,
124
name="bitmap0", granularity=GRANULARITY)
125
log('')
126
127
@@ -XXX,XX +XXX,XX @@ def test_backup_api():
128
log("-- Sync mode {:s} tests --\n".format(sync_mode))
129
for bitmap in (None, 'bitmap404', 'bitmap0'):
130
for policy in error_cases[sync_mode][bitmap]:
131
- blockdev_backup(drive0.vm, drive0.name, "backup_target",
132
+ blockdev_backup(drive0.vm, drive0.node, "backup_target",
133
sync_mode, job_id='api_job',
134
bitmap=bitmap, bitmap_mode=policy)
135
log('')
136
--
137
2.21.0
138
139
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
SCSI devices are unused in test, drop them.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20190920142056.12778-12-vsementsov@virtuozzo.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/257 | 8 -------
11
tests/qemu-iotests/257.out | 44 --------------------------------------
12
2 files changed, 52 deletions(-)
13
14
diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/257
17
+++ b/tests/qemu-iotests/257
18
@@ -XXX,XX +XXX,XX @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
19
node_name=drive0.node,
20
driver=drive0.fmt,
21
file=file_config)
22
- # Use share-rw to allow writes directly to the node;
23
- # The anonymous block-backend for this configuration prevents us
24
- # from using HMP's qemu-io commands to address the device.
25
- vm.qmp_log("device_add", id='device0',
26
- drive=drive0.node, driver="scsi-hd",
27
- share_rw=True)
28
log('')
29
30
# 0 - Writes and Reference Backup
31
@@ -XXX,XX +XXX,XX @@ def test_backup_api():
32
node_name=drive0.node,
33
driver=drive0.fmt,
34
file=file_config)
35
- vm.qmp_log("device_add", id='device0',
36
- drive=drive0.node, driver="scsi-hd")
37
log('')
38
39
target0 = Drive(backup_path, vm=vm)
40
diff --git a/tests/qemu-iotests/257.out b/tests/qemu-iotests/257.out
41
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/qemu-iotests/257.out
43
+++ b/tests/qemu-iotests/257.out
44
@@ -XXX,XX +XXX,XX @@
45
46
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
47
{"return": {}}
48
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
49
-{"return": {}}
50
51
--- Write #0 ---
52
53
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
54
55
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "blkdebug", "image": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "inject-error": [{"errno": 5, "event": "read_aio", "immediately": false, "once": true, "state": 3}], "set-state": [{"event": "flush_to_disk", "new-state": 2, "state": 1}, {"event": "read_aio", "new-state": 3, "state": 2}]}, "node-name": "drive0"}}
56
{"return": {}}
57
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
58
-{"return": {}}
59
60
--- Write #0 ---
61
62
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
63
64
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
65
{"return": {}}
66
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
67
-{"return": {}}
68
69
--- Write #0 ---
70
71
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
72
73
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
74
{"return": {}}
75
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
76
-{"return": {}}
77
78
--- Write #0 ---
79
80
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
81
82
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "blkdebug", "image": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "inject-error": [{"errno": 5, "event": "read_aio", "immediately": false, "once": true, "state": 3}], "set-state": [{"event": "flush_to_disk", "new-state": 2, "state": 1}, {"event": "read_aio", "new-state": 3, "state": 2}]}, "node-name": "drive0"}}
83
{"return": {}}
84
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
85
-{"return": {}}
86
87
--- Write #0 ---
88
89
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
90
91
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
92
{"return": {}}
93
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
94
-{"return": {}}
95
96
--- Write #0 ---
97
98
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
99
100
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
101
{"return": {}}
102
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
103
-{"return": {}}
104
105
--- Write #0 ---
106
107
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
108
109
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "blkdebug", "image": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "inject-error": [{"errno": 5, "event": "read_aio", "immediately": false, "once": true, "state": 3}], "set-state": [{"event": "flush_to_disk", "new-state": 2, "state": 1}, {"event": "read_aio", "new-state": 3, "state": 2}]}, "node-name": "drive0"}}
110
{"return": {}}
111
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
112
-{"return": {}}
113
114
--- Write #0 ---
115
116
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
117
118
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
119
{"return": {}}
120
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
121
-{"return": {}}
122
123
--- Write #0 ---
124
125
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
126
127
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
128
{"return": {}}
129
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
130
-{"return": {}}
131
132
--- Write #0 ---
133
134
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
135
136
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "blkdebug", "image": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "inject-error": [{"errno": 5, "event": "read_aio", "immediately": false, "once": true, "state": 3}], "set-state": [{"event": "flush_to_disk", "new-state": 2, "state": 1}, {"event": "read_aio", "new-state": 3, "state": 2}]}, "node-name": "drive0"}}
137
{"return": {}}
138
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
139
-{"return": {}}
140
141
--- Write #0 ---
142
143
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
144
145
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
146
{"return": {}}
147
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
148
-{"return": {}}
149
150
--- Write #0 ---
151
152
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
153
154
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
155
{"return": {}}
156
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
157
-{"return": {}}
158
159
--- Write #0 ---
160
161
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
162
163
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "blkdebug", "image": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "inject-error": [{"errno": 5, "event": "read_aio", "immediately": false, "once": true, "state": 3}], "set-state": [{"event": "flush_to_disk", "new-state": 2, "state": 1}, {"event": "read_aio", "new-state": 3, "state": 2}]}, "node-name": "drive0"}}
164
{"return": {}}
165
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
166
-{"return": {}}
167
168
--- Write #0 ---
169
170
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
171
172
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
173
{"return": {}}
174
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
175
-{"return": {}}
176
177
--- Write #0 ---
178
179
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
180
181
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
182
{"return": {}}
183
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
184
-{"return": {}}
185
186
--- Write #0 ---
187
188
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
189
190
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "blkdebug", "image": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "inject-error": [{"errno": 5, "event": "read_aio", "immediately": false, "once": true, "state": 3}], "set-state": [{"event": "flush_to_disk", "new-state": 2, "state": 1}, {"event": "read_aio", "new-state": 3, "state": 2}]}, "node-name": "drive0"}}
191
{"return": {}}
192
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
193
-{"return": {}}
194
195
--- Write #0 ---
196
197
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
198
199
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
200
{"return": {}}
201
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
202
-{"return": {}}
203
204
--- Write #0 ---
205
206
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
207
208
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
209
{"return": {}}
210
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
211
-{"return": {}}
212
213
--- Write #0 ---
214
215
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
216
217
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "blkdebug", "image": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "inject-error": [{"errno": 5, "event": "read_aio", "immediately": false, "once": true, "state": 3}], "set-state": [{"event": "flush_to_disk", "new-state": 2, "state": 1}, {"event": "read_aio", "new-state": 3, "state": 2}]}, "node-name": "drive0"}}
218
{"return": {}}
219
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
220
-{"return": {}}
221
222
--- Write #0 ---
223
224
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
225
226
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
227
{"return": {}}
228
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0", "share-rw": true}}
229
-{"return": {}}
230
231
--- Write #0 ---
232
233
@@ -XXX,XX +XXX,XX @@ qemu_img compare "TEST_DIR/PID-img" "TEST_DIR/PID-fbackup2" ==> Identical, OK!
234
235
{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-img"}, "node-name": "drive0"}}
236
{"return": {}}
237
-{"execute": "device_add", "arguments": {"drive": "drive0", "driver": "scsi-hd", "id": "device0"}}
238
-{"return": {}}
239
240
{}
241
{"execute": "job-dismiss", "arguments": {"id": "bdc-file-job"}}
242
--
243
2.21.0
244
245
diff view generated by jsdifflib
Deleted patch
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
2
1
3
Make the stat fields definition slightly more readable.
4
Also reorder total_time_ns stats read-write-flush as done elsewhere.
5
Cosmetic change only.
6
7
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Message-id: 20190923121737.83281-2-anton.nefedov@virtuozzo.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
qapi/block-core.json | 26 +++++++++++++++-----------
14
1 file changed, 15 insertions(+), 11 deletions(-)
15
16
diff --git a/qapi/block-core.json b/qapi/block-core.json
17
index XXXXXXX..XXXXXXX 100644
18
--- a/qapi/block-core.json
19
+++ b/qapi/block-core.json
20
@@ -XXX,XX +XXX,XX @@
21
# @flush_operations: The number of cache flush operations performed by the
22
# device (since 0.15.0)
23
#
24
-# @flush_total_time_ns: Total time spend on cache flushes in nano-seconds
25
-# (since 0.15.0).
26
+# @rd_total_time_ns: Total time spent on reads in nanoseconds (since 0.15.0).
27
#
28
-# @wr_total_time_ns: Total time spend on writes in nano-seconds (since 0.15.0).
29
+# @wr_total_time_ns: Total time spent on writes in nanoseconds (since 0.15.0).
30
#
31
-# @rd_total_time_ns: Total_time_spend on reads in nano-seconds (since 0.15.0).
32
+# @flush_total_time_ns: Total time spent on cache flushes in nanoseconds
33
+# (since 0.15.0).
34
#
35
# @wr_highest_offset: The offset after the greatest byte written to the
36
# device. The intended use of this information is for
37
@@ -XXX,XX +XXX,XX @@
38
# Since: 0.14.0
39
##
40
{ 'struct': 'BlockDeviceStats',
41
- 'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'rd_operations': 'int',
42
- 'wr_operations': 'int', 'flush_operations': 'int',
43
- 'flush_total_time_ns': 'int', 'wr_total_time_ns': 'int',
44
- 'rd_total_time_ns': 'int', 'wr_highest_offset': 'int',
45
- 'rd_merged': 'int', 'wr_merged': 'int', '*idle_time_ns': 'int',
46
+ 'data': {'rd_bytes': 'int', 'wr_bytes': 'int',
47
+ 'rd_operations': 'int', 'wr_operations': 'int',
48
+ 'flush_operations': 'int',
49
+ 'rd_total_time_ns': 'int', 'wr_total_time_ns': 'int',
50
+ 'flush_total_time_ns': 'int',
51
+ 'wr_highest_offset': 'int',
52
+ 'rd_merged': 'int', 'wr_merged': 'int',
53
+ '*idle_time_ns': 'int',
54
'failed_rd_operations': 'int', 'failed_wr_operations': 'int',
55
- 'failed_flush_operations': 'int', 'invalid_rd_operations': 'int',
56
- 'invalid_wr_operations': 'int', 'invalid_flush_operations': 'int',
57
+ 'failed_flush_operations': 'int',
58
+ 'invalid_rd_operations': 'int', 'invalid_wr_operations': 'int',
59
+ 'invalid_flush_operations': 'int',
60
'account_invalid': 'bool', 'account_failed': 'bool',
61
'timed_stats': ['BlockDeviceTimedStats'],
62
'*rd_latency_histogram': 'BlockLatencyHistogramInfo',
63
--
64
2.21.0
65
66
diff view generated by jsdifflib
Deleted patch
1
From: Anton Nefedov <anton.nefedov@virtuozzo.com>
2
1
3
Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Message-id: 20190923121737.83281-5-anton.nefedov@virtuozzo.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
hw/ide/core.c | 12 ++++++++++++
9
1 file changed, 12 insertions(+)
10
11
diff --git a/hw/ide/core.c b/hw/ide/core.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/ide/core.c
14
+++ b/hw/ide/core.c
15
@@ -XXX,XX +XXX,XX @@ static void ide_issue_trim_cb(void *opaque, int ret)
16
TrimAIOCB *iocb = opaque;
17
IDEState *s = iocb->s;
18
19
+ if (iocb->i >= 0) {
20
+ if (ret >= 0) {
21
+ block_acct_done(blk_get_stats(s->blk), &s->acct);
22
+ } else {
23
+ block_acct_failed(blk_get_stats(s->blk), &s->acct);
24
+ }
25
+ }
26
+
27
if (ret >= 0) {
28
while (iocb->j < iocb->qiov->niov) {
29
int j = iocb->j;
30
@@ -XXX,XX +XXX,XX @@ static void ide_issue_trim_cb(void *opaque, int ret)
31
}
32
33
if (!ide_sect_range_ok(s, sector, count)) {
34
+ block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_UNMAP);
35
iocb->ret = -EINVAL;
36
goto done;
37
}
38
39
+ block_acct_start(blk_get_stats(s->blk), &s->acct,
40
+ count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
41
+
42
/* Got an entry! Submit and exit. */
43
iocb->aiocb = blk_aio_pdiscard(s->blk,
44
sector << BDRV_SECTOR_BITS,
45
--
46
2.21.0
47
48
diff view generated by jsdifflib
Deleted patch
1
If we use growth_mode = metadata, it is very much possible that the file
2
uses more disk space after we have written something to the added area.
3
We did indeed want to test for this case, but unfortunately we evidently
4
just copied the code from the "Test creation preallocation" section and
5
forgot to replace "$create_mode" by "$growth_mode".
6
1
7
We never noticed because we only read the first number from qemu-img
8
info's "disk size" output -- and that is effectively useless, because
9
qemu-img prints a human-readable value (which generally includes a
10
decimal point). That will be fixed in the patch after the next one.
11
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20190925183231.11196-2-mreitz@redhat.com
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/125 | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/125
23
+++ b/tests/qemu-iotests/125
24
@@ -XXX,XX +XXX,XX @@ for GROWTH_SIZE in 16 48 80; do
25
if [ $file_length_2 -gt $file_length_1 ]; then
26
echo "ERROR (grow): Image length has grown from $file_length_1 to $file_length_2"
27
fi
28
- if [ $create_mode != metadata ]; then
29
+ if [ $growth_mode != metadata ]; then
30
# The host size should not have grown either
31
if [ $host_size_2 -gt $host_size_1 ]; then
32
echo "ERROR (grow): Host size has grown from $host_size_1 to $host_size_2"
33
--
34
2.21.0
35
36
diff view generated by jsdifflib
Deleted patch
1
And by that I mean all XFS versions, as far as I can tell. All details
2
are in the comment below.
3
1
4
We never noticed this problem because we only read the first number from
5
qemu-img info's "disk size" output -- and that is effectively useless,
6
because qemu-img prints a human-readable value (which generally includes
7
a decimal point). That will be fixed in the next patch.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Message-id: 20190925183231.11196-3-mreitz@redhat.com
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
tests/qemu-iotests/125 | 40 ++++++++++++++++++++++++++++++++++++++++
15
1 file changed, 40 insertions(+)
16
17
diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/125
20
+++ b/tests/qemu-iotests/125
21
@@ -XXX,XX +XXX,XX @@ if [ -z "$TEST_IMG_FILE" ]; then
22
TEST_IMG_FILE=$TEST_IMG
23
fi
24
25
+# Test whether we are running on a broken XFS version. There is this
26
+# bug:
27
+
28
+# $ rm -f foo
29
+# $ touch foo
30
+# $ block_size=4096 # Your FS's block size
31
+# $ fallocate -o $((block_size / 2)) -l $block_size foo
32
+# $ LANG=C xfs_bmap foo | grep hole
33
+# 1: [8..15]: hole
34
+#
35
+# The problem is that the XFS driver rounds down the offset and
36
+# rounds up the length to the block size, but independently. As
37
+# such, it only allocates the first block in the example above,
38
+# even though it should allocate the first two blocks (because our
39
+# request is to fallocate something that touches both the first
40
+# two blocks).
41
+#
42
+# This means that when you then write to the beginning of the
43
+# second block, the disk usage of the first two blocks grows.
44
+#
45
+# That is precisely what fallocate() promises, though: That when you
46
+# write to an area that you have fallocated, no new blocks will have
47
+# to be allocated.
48
+
49
+touch "$TEST_IMG_FILE"
50
+# Assuming there is no FS with a block size greater than 64k
51
+fallocate -o 65535 -l 2 "$TEST_IMG_FILE"
52
+len0=$(get_image_size_on_host)
53
+
54
+# Write to something that in theory we have just fallocated
55
+# (Thus, the on-disk size should not increase)
56
+poke_file "$TEST_IMG_FILE" 65536 42
57
+len1=$(get_image_size_on_host)
58
+
59
+if [ $len1 -gt $len0 ]; then
60
+ _notrun "the test filesystem's fallocate() is broken"
61
+fi
62
+
63
+rm -f "$TEST_IMG_FILE"
64
+
65
# Generally, we create some image with or without existing preallocation and
66
# then resize it. Then we write some data into the image and verify that its
67
# size does not change if we have used preallocation.
68
--
69
2.21.0
70
71
diff view generated by jsdifflib
Deleted patch
1
125 should not use qemu-img to get the on-disk image size, because that
2
reports it in a human-readable format that is useless to us. Just use
3
stat instead (like we do to get the image file length).
4
1
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20190925183231.11196-4-mreitz@redhat.com
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/125 | 3 +--
11
1 file changed, 1 insertion(+), 2 deletions(-)
12
13
diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/125
16
+++ b/tests/qemu-iotests/125
17
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
18
19
get_image_size_on_host()
20
{
21
- $QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep "disk size" \
22
- | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/'
23
+ echo $(($(stat -c '%b * %B' "$TEST_IMG_FILE")))
24
}
25
26
# get standard environment and filters
27
--
28
2.21.0
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Move synchronization mechanism to block-copy, to be able to use one
4
block-copy instance from backup job and backup-top filter in parallel.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-id: 20191001131409.14202-2-vsementsov@virtuozzo.com
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
include/block/block-copy.h | 8 ++++++
12
block/backup.c | 52 --------------------------------------
13
block/block-copy.c | 43 +++++++++++++++++++++++++++++++
14
3 files changed, 51 insertions(+), 52 deletions(-)
15
16
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-copy.h
19
+++ b/include/block/block-copy.h
20
@@ -XXX,XX +XXX,XX @@
21
22
#include "block/block.h"
23
24
+typedef struct BlockCopyInFlightReq {
25
+ int64_t start_byte;
26
+ int64_t end_byte;
27
+ QLIST_ENTRY(BlockCopyInFlightReq) list;
28
+ CoQueue wait_queue; /* coroutines blocked on this request */
29
+} BlockCopyInFlightReq;
30
+
31
typedef void (*ProgressBytesCallbackFunc)(int64_t bytes, void *opaque);
32
typedef void (*ProgressResetCallbackFunc)(void *opaque);
33
typedef struct BlockCopyState {
34
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState {
35
bool use_copy_range;
36
int64_t copy_range_size;
37
uint64_t len;
38
+ QLIST_HEAD(, BlockCopyInFlightReq) inflight_reqs;
39
40
BdrvRequestFlags write_flags;
41
42
diff --git a/block/backup.c b/block/backup.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/block/backup.c
45
+++ b/block/backup.c
46
@@ -XXX,XX +XXX,XX @@
47
48
#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
49
50
-typedef struct CowRequest {
51
- int64_t start_byte;
52
- int64_t end_byte;
53
- QLIST_ENTRY(CowRequest) list;
54
- CoQueue wait_queue; /* coroutines blocked on this request */
55
-} CowRequest;
56
-
57
typedef struct BackupBlockJob {
58
BlockJob common;
59
BlockDriverState *source_bs;
60
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
61
uint64_t bytes_read;
62
int64_t cluster_size;
63
NotifierWithReturn before_write;
64
- QLIST_HEAD(, CowRequest) inflight_reqs;
65
66
BlockCopyState *bcs;
67
} BackupBlockJob;
68
69
static const BlockJobDriver backup_job_driver;
70
71
-/* See if in-flight requests overlap and wait for them to complete */
72
-static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job,
73
- int64_t start,
74
- int64_t end)
75
-{
76
- CowRequest *req;
77
- bool retry;
78
-
79
- do {
80
- retry = false;
81
- QLIST_FOREACH(req, &job->inflight_reqs, list) {
82
- if (end > req->start_byte && start < req->end_byte) {
83
- qemu_co_queue_wait(&req->wait_queue, NULL);
84
- retry = true;
85
- break;
86
- }
87
- }
88
- } while (retry);
89
-}
90
-
91
-/* Keep track of an in-flight request */
92
-static void cow_request_begin(CowRequest *req, BackupBlockJob *job,
93
- int64_t start, int64_t end)
94
-{
95
- req->start_byte = start;
96
- req->end_byte = end;
97
- qemu_co_queue_init(&req->wait_queue);
98
- QLIST_INSERT_HEAD(&job->inflight_reqs, req, list);
99
-}
100
-
101
-/* Forget about a completed request */
102
-static void cow_request_end(CowRequest *req)
103
-{
104
- QLIST_REMOVE(req, list);
105
- qemu_co_queue_restart_all(&req->wait_queue);
106
-}
107
-
108
static void backup_progress_bytes_callback(int64_t bytes, void *opaque)
109
{
110
BackupBlockJob *s = opaque;
111
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
112
bool *error_is_read,
113
bool is_write_notifier)
114
{
115
- CowRequest cow_request;
116
int ret = 0;
117
int64_t start, end; /* bytes */
118
119
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
120
121
trace_backup_do_cow_enter(job, start, offset, bytes);
122
123
- wait_for_overlapping_requests(job, start, end);
124
- cow_request_begin(&cow_request, job, start, end);
125
-
126
ret = block_copy(job->bcs, start, end - start, error_is_read,
127
is_write_notifier);
128
129
- cow_request_end(&cow_request);
130
-
131
trace_backup_do_cow_return(job, offset, bytes, ret);
132
133
qemu_co_rwlock_unlock(&job->flush_rwlock);
134
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run(Job *job, Error **errp)
135
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
136
int ret = 0;
137
138
- QLIST_INIT(&s->inflight_reqs);
139
qemu_co_rwlock_init(&s->flush_rwlock);
140
141
backup_init_copy_bitmap(s);
142
diff --git a/block/block-copy.c b/block/block-copy.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/block/block-copy.c
145
+++ b/block/block-copy.c
146
@@ -XXX,XX +XXX,XX @@
147
#include "block/block-copy.h"
148
#include "sysemu/block-backend.h"
149
150
+static void coroutine_fn block_copy_wait_inflight_reqs(BlockCopyState *s,
151
+ int64_t start,
152
+ int64_t end)
153
+{
154
+ BlockCopyInFlightReq *req;
155
+ bool waited;
156
+
157
+ do {
158
+ waited = false;
159
+ QLIST_FOREACH(req, &s->inflight_reqs, list) {
160
+ if (end > req->start_byte && start < req->end_byte) {
161
+ qemu_co_queue_wait(&req->wait_queue, NULL);
162
+ waited = true;
163
+ break;
164
+ }
165
+ }
166
+ } while (waited);
167
+}
168
+
169
+static void block_copy_inflight_req_begin(BlockCopyState *s,
170
+ BlockCopyInFlightReq *req,
171
+ int64_t start, int64_t end)
172
+{
173
+ req->start_byte = start;
174
+ req->end_byte = end;
175
+ qemu_co_queue_init(&req->wait_queue);
176
+ QLIST_INSERT_HEAD(&s->inflight_reqs, req, list);
177
+}
178
+
179
+static void coroutine_fn block_copy_inflight_req_end(BlockCopyInFlightReq *req)
180
+{
181
+ QLIST_REMOVE(req, list);
182
+ qemu_co_queue_restart_all(&req->wait_queue);
183
+}
184
+
185
void block_copy_state_free(BlockCopyState *s)
186
{
187
if (!s) {
188
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(
189
s->use_copy_range =
190
!(write_flags & BDRV_REQ_WRITE_COMPRESSED) && s->copy_range_size > 0;
191
192
+ QLIST_INIT(&s->inflight_reqs);
193
+
194
/*
195
* We just allow aio context change on our block backends. block_copy() user
196
* (now it's only backup) is responsible for source and target being in same
197
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
198
int64_t end = bytes + start; /* bytes */
199
void *bounce_buffer = NULL;
200
int64_t status_bytes;
201
+ BlockCopyInFlightReq req;
202
203
/*
204
* block_copy() user is responsible for keeping source and target in same
205
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
206
assert(QEMU_IS_ALIGNED(start, s->cluster_size));
207
assert(QEMU_IS_ALIGNED(end, s->cluster_size));
208
209
+ block_copy_wait_inflight_reqs(s, start, bytes);
210
+ block_copy_inflight_req_begin(s, &req, start, end);
211
+
212
while (start < end) {
213
int64_t dirty_end;
214
215
@@ -XXX,XX +XXX,XX @@ int coroutine_fn block_copy(BlockCopyState *s,
216
qemu_vfree(bounce_buffer);
217
}
218
219
+ block_copy_inflight_req_end(&req);
220
+
221
return ret;
222
}
223
--
224
2.21.0
225
226
diff view generated by jsdifflib